Argo Rollouts: Progressive Delivery with Canary and Blue-Green Deployments
Kubernetes rolling updates give you a basic deployment strategy, but no traffic control, no analysis, and no automatic rollback. Argo Rollouts adds progressive delivery: canary releases that shift traffic gradually, blue-green deployments with instant cutover, automated analysis using Prometheus metrics or custom webhooks, and pause/promote/abort workflows.

Kubernetes rolling updates move old pods to new pods gradually, but they don't control traffic. All pods receive production traffic immediately after they become Ready — there's no way to say "send 5% of traffic to the new version, measure error rate, and automatically roll back if it degrades." Argo Rollouts adds this layer.
Argo Rollouts replaces the Deployment with a Rollout object that supports canary and blue-green strategies with traffic management integrations (Istio, AWS ALB, NGINX) and automated analysis gates.
Installation
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/download/v1.7.2/install.yaml
# Check https://github.com/argoproj/argo-rollouts/releases for current versionOr via Helm:
1helm repo add argo https://argoproj.github.io/argo-helm
2helm repo update
3
4helm install argo-rollouts argo/argo-rollouts \
5 --namespace argo-rollouts \
6 --create-namespace \
7 --values rollouts-values.yaml1# rollouts-values.yaml
2controller:
3 replicas: 2 # HA for the rollouts controller
4
5dashboard:
6 enabled: true # Argo Rollouts UI (not the Argo CD UI)
7 service:
8 type: ClusterIP# Install the kubectl plugin
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x kubectl-argo-rollouts-linux-amd64
mv kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rolloutsCanary Rollout
A Rollout spec is almost identical to a Deployment spec, with a strategy.canary block replacing strategy.rollingUpdate:
1apiVersion: argoproj.io/v1alpha1
2kind: Rollout
3metadata:
4 name: payments-api
5 namespace: production
6spec:
7 replicas: 5
8 selector:
9 matchLabels:
10 app: payments-api
11 template:
12 metadata:
13 labels:
14 app: payments-api
15 spec:
16 containers:
17 - name: api
18 image: 123456789.dkr.ecr.us-east-1.amazonaws.com/payments-api:1.4.2
19 ports:
20 - containerPort: 8080
21 resources:
22 requests:
23 cpu: 200m
24 memory: 256Mi
25
26 strategy:
27 canary:
28 # Stable Service — receives traffic from non-canary pods
29 stableService: payments-api-stable
30 # Canary Service — receives the traffic percentage assigned to canary
31 canaryService: payments-api-canary
32
33 trafficRouting:
34 istio:
35 virtualService:
36 name: payments-api
37 routes:
38 - primary
39 destinationRule:
40 name: payments-api
41 stableSubsetName: stable
42 canarySubsetName: canary
43
44 steps:
45 - setWeight: 5 # 5% traffic to canary
46 - pause: {} # Pause indefinitely — wait for manual promote or analysis
47 - setWeight: 20
48 - pause: {duration: 10m} # Auto-advance after 10 minutes
49 - setWeight: 40
50 - pause: {duration: 10m}
51 - setWeight: 60
52 - analysis:
53 templates:
54 - templateName: success-rate
55 - setWeight: 80
56 - pause: {duration: 5m}
57 # Final step: 100% promoted automatically (or promote manually)Services for Traffic Splitting
Canary traffic splitting requires two Services pointing to the same selector but managed by Argo Rollouts:
1# Stable service — points to stable (non-canary) pods
2apiVersion: v1
3kind: Service
4metadata:
5 name: payments-api-stable
6 namespace: production
7spec:
8 selector:
9 app: payments-api
10 ports:
11 - port: 80
12 targetPort: 8080
13---
14# Canary service — Argo Rollouts patches this to point to canary pods
15apiVersion: v1
16kind: Service
17metadata:
18 name: payments-api-canary
19 namespace: production
20spec:
21 selector:
22 app: payments-api
23 ports:
24 - port: 80
25 targetPort: 8080Argo Rollouts modifies the selector on the canary Service to add a pod-hash label, isolating traffic to canary pods.
Automated Analysis
AnalysisTemplate defines metrics to query during a rollout. Argo Rollouts evaluates these and automatically promotes or aborts:
1apiVersion: argoproj.io/v1alpha1
2kind: AnalysisTemplate
3metadata:
4 name: success-rate
5 namespace: production
6spec:
7 args:
8 - name: service-name
9 metrics:
10 - name: success-rate
11 interval: 1m
12 successCondition: result[0] >= 0.99 # 99% success rate required
13 failureLimit: 3 # Allow 3 failures before marking analysis as Failed
14 provider:
15 prometheus:
16 address: http://kube-prometheus-stack-prometheus.monitoring:9090
17 query: |
18 sum(rate(http_requests_total{
19 app="{{args.service-name}}",
20 status!~"5.."
21 }[5m]))
22 /
23 sum(rate(http_requests_total{
24 app="{{args.service-name}}"
25 }[5m]))Referencing the template in the Rollout:
1steps:
2 - setWeight: 20
3 - analysis:
4 templates:
5 - templateName: success-rate
6 args:
7 - name: service-name
8 value: payments-api-canary
9 - setWeight: 50If the analysis fails (success rate drops below 99%), Argo Rollouts automatically aborts the rollout and scales the canary back to 0.
Background Analysis
Run analysis throughout the entire rollout rather than at specific steps:
1strategy:
2 canary:
3 analysis:
4 templates:
5 - templateName: success-rate
6 args:
7 - name: service-name
8 value: payments-api-canary
9 startingStep: 1 # Start analysis after step 1 (not during the first setWeight)Blue-Green Rollout
Blue-green maintains two full deployments — active (blue) and preview (green). Traffic switches atomically:
1apiVersion: argoproj.io/v1alpha1
2kind: Rollout
3metadata:
4 name: payments-api
5 namespace: production
6spec:
7 replicas: 3
8 selector:
9 matchLabels:
10 app: payments-api
11 template:
12 metadata:
13 labels:
14 app: payments-api
15 spec:
16 containers:
17 - name: api
18 image: 123456789.dkr.ecr.us-east-1.amazonaws.com/payments-api:1.4.2
19
20 strategy:
21 blueGreen:
22 activeService: payments-api-active # Receives production traffic
23 previewService: payments-api-preview # Receives preview traffic (testing)
24 autoPromotionEnabled: false # Require manual promotion
25 prePromotionAnalysis: # Run analysis before promoting
26 templates:
27 - templateName: success-rate
28 args:
29 - name: service-name
30 value: payments-api-preview
31 postPromotionAnalysis: # Run analysis after promoting (abort if fails)
32 templates:
33 - templateName: success-rate
34 args:
35 - name: service-name
36 value: payments-api-active
37 scaleDownDelaySeconds: 300 # Keep old (blue) pods running 5 min after promotion
38 abortScaleDownDelaySeconds: 30Rollout Operations
1# Watch a rollout in progress
2kubectl argo rollouts get rollout payments-api -n production --watch
3
4# Promote (advance past a pause step or fully promote)
5kubectl argo rollouts promote payments-api -n production
6
7# Abort and roll back to stable
8kubectl argo rollouts abort payments-api -n production
9
10# Retry after an abort
11kubectl argo rollouts retry rollout payments-api -n production
12
13# Update the image (triggers a new rollout)
14kubectl argo rollouts set image payments-api api=...ecr.../payments-api:1.4.3 -n productionRollout Status
1kubectl argo rollouts get rollout payments-api -n production
2# NAME KIND STATUS STABLE DESIRED READY UP-TO-DATE
3# payments-api Rollout Progressing 1 5 4 1
4#
5# Revision 3:
6# ⟳ payments-api-77c8d4b89 canary 1/1 (5%)
7# Revision 2:
8# ✔ payments-api-6f4c7b8d stable 4/4HPA Integration
HPA targets Rollout objects the same way it targets Deployment objects:
1apiVersion: autoscaling/v2
2kind: HorizontalPodAutoscaler
3metadata:
4 name: payments-api
5 namespace: production
6spec:
7 scaleTargetRef:
8 apiVersion: argoproj.io/v1alpha1
9 kind: Rollout
10 name: payments-api
11 minReplicas: 3
12 maxReplicas: 20
13 metrics:
14 - type: Resource
15 resource:
16 name: cpu
17 target:
18 type: Utilization
19 averageUtilization: 70HPA adjusts the Rollout's desired replica count, and Argo Rollouts distributes replicas between stable and canary ReplicaSets according to the current weight.
Frequently Asked Questions
How do I migrate from a Deployment to a Rollout?
Argo Rollouts docs provide a migration guide — the key step is that the Rollout spec is a superset of Deployment spec with strategy.canary or strategy.blueGreen replacing strategy.rollingUpdate. The selector and template are identical. You can delete the Deployment and create the Rollout without downtime if the pod selector remains the same.
Does Argo Rollouts work without a traffic management integration?
Yes. Without trafficRouting, Argo Rollouts uses a subset-based canary: setWeight: 20 with 5 total replicas means 1 pod runs the new version and 4 run the old version. This is an approximation of 20% — you get 20% of pods on the new version, not 20% of traffic. For exact traffic percentages, you need Istio, AWS ALB, or NGINX integration.
Can I use Argo Rollouts with Argo CD?
Yes — and this is the recommended approach. Argo CD manages the Rollout manifest in Git. When you update the image tag in Git, Argo CD syncs it, which triggers the rollout process. Argo CD has native awareness of Rollout health — it shows the rollout status (progressing, degraded, healthy) in its UI.
Header-Based Canary Routing
Route specific users to the canary version by request header — useful for internal testing before percentage-based rollout:
1steps:
2 - setHeaderRoute:
3 name: canary-header
4 match:
5 - headerName: X-Canary
6 headerValue:
7 exact: "true"
8 - pause: {} # Hold until internal testing complete
9 - setWeight: 10
10 - pause: {duration: 10m}
11 - setWeight: 100Internal QA team sends X-Canary: true headers. Production users see the stable version until you advance past the pause. This requires Nginx or Istio with header-based routing support.
Web Webhook Analysis
For services with a dedicated health endpoint or custom validation API:
1apiVersion: argoproj.io/v1alpha1
2kind: AnalysisTemplate
3metadata:
4 name: canary-health-check
5spec:
6 metrics:
7 - name: health
8 interval: 30s
9 count: 10
10 successCondition: result == "Healthy"
11 provider:
12 web:
13 url: "https://my-service.example.com/canary-health"
14 jsonPath: "{$.status}"Migrating from Deployment to Rollout
Migrating an existing Deployment to a Rollout without downtime:
- Copy the Deployment spec into a Rollout resource — the
templatesection is identical - Add the strategy block — start with a simple canary (one step to 100%, no analysis) as a safe migration
- Scale the Deployment to 0 — Rollout takes over pod management
- Delete the Deployment once the Rollout is confirmed working
# Convert a Deployment to Rollout (Argo plugin command)
kubectl argo rollouts create -f rollout.yaml
# Scale down the old Deployment
kubectl scale deployment payments-api --replicas=0 -n productionDo not delete the Deployment until the Rollout is healthy — if something goes wrong, you can scale the Deployment back up. The Rollout selector must match the Deployment selector exactly or the pods will not be adopted.
Notifications
Argo Rollouts uses the same notifications engine as Argo CD. Configure alerts for rollout events in the argo-rollouts-notification-configmap ConfigMap:
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: argo-rollouts-notification-configmap
5 namespace: argo-rollouts
6data:
7 service.slack: |
8 token: $slack-token
9 template.rollout-completed: |
10 message: Rollout {{.rollout.metadata.name}} completed successfully
11 trigger.on-rollout-completed: |
12 - send: [rollout-completed]
13 when: "rollout.status.phase == 'Healthy'"GitOps Integration with Argo CD
Argo Rollouts works naturally with Argo CD. Deploy the Rollout resource through Argo CD like any other Kubernetes object. The Rollout controller handles the progressive delivery; Argo CD handles reconciliation:
1# Argo CD Application for the service
2apiVersion: argoproj.io/v1alpha1
3kind: Application
4metadata:
5 name: payments-api
6 namespace: argocd
7spec:
8 source:
9 repoURL: https://github.com/my-org/payments-api
10 path: deploy/
11 targetRevision: HEAD
12 destination:
13 server: https://kubernetes.default.svc
14 namespace: production
15 syncPolicy:
16 automated:
17 prune: true
18 selfHeal: trueWhen you merge a new image tag to Git, Argo CD updates the Rollout. The Rollout controller starts the canary steps. Analysis runs automatically. If the analysis passes, the rollout completes. If it fails, the Rollout rolls back and Argo CD shows the sync status as OutOfSync — the desired state (new image) differs from the current state (rolled back to old image), which correctly prompts investigation before retrying.
Note: Argo CD's sync will show OutOfSync after an automatic rollback because the Rollout spec (image tag) doesn't match what's running. This is intentional — the rollback is an operational decision that should be reflected in a git change, not silently accepted.
For Istio VirtualService traffic splitting that Argo Rollouts manipulates during canary releases, see Istio Service Mesh for Kubernetes. For Argo CD that manages Rollout manifests in GitOps, see Argo CD ApplicationSet: Multi-Cluster Deployments. For the Argo CD setup that manages Rollout manifests as part of your GitOps workflow, see GitOps with Argo CD: Production Setup Guide.
Rolling out a canary release strategy for a production Kubernetes platform? Talk to us at Coding Protocols — we help platform teams implement progressive delivery pipelines that reduce deployment risk without slowing down release velocity.


