Mission 1.2 · Stage 1 — GitOps with Argo CD
Your First Application: Sync and Health
Goal: ShopLite's web Deployment and Service deployed by Argo CD from Git, with a deploy done purely by a commit.
By the end of this mission
- Write an Argo CD Application resource
- Read Sync status (Synced/OutOfSync) and Health status (Healthy/Progressing/Degraded)
- Deploy a new version with a Git commit, and roll back with git revert
- Use the argocd CLI to inspect diffs and history
Part 1
Understand it first
The Application resource
An Application connects a SOURCE (repo URL, revision, path, and how to render it) to a DESTINATION (cluster and namespace). Argo CD renders the source, compares it with what's live, and reports two independent statuses.
SYNC STATUS answers 'does the cluster match Git?' (Synced / OutOfSync). HEALTH STATUS answers 'is what's running actually working?' (Healthy, Progressing, Degraded, Missing, Suspended). An app can be Synced but Degraded: Git was applied perfectly, and the new pods crash. Health checks are built in for standard kinds (a Deployment is Healthy when its rollout completed) and can be customised in Lua for CRDs.
Part 2
Your project after this mission · 3 files change
- shoplite-gitops/
- apps/
- web/
- deployment.yamlnew
- service.yamlnew
- argocd/
- web-dev.yamlnew
- README.md
Part 3
Build it, step by step
- 1
Write the manifests
The same Deployment you wrote in the Kubernetes course, with probes and resources.
nginxdemos/hellostands in for the ShopLite web image; it shows its version in the page, so you can watch deploys happen.shoplite-gitops/apps/web/deployment.yamlwhole fileyaml apiVersion: apps/v1 kind: Deployment metadata: name: web labels: { app: web } spec: replicas: 2 selector: matchLabels: { app: web } template: metadata: labels: { app: web } spec: containers: - name: web image: nginxdemos/hello:0.3 ports: [{ containerPort: 80 }] readinessProbe: httpGet: { path: /, port: 80 } resources: requests: { cpu: 50m, memory: 32Mi } limits: { memory: 64Mi } - 2
And the Service
A ClusterIP Service in front of the pods.
shoplite-gitops/apps/web/service.yamlwhole fileyaml apiVersion: v1 kind: Service metadata: name: web spec: selector: { app: web } ports: [{ port: 80, targetPort: 80 }] - 3
Declare the Application
The Application itself is YAML too, and it lives in the same repo, so even 'what Argo CD manages' is in Git.
CreateNamespace=truelets Argo createshoplite-dev. There's noautomatedblock yet, so Argo will only report differences; you'll sync by hand first to see each step.shoplite-gitops/argocd/web-dev.yamlwhole fileyaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: web-dev namespace: argocd spec: project: default source: repoURL: https://github.com/<you>/shoplite-gitops.git targetRevision: main path: apps/web destination: server: https://kubernetes.default.svc namespace: shoplite-dev syncPolicy: syncOptions: - CreateNamespace=true - 4
Push, register, and sync
After this one-time
kubectl applyof the Application, you won't use kubectl to deploy again. Before the first sync, the app isOutOfSyncandMissing: Git has resources the cluster doesn't.terminal$ git add . && git commit -m 'web: initial deploy to dev' && git pushkubectl apply -f argocd/web-dev.yamlargocd app get web-dev | grep -E 'Sync Status|Health'argocd app sync web-devargocd app wait web-dev --health── expected output ──Sync Status: OutOfSync from main (a1b2c3d)Health Status: Missing...GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGEService shoplite-dev web Synced Healthy service/web createdapps Deployment shoplite-dev web Synced Progressing deployment.apps/web created...Health Status: Healthy - 5
Deploy by commit
Change the image tag in Git. That's the whole deploy. Argo polls repos every 3 minutes by default; a Git webhook to
/api/webhookmakes it near-instant.argocd app diffshows exactly what will change, liketerraform plan.terminal$ sed -i 's/hello:0.3/hello:0.4/' apps/web/deployment.yamlgit commit -am 'web: 0.3 → 0.4' && git pushargocd app diff web-dev --refreshargocd app sync web-dev && argocd app history web-dev── expected output ──===== apps/Deployment shoplite-dev/web ======< image: nginxdemos/hello:0.3> image: nginxdemos/hello:0.4...ID DATE REVISION0 2026-09-26 10:02:11 +0530 IST main (a1b2c3d)1 2026-09-26 10:09:47 +0530 IST main (d4e5f6a) - 6
Roll back the GitOps way
argocd app rollbackexists, but it makes the cluster differ from Git, and with auto-sync on (next mission) Argo would immediately undo it. The GitOps rollback isgit revert: history shows exactly who rolled back, when, and why.terminal$ git revert --no-edit HEAD && git pushargocd app sync web-devkubectl -n shoplite-dev get deploy web -o jsonpath='{.spec.template.spec.containers[0].image}'── expected output ──nginxdemos/hello:0.3
Checkpoint — you should now have
- ✓
argocd app get web-devshows Synced and Healthy. - ✓You deployed 0.4 and rolled back to 0.3 using only Git commits.
- ✓
argocd app history web-devlists each deploy with its Git revision.
Part 4
Break it on purpose
Make each change, run the command, and read the error before revealing the diagnosis. Recognising these messages on sight is what makes you fast on a real team. Undo the change afterwards.
Break #1
Synced but broken
Set the image to nginxdemos/hello:does-not-exist, commit, push, and sync.
Break #2
Point at a path that doesn't exist
Change the Application's path to apps/webb and apply it.
Part 5
Interview questions from this mission
What's the difference between Sync status and Health status in Argo CD?
How do you roll back in GitOps?