App → ECR → EKS via GitHub Actions

Build image, push to registry, deploy to Kubernetes — one pipeline. · ~45 min

Reviewed: ·Tested on: Kubernetes 1.29, Terraform 1.8, Ubuntu 22.04

If you're on Kubernetes 1.27 or older

  • Ingress: networking.k8s.io/v1 is required — v1beta1 removed in 1.22+
  • Pod Security: PodSecurityPolicy removed in 1.25 — use Pod Security Admission (PSA) labels
  • HPA v2 autoscaling/v2 is stable — check API version in manifests

If you're on Kubernetes 1.28

  • Sidecar containers (1.29+) change init-container ordering — review sidecar docs before upgrade
  • Verify metrics-server and HPA after control plane bump

If you're on Terraform 1.7 or older

  • S3 native locking (use_lockfile) differs from DynamoDB — don't mix backends mid-migration
  • Provider version constraints: run terraform init -upgrade after bump
  • terraform test (1.6+) replaces some external test harness patterns

1. Dockerfile + K8s manifests in repo

App code, Dockerfile, and k8s/ folder on main branch.

2. Add GitHub Actions workflow

name: Deploy
on:
  push:
    branches: [main]
permissions:
  id-token: write
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1
      - uses: aws-actions/amazon-ecr-login@v2
      - run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$GITHUB_SHA
      - run: kubectl apply -f k8s/
        env:
          KUBECONFIG: ${{ secrets.KUBECONFIG_DATA }}

3. Secrets in GitHub repo

Settings → Secrets: AWS_ROLE_ARN (OIDC), or AWS keys; KUBECONFIG_DATA base64; ECR registry vars.

4. Ingress + verify

kubectl rollout status deploy/<app> -n <ns>
kubectl get ingress -n <ns>
curl -I https://app.example.com/health

5. If deploy fails

Check Actions log → push auth → cluster access.