Progressive Delivery (Argo Rollouts)
Canary deployments with automated traffic shifting, health analysis, and auto-rollback.
Time: ~20 minutes Difficulty: Advanced
Resources: This demo needs ~1GB RAM. Clean up other demos first:
task clean:all
What You Will Learn
Section titled “What You Will Learn”- Argo Rollouts: a drop-in replacement for Deployments with advanced rollout strategies
- Canary deployments: shift traffic gradually (10% -> 50% -> 100%)
- AnalysisTemplate: automated health checks that gate promotion
- Auto-rollback: bad deployments are automatically reverted
- The difference between a Deployment rolling update and a true canary
The Scenario
Section titled “The Scenario”Service ──> Argo Rollout (canary) ──> Stable ReplicaSet (90%) ──> Canary ReplicaSet (10%) | AnalysisRun checks health | Auto-promote or auto-rollbackVersion 1 serves “Stable” HTML. We trigger a v2 rollout that serves “Canary” HTML. Traffic shifts from 10% to 50% to 100%, with a health check running at each step. If the canary fails health checks, the rollout automatically rolls back.
Prerequisites
Section titled “Prerequisites”Install Argo Rollouts Controller
Section titled “Install Argo Rollouts Controller”kubectl create namespace argo-rollouts 2>/dev/null || truekubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yamlWait for the controller:
kubectl get pods -n argo-rollouts -wInstall the kubectl Plugin (optional but recommended)
Section titled “Install the kubectl Plugin (optional but recommended)”# Linux (amd64)curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64chmod +x kubectl-argo-rollouts-linux-amd64sudo mv kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
# macOS (arm64)# curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-darwin-arm64# chmod +x kubectl-argo-rollouts-darwin-arm64# sudo mv kubectl-argo-rollouts-darwin-arm64 /usr/local/bin/kubectl-argo-rolloutsVerify:
kubectl argo rollouts versionDeploy
Section titled “Deploy”Navigate to the demo directory:
cd demos/progressive-deliveryStep 1: Deploy Version 1 (Stable)
Section titled “Step 1: Deploy Version 1 (Stable)”kubectl apply -f manifests/namespace.yamlkubectl apply -f manifests/analysis-template.yamlkubectl apply -f manifests/service.yamlkubectl apply -f manifests/rollout.yamlWait for all pods:
kubectl get pods -n rollouts-demo -wCheck the rollout status:
kubectl argo rollouts get rollout canary-app -n rollouts-demoAll 4 replicas should show as Stable. Verify v1 is serving:
kubectl port-forward svc/canary-app-stable 8080:80 -n rollouts-demo &curl http://localhost:8080# <html><body><h1>Version 1 - Stable</h1>...kill %1Step 2: Trigger the Canary Rollout (v2)
Section titled “Step 2: Trigger the Canary Rollout (v2)”Apply the v2 manifest which changes the image and the HTML content:
kubectl apply -f manifests/rollout-v2.yamlImmediately watch the rollout:
kubectl argo rollouts get rollout canary-app -n rollouts-demo -wYou will see:
- 10% weight - 1 canary pod starts, AnalysisRun begins health checking
- 30s pause - traffic continues at 10% canary / 90% stable
- 50% weight - more canary pods are created
- 30s pause - traffic at 50/50
- 100% weight - canary becomes the new stable, old ReplicaSet scales down
Press Ctrl+C when the rollout completes.
Step 3: Verify the Canary During Rollout
Section titled “Step 3: Verify the Canary During Rollout”While the rollout is in progress (during a pause), check both services:
# Stable service - serves v1kubectl port-forward svc/canary-app-stable 8080:80 -n rollouts-demo &curl http://localhost:8080kill %1
# Canary service - serves v2kubectl port-forward svc/canary-app-canary 8081:80 -n rollouts-demo &curl http://localhost:8081kill %1Step 4: Check AnalysisRun Results
Section titled “Step 4: Check AnalysisRun Results”# List analysis runskubectl get analysisruns -n rollouts-demo
# Check the latest analysis runkubectl describe analysisrun -n rollouts-demo -l rollouts-pod-template-hashThe analysis run executes a Job that sends a wget request to the canary service. If it gets HTTP 200, the metric reports “healthy” and the rollout proceeds. Three successful checks are required.
Step 5: Simulate a Bad Deployment (Auto-Rollback)
Section titled “Step 5: Simulate a Bad Deployment (Auto-Rollback)”Deploy a version that will fail the health check. We use an image that does not exist, so the canary pods will never become ready:
kubectl argo rollouts set image canary-app nginx=nginx:999.999.999-doesnotexist -n rollouts-demoWatch the rollout:
kubectl argo rollouts get rollout canary-app -n rollouts-demo -wThe canary pod fails to start (ImagePullBackOff). The AnalysisRun fails because the health check cannot reach the canary. After the failure limit is reached, the rollout automatically aborts and scales down the failed canary ReplicaSet.
# Check rollout status - should show "Degraded"kubectl argo rollouts status canary-app -n rollouts-demo
# Check eventskubectl describe rollout canary-app -n rollouts-demo | grep -A 10 "Events"The stable version (v2 from Step 2) continues serving traffic. No downtime.
Step 6: Recover from the Bad Deployment
Section titled “Step 6: Recover from the Bad Deployment”Abort the failed rollout and restore to healthy state:
kubectl argo rollouts abort canary-app -n rollouts-demokubectl argo rollouts set image canary-app nginx=nginx:1.25.4-alpine -n rollouts-demoWatch recovery:
kubectl argo rollouts get rollout canary-app -n rollouts-demo -wWhat is Happening
Section titled “What is Happening”manifests/ namespace.yaml # rollouts-demo namespace rollout.yaml # Argo Rollout with canary strategy (v1) rollout-v2.yaml # Updated Rollout with new image/content (v2) service.yaml # Stable and canary Services analysis-template.yaml # AnalysisTemplate with wget health checkArgo Rollout vs Deployment:
| Feature | Deployment | Argo Rollout |
|---|---|---|
| Rolling update | Yes | Yes |
| Canary with traffic splitting | No | Yes |
| Automated analysis | No | Yes (AnalysisTemplate) |
| Auto-rollback on failure | No | Yes |
| Pause between steps | No | Yes |
| Blue-green strategy | No | Yes |
Canary progression:
Step 1: setWeight 10% ──> 1 canary pod, AnalysisRun starts │Step 2: pause 30s ──> Health checks run, traffic at 10/90 │Step 3: setWeight 50% ──> 2 canary pods, traffic at 50/50 │Step 4: pause 30s ──> Health checks continue │Step 5: setWeight 100% ──> Canary becomes stable, old RS scales downExperiment
Section titled “Experiment”-
Manually promote during a pause instead of waiting:
Terminal window kubectl argo rollouts promote canary-app -n rollouts-demo -
Check the rollout history:
Terminal window kubectl argo rollouts get rollout canary-app -n rollouts-demo --no-color -
Try a blue-green strategy (edit rollout.yaml to replace the canary block):
strategy:blueGreen:activeService: canary-app-stablepreviewService: canary-app-canaryautoPromotionEnabled: trueautoPromotionSeconds: 30 -
View the Argo Rollouts dashboard:
Terminal window kubectl argo rollouts dashboard -n rollouts-demoOpen http://localhost:3100 in your browser.
Cleanup
Section titled “Cleanup”kubectl delete namespace rollouts-demokubectl delete namespace argo-rolloutsFurther Reading
Section titled “Further Reading”See docs/deep-dive.md for a detailed explanation of progressive delivery patterns, traffic management with Istio and NGINX ingress integration, Prometheus-based AnalysisTemplates, blue-green vs canary trade-offs, and how GitOps pipelines trigger Argo Rollouts.
Next Step
Section titled “Next Step”Move on to Istio Service Mesh to learn about mTLS, traffic splitting, and observability with a service mesh.