Lesson 14 GitOps with ArgoCD
Theme:

Lab 14 — Install ArgoCD on kind, deploy the URL shortener via App-of-Apps, prove drift detection and git-push deploys

Lesson 14 · Cloud Infrastructure & DevOps · ~60 min

Prereqs

The L13 lab must be complete: the URL shortener with HPA, PDB, and blue/green is working on your kind cluster. For the GitOps loop you need to be able to push to a git remote — fork the course repo to your own GitHub account and edit repoURL: in the ArgoCD manifests to point at your fork before applying. You also need the argocd CLI:

brew install argocd        # macOS
# or download from https://github.com/argoproj/argo-cd/releases/tag/v2.11.0
argocd version --client

Step 1 — Tear down the helm-installed app

We are about to install the same chart via ArgoCD. Starting clean shows the bootstrap order in the UI.

helm uninstall url-shortener -n url-shortener
kubectl delete namespace url-shortener
kubectl get ns url-shortener   # should return NotFound

Step 2 — Install ArgoCD

kubectl create namespace argocd
kubectl apply -n argocd \
  -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.11.0/manifests/install.yaml
kubectl -n argocd rollout status deploy/argocd-server --timeout=5m

Expected output: deployment "argocd-server" successfully rolled out.

Step 3 — Get the admin password and open the UI

kubectl -n argocd port-forward svc/argocd-server 8080:443 &
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath='{.data.password}' | base64 -d ; echo

Open https://localhost:8080 in your browser. Accept the self-signed cert. Log in as admin with the password above.

Step 4 — Edit repoURL in the ArgoCD manifests to your fork

Before applying, replace the <you> placeholder with your actual GitHub username across all manifests:

sed -i.bak 's|https://github.com/<you>/Claude_Lessons.git|https://github.com/YOURNAME/Claude_Lessons.git|g' \
  cloud-devops/sample-app/argocd/*.yaml \
  cloud-devops/sample-app/argocd/children/*.yaml
git diff
git add cloud-devops/sample-app/argocd/
git commit -m "lab(L14): point ArgoCD manifests at my fork"
git push origin main
ArgoCD polls the git remote. If the manifests still point at the placeholder URL, all Applications will fail to sync. Confirm your fork is public (or ArgoCD has credentials for a private repo).

Step 5 — Apply the App-of-Apps

kubectl apply -n argocd -f cloud-devops/sample-app/argocd/app-of-apps.yaml

In the UI: a single app-of-apps Application appears. Click it. Within a few seconds, child Applications appear in the list: cert-manager, ingress-nginx, kube-prometheus-stack, url-shortener. Watch the sync wave order — the wave −1 applications (cert-manager, ingress-nginx, kube-prometheus-stack) go Healthy before url-shortener (wave 0) starts syncing.

argocd login localhost:8080 --insecure
argocd app list
argocd app get url-shortener

Step 6 — Wait for everything Healthy

kubectl -n url-shortener rollout status deploy url-shortener-api-blue --timeout=10m
kubectl -n url-shortener get pods,svc,ingress,hpa,pdb
curl -sk https://localhost/

Confirm the same shape you had at the end of L13 — HPA present, PDB present, blue Deployment serving — just installed via ArgoCD instead of a manual helm upgrade.

Step 7 — Prove drift detection

Manually edit a Deployment outside of git:

kubectl -n url-shortener scale deploy url-shortener-api-blue --replicas=10
kubectl -n url-shortener get deploy url-shortener-api-blue
# DESIRED: 10  (for now)

Watch the UI: within ~3 minutes the url-shortener Application goes OutOfSync (yellow indicator). Then ArgoCD automatically reverts the change because automated.selfHeal: true is set. Confirm:

kubectl -n url-shortener get deploy url-shortener-api-blue
# DESIRED is back to 3 (or whatever values-prod.yaml says), not 10.

Now test the ignoreDifferences exception. Drive load against the API so the HPA scales it up:

# Drive load (adapt the host as needed)
for i in $(seq 1 200); do curl -sk https://localhost/s/any & done
kubectl -n url-shortener get hpa url-shortener-api --watch

The HPA scales replicas from 2 → N. Wait 3+ minutes. Confirm ArgoCD did not revert the replica count back to the git value — because /spec/replicas is in ignoreDifferences.

Step 8 — Deploy via git push

Edit cloud-devops/sample-app/helm/values-prod.yaml and change something visible, for example bump api.maxReplicas:

grep maxReplicas cloud-devops/sample-app/helm/values-prod.yaml
# Change the value, e.g. from 8 to 10
git add cloud-devops/sample-app/helm/values-prod.yaml
git commit -m "lab(L14): bump api maxReplicas to 10"
git push origin main

Within ~3 minutes ArgoCD detects the change in main, syncs, and updates the HPA. Watch the UI — url-shortener briefly goes OutOfSync then returns to Healthy. Confirm:

kubectl -n url-shortener get hpa url-shortener-api -o jsonpath='{.spec.maxReplicas}'
# 10

No kubectl edit. No helm upgrade. No SSH. Git push is the deploy.

Step 9 — Roll back via git revert

git revert HEAD --no-edit
git push origin main

ArgoCD picks up the revert commit and syncs. The HPA maxReplicas returns to its previous value. Confirm in the UI and via kubectl.

Step 10 — Optional: swap App-of-Apps for ApplicationSet

kubectl delete -n argocd -f cloud-devops/sample-app/argocd/app-of-apps.yaml
kubectl apply -n argocd -f cloud-devops/sample-app/argocd/appset-environments.yaml
argocd app list

Expect three Applications: url-shortener-dev, url-shortener-stage, url-shortener-prod. Each renders the same Helm chart with a different values file into a different namespace. If values-dev.yaml or values-stage.yaml do not exist yet, those Applications will be OutOfSync — create the missing files (or copy values.yaml) and push to fix.

Step 11 — Verify the full loop works end-to-end

What you should leave with

A kind cluster fully managed by ArgoCD: every Helm chart deployed via an Application, sync waves bootstrap the dependencies in order, drift is auto-corrected within 3 minutes, deploys are git pushes. This is the production shape.

Course wrap-up

You have built a 14-lesson path-of-a-feature deployment stack — container, Dockerfile design, multi-service builds, CI, scanning and signing, push-to-deploy, VM hosting, Terraform, Kubernetes, Helm, Ingress and TLS, observability, autoscaling, GitOps. The URL shortener is small; the platform around it is full-shape. The next move is your app. Pick one. Run through the same stack. Operate it for 30 days. Then re-read your own observability dashboards and decide what to refactor.

Troubleshooting