Project 9 of 12 · project brief
GitOps Delivery: GitHub Actions → ECR → Argo CD → EKS
CI builds and pushes images; a config repo is the source of truth; Argo CD deploys to dev automatically and to prod by pull request, with canary releases.
The scenario
Deploys to EKS (Project 8) still happen from a laptop with helm upgrade. Nobody can tell exactly what's running in prod or who changed it. Your brief: a GitOps workflow where Git is the only way to change the cluster, CI never holds cluster credentials, prod promotion is a reviewed PR, and releases roll out as canaries.
Before you start
- GitOps course
Argo CD, overlays, secrets, Argo Rollouts, ApplicationSets.
- CI/CD · Least privilege with OIDC
Pushing to ECR without long-lived keys.
Stack
Target architecture
Deliverables and requirements
You will hand in
- App repo workflow: test, build, push to ECR via OIDC, bump the dev tag in the config repo
- Config repo with base + dev/prod overlays (or Helm values) and an ApplicationSet
- Argo CD with SSO/RBAC basics, auto-sync + self-heal in dev
- Prod API as an Argo Rollout with canary steps and automated analysis
Functional
- Merging to main deploys to dev within 5 minutes without human action
- Prod changes only through an approved PR in the config repo
- A failing canary rolls back automatically
Non-functional
- CI has no kubeconfig or cluster credentials
- Every deployed version traceable to a commit and an image digest
- Manual
kubectlchanges are reverted by self-heal
Milestones
- 1
CI with OIDC and ECR
Done when: Images pushed from GitHub Actions without stored AWS keys.
- IAM OIDC provider + role trusting only
repo:<org>/shoplite-api:ref:refs/heads/main - Workflow: test → build → push
ecr/shoplite-api:sha-<sha> - Enable ECR image scanning and immutable tags
Prove it works
terminal$ aws ecr describe-images --repository-name shoplite-api --query 'sort_by(imageDetails,&imagePushedAt)[-1].imageTags'── expected output ──["sha-3f2a1c9"] - IAM OIDC provider + role trusting only
- 2
Config repo and Argo CD
Done when: Argo CD deploying dev from the config repo.
- Install Argo CD (Helm, via Terraform or a bootstrap script)
- Config repo with overlays; ApplicationSet generating an app per env
- Dev:
automated: { prune: true, selfHeal: true }
Prove it works
terminal$ argocd app list── expected output ──NAME SYNC STATUS HEALTH STATUSapi-dev Synced Healthyapi-prod Synced Healthy - 3
Automated dev deploys, PR-based prod
Done when: CI bumps dev; promotion to prod is a reviewed PR.
- CI job commits the new tag to
envs/devusing a scoped token - CODEOWNERS + branch protection on
envs/prod/** - A small workflow (or manual step) to open the promotion PR with the same tag
Prove it works
terminal$ git log --oneline -3 -- envs/── expected output ──a91c2e7 api(prod): promote sha-3f2a1c9 (#41)6b0d8f3 api(dev): deploy sha-3f2a1c9 from shoplite-api2c4e1a0 api(dev): deploy sha-91be7d0 from shoplite-api - CI job commits the new tag to
- 4
Canary with analysis
Done when: Prod releases shift traffic gradually and abort on errors.
- Install Argo Rollouts; convert the prod API Deployment to a Rollout
- Steps 10% → 30% → 60% → 100% with pauses
- AnalysisTemplate on success rate from Prometheus; test with a deliberately faulty image
Prove it works
terminal$ kubectl argo rollouts get rollout api -n shoplite-prod | head -4── expected output ──Name: apiStatus: ✖ DegradedMessage: RolloutAborted: Metric "success-rate" assessed FailedImages: ...sha-3f2a1c9 (stable)
Would you run this in production?
- ☐Git is the only change path; self-heal on
- ☐No cluster credentials in CI; OIDC everywhere
- ☐Immutable, traceable image tags
- ☐Secrets via External Secrets, never in Git
- ☐Argo CD with SSO, RBAC, and notifications on degraded apps
Stretch goals
- Preview environments per PR with the ApplicationSet pull-request generator
- Sign images in CI and verify signatures with Kyverno before deploy (Project 11)
- Automate promotion with Kargo
Show it off
Résumé bullet
Implemented GitOps delivery to EKS with GitHub Actions (OIDC → ECR), Argo CD ApplicationSets, PR-based promotion, and Argo Rollouts canaries with Prometheus analysis and automatic rollback; removed all cluster credentials from CI.
Demo script
- Merge a change and watch it reach dev with no clicks
kubectl editin dev and watch self-heal revert it- Ship a faulty image to prod and watch the canary abort
Interview questions about this project
How does your pipeline get a change from commit to production?
What are the security benefits of GitOps?