LAB 11 – Progressive delivery with Argo Rollouts¶
Story: Last month a bad checkout release hit 100 % of customers in one go. From now on a new checkout version gets 25 % of the pods first – and only a human (or a metric) lets it go further.
| Duration | ~45 min |
| You create | argocd/checkout.yaml; you edit apps/checkout/rollout.yaml |
| Solution | solutions/LAB11/ (or ./bin/lab catchup 11) |
Argo CD decides what runs (desired state from Git). Argo Rollouts decides how a new version replaces the old one. A Rollout is a Deployment with a strategy:
| Strategy | How |
|---|---|
| Canary | shift a growing share of pods/traffic to the new version, pause between steps |
| Blue-green | start the new version next to the old one, switch the Service at once |
| + Analysis | query Prometheus/Datadog/a web endpoint/a Job between steps – abort automatically on bad results |
| + Traffic routing | exact percentages via an ingress/service mesh (Traefik, NGINX, Istio, Gateway API plugin…) – without it, the split follows the pod ratio |
The controller was installed in LAB08 (argo-rollouts app).
Step 1 – Deploy checkout¶
Read apps/checkout/rollout.yaml: 4 replicas, steps 25 % → pause (indefinitely) → 50 % → 30 s → 75 % → 30 s → 100 %.
cd work/gitops
cat > argocd/checkout.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: checkout
namespace: argocd
spec:
project: parcelpal
source:
repoURL: http://gitea:3000/student/gitops.git
targetRevision: main
path: apps/checkout
destination:
server: https://kubernetes.default.svc
namespace: checkout
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
git add argocd/checkout.yaml && git commit -m "checkout app" && git push
✅ Checkpoint: the checkout app is Healthy; http://checkout.localtest.me is green, version 6.16.0.
The first rollout goes straight to 100 % – there is no old version to protect.
Step 2 – A canary release¶
In a second terminal keep an eye on the versions:
while true; do curl -s http://checkout.localtest.me/version | grep -o '"version": "[^"]*"'; sleep 1; done
Release 6.17.0 in orange:
sed -i -e 's#podinfo:6.16.0#podinfo:6.17.0#' -e 's/"#2e8b57"/"#ff8c00"/' apps/checkout/rollout.yaml
git commit -am "checkout 6.17.0" && git push
kubectl argo rollouts get rollout checkout -n checkout --watch # Ctrl+C
✅ Checkpoint: 1 of 4 pods runs 6.17.0 (25 %), the rollout is Paused, and the Argo CD app health shows Suspended. About every fourth answer in the loop says 6.17.0.
Happy with the canary? Promote it:
…or in Argo CD: open the Rollout resource → ⋮ → Resume (resource actions).
✅ Checkpoint: 50 % → 75 % → 100 % with 30 s pauses; finally all answers are 6.17.0, the app is Healthy.
Step 3 – Abort a bad release¶
Release a version that cannot start:
sed -i 's#podinfo:6.17.0#podinfo:6.99.0#' apps/checkout/rollout.yaml
git commit -am "checkout 6.99.0" && git push
kubectl argo rollouts get rollout checkout -n checkout
The canary pod is stuck in ImagePullBackOff – but 3 of 4 pods still serve 6.17.0. Abort:
✅ Checkpoint: the stable version is scaled back to 4 pods; the rollout is Degraded (aborted) and so is the Argo CD app.
Now fix the source of truth – Git still says 6.99.0:
✅ Checkpoint: the rollout returns to Healthy on 6.17.0 without a new canary – it is the stable version already.
Never fix a rollout only with
kubectl argo rollouts undowhile Argo CD watches: self-heal would bring the bad spec back. Revert in Git.
Step 4 – Dashboard (optional)¶
Bonus¶
- Automated analysis: add an
AnalysisTemplatewith thewebprovider that callshttp://checkout.checkout.svc/healthzand a step- analysis: { templates: [{ templateName: health }] }aftersetWeight: 25. - Blue-green: replace
canarywithblueGreen: { activeService: checkout, autoPromotionEnabled: false }(and a preview Service). - Why did we not need a
Deploymentat all? Look atkubectl -n checkout get rs– who owns the ReplicaSets?
Troubleshooting¶
| Symptom | Likely cause |
|---|---|
no matches for kind "Rollout" |
the argo-rollouts app (LAB08) is missing – the CRD is not installed |
| app stays Progressing during the pause | expected for timed pauses; an indefinite pause shows Suspended |
promote does nothing |
the rollout is not paused, or you are in the wrong namespace (-n checkout) |
| traffic split not exactly 25 % | without traffic routing the split follows the ratio of ready pods |
Files for this lab: Think-Cube/argocd-labs/labs/LAB11-progressive-delivery