64.6 Argo Rollouts: automated canary and blue-green with analysis
Why: the problem
In 64.3 to 64.5 we did a lot by hand: patching weights, waiting, running smoke tests, deciding to promote or abort. That works for a lab, but at a company like Meesho, with dozens of releases a day, people forget steps and decisions become inconsistent. Argo Rollouts turns those steps into a declared object that a controller carries out for you. Argo Rollouts adds a custom resource called Rollout. It looks almost exactly like a Deployment: same replicas, selector and pod template. The difference is the strategy section. A canary strategy lists steps such as setWeight: 20, pause for 60 seconds, setWeight: 50, analysis, and so on. A blueGreen strategy names an activeService and a previewService and decides whether promotion is automatic. The Rollout controller creates ReplicaSets itself, so you must not also have a Deployment for the same pods. Without a traffic router, Argo Rollouts approximates the weight with replica counts, like our replica canary in 64.5. With a trafficRouting section it drives a router for exact percentages. It supports ingress-nginx (by managing a canary Ingress with the annotations you used), the Gateway API through a plugin, the AWS Load Balancer Controller, Istio, Linkerd through SMI and others. The most valuable part is analysis. An AnalysisTemplate describes how to measure success: a Prometheus query for error rate, a Datadog or CloudWatch metric, a web request, or a Kubernetes Job whose exit code means pass or fail. When an analysis step or background analysis fails, the controller aborts the rollout automatically: it sets canary weight back to zero, scales the canary down and marks the Rollout Degraded. Nobody has to be awake at 2 am to roll back. The kubectl argo rollouts plugin gives you get rollout --watch, promote, abort, retry and undo, and a small dashboard. Since v1.10.1 (October 2026) that dashboard listens only on 127.0.0.1 by default, so add --address 0.0.0.0 only if you really expose it through a Service. In this lesson we install Argo Rollouts on the ch64 cluster from a pinned manifest, convert our cart service to a Rollout with canary steps through ingress-nginx, add a Job-based analysis that blocks a bad release on its own, and look at the blue-green strategy.
What: every term in plain English
- Argo Rollouts — Controller and CRDs for progressive delivery in Kubernetes.
- Rollout — CRD that replaces a Deployment and adds canary or blueGreen strategies.
- setWeight — Canary step that sets the share of traffic to the new version.
- pause — Step that waits for a duration or for manual promotion.
- trafficRouting — Section that lets the controller drive ingress-nginx, Gateway API, Istio and others.
- stableService and canaryService — Services the controller points at stable and canary ReplicaSets.
- AnalysisTemplate — Reusable definition of metrics and pass or fail conditions.
- AnalysisRun — One execution of an AnalysisTemplate during a rollout.
- Job provider — Analysis that runs a Kubernetes Job; exit code 0 passes.
- Abort — Controller returns all traffic to stable after failed analysis.
- Degraded — Rollout status after an abort.
- kubectl argo rollouts — kubectl plugin to watch, promote, abort and undo.
How: step by step
- Install Argo Rollouts from a pinned manifest. Controller running.
- Install the kubectl plugin. get rollout works.
- Create the cart Rollout with canary steps. Revision 1 stable.
- Release v2. Weights step 20, 50, 100.
- Add a Job-based AnalysisTemplate. Checks between steps.
- Release a bad v3. Analysis fails, controller aborts.
- Look at blueGreen. Preview and active Services.
- Clean up the cluster. Chapter done.
Example 1: A canary Rollout through ingress-nginx
Goal. A canary Rollout through ingress-nginx.
install.sh
# argo-rollouts-install.yaml: the install manifest for a pinned release, saved from the official Argo Rollouts docs and reviewed
kubectl create ns argo-rollouts
kubectl apply -n argo-rollouts -f argo-rollouts-install.yaml
kubectl wait -n argo-rollouts --for=condition=available deploy/argo-rollouts --timeout=180s
kubectl argo rollouts version
rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: cart
namespace: ar
spec:
replicas: 4
selector:
matchLabels:
app: cart
template:
metadata:
labels:
app: cart
spec:
containers:
- name: web
image: hashicorp/http-echo:1.0
args:
- -listen=:8080
- -text=cart v1
ports:
- containerPort: 8080
strategy:
canary:
stableService: cart-stable
canaryService: cart-canary
trafficRouting:
nginx:
stableIngress: cart
steps:
- setWeight: 20
- pause: {duration: 30s}
- setWeight: 50
- pause: {duration: 30s}
What each line does
Rollout instead of Deployment— Same template; the controller owns the ReplicaSets.stableService and canaryService— Two plain Services selecting app: cart; the controller adds a hash selector to each.stableIngress— Our normal Ingress for cart.local; the controller creates the canary Ingress itself.steps— 20% for 30 seconds, 50% for 30 seconds, then full promotion.Plugin— kubectl argo rollouts comes from the official docs install page, for example through a package manager.
Green output
$ bash install.sh
argo-rollouts: v1.10.1
$ kubectl create ns ar
$ kubectl create svc clusterip cart-stable -n ar --tcp=80:8080 && kubectl set selector svc cart-stable -n ar app=cart
$ kubectl create svc clusterip cart-canary -n ar --tcp=80:8080 && kubectl set selector svc cart-canary -n ar app=cart
$ kubectl create ingress cart -n ar --class=nginx --rule="cart.local/*=cart-stable:80"
$ kubectl apply -f rollout.yaml
$ kubectl patch rollout cart -n ar --type=json -p '[{"op":"replace","path":"/spec/template/spec/containers/0/args/1","value":"-text=cart v2"}]'
$ kubectl argo rollouts get rollout cart -n ar
Name: cart
Status: Paused
Message: CanaryPauseStep
Strategy: Canary
Step: 1/4
SetWeight: 20
ActualWeight: 20
$ kubectl get ingress -n ar
NAME CLASS HOSTS PORTS
cart nginx cart.local 80
cart-cart-canary nginx cart.local 80
Expected result. The controller created the canary Ingress with the same annotations you wrote by hand in 64.5, set it to 20%, and will move to 50% and then 100% on its own after each pause.
Example 2: Analysis stops a bad release automatically
Goal. Analysis stops a bad release automatically.
analysis.yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: smoke
namespace: ar
spec:
metrics:
- name: canary-smoke
count: 3
interval: 10s
failureLimit: 0
provider:
job:
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: check
image: busybox:1.36
command:
- sh
- -c
- for i in 1 2 3 4 5; do wget -q -O- http://cart-canary.ar | grep -q ERROR && exit 1; done; exit 0
steps-patch.yaml
spec:
strategy:
canary:
steps:
- setWeight: 20
- analysis:
templates:
- templateName: smoke
- setWeight: 50
- pause: {duration: 30s}
What each line does
Job provider— Runs a Job; exit 0 is success, anything else is failure.cart-canary.ar— Talks straight to canary pods, so the check measures only the new version.count 3, interval 10s— Three checks, ten seconds apart.failureLimit 0— A single failure aborts the rollout.analysis step— Runs after the first 20% step; the rollout waits for the result.
Green output
$ kubectl apply -f analysis.yaml
$ kubectl patch rollout cart -n ar --type=merge --patch-file steps-patch.yaml
$ kubectl patch rollout cart -n ar --type=json -p '[{"op":"replace","path":"/spec/template/spec/containers/0/args/1","value":"-text=ERROR v3"}]'
$ kubectl argo rollouts get rollout cart -n ar --watch
Status: Degraded
Message: RolloutAborted: Rollout aborted update to revision 4: Metric "canary-smoke" assessed Failed due to failed (1) > failureLimit (0)
ActualWeight: 0
$ kubectl get analysisrun -n ar
NAME STATUS
cart-5d9c7f8b-4-2 Failed
$ kubectl run c -n ar --rm -i --image=busybox:1.36 --restart=Never -- wget -q -O- --header=Host:cart.local http://ingress-nginx-controller.ingress-nginx
cart v2
Expected result. The bad version got 20% for a few seconds while the analysis ran. The Job found ERROR, the AnalysisRun failed, and the controller set the weight back to 0 and scaled the canary down. Users stayed on v2 with no human action.
Example 3: Retry, undo and the blueGreen strategy
Goal. Retry, undo and the blueGreen strategy.
fix.sh
kubectl patch rollout cart -n ar --type=json -p '[{"op":"replace","path":"/spec/template/spec/containers/0/args/1","value":"-text=cart v4"}]'
kubectl argo rollouts get rollout cart -n ar --watch --timeout 3m
kubectl argo rollouts undo cart -n ar
kubectl argo rollouts promote cart -n ar --full
bluegreen.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: booking
namespace: ar
spec:
replicas: 3
selector:
matchLabels:
app: booking
template:
metadata:
labels:
app: booking
spec:
containers:
- name: web
image: hashicorp/http-echo:1.0
args: ["-listen=:8080", "-text=booking v1"]
strategy:
blueGreen:
activeService: booking
previewService: booking-preview
autoPromotionEnabled: false
scaleDownDelaySeconds: 60
What each line does
New fixed version— A fresh patch starts a new rollout from Degraded.undo— Goes back one revision, like kubectl rollout undo.promote --full— Skips the remaining steps and goes to 100%.blueGreen— activeService and previewService, as in 64.4, managed for you.autoPromotionEnabled false— Waits for kubectl argo rollouts promote after testing preview.
Green output
$ bash fix.sh
Status: Healthy
Step: 4/4
ActualWeight: 100
rollout 'cart' undo
rollout 'cart' fully promoted
$ kubectl create svc clusterip booking -n ar --tcp=80:8080 && kubectl create svc clusterip booking-preview -n ar --tcp=80:8080
$ kubectl apply -f bluegreen.yaml
$ kubectl patch rollout booking -n ar --type=json -p '[{"op":"replace","path":"/spec/template/spec/containers/0/args/1","value":"-text=booking v2"}]'
$ kubectl argo rollouts get rollout booking -n ar
Status: Paused
Message: BlueGreenPause
$ kubectl argo rollouts promote booking -n ar
rollout 'booking' promoted
Expected result. Argo Rollouts handled the full lifecycle: a good canary ran to 100%, undo and full promotion took one command each, and the blueGreen Rollout waited on preview until we promoted it. The old ReplicaSet stays up for 60 seconds for a quick switch back.
Every command, step by step (kind lab with kubectl)
-
Install
bash install.shWhat it does: Controller ready.
deployment.apps/argo-rollouts condition met -
Services
kubectl create svc clusterip cart-stable -n ar --tcp=80:8080What it does: Two Services.
service/cart-stable created -
Ingress
kubectl create ingress cart -n ar --class=nginx --rule="cart.local/*=cart-stable:80"What it does: Stable Ingress.
ingress.networking.k8s.io/cart created -
Rollout
kubectl apply -f rollout.yamlWhat it does: Revision 1.
rollout.argoproj.io/cart created -
Release
kubectl patch rollout cart -n ar ...What it does: Steps run.
SetWeight: 20 -
Analysis
kubectl apply -f analysis.yamlWhat it does: Template.
analysistemplate.argoproj.io/smoke created -
Bad
kubectl patch rollout cart -n ar ... ERROR v3What it does: Aborted.
Status: Degraded -
Runs
kubectl get analysisrun -n arWhat it does: Failed.
cart-5d9c7f8b-4-2 Failed -
Fix
bash fix.shWhat it does: Healthy.
rollout 'cart' fully promoted -
Blue-green
kubectl apply -f bluegreen.yamlWhat it does: Paused for promotion.
Message: BlueGreenPause -
Clean up
kind delete cluster --name ch64What it does: Chapter done.
Deleted nodes: ["ch64-control-plane" "ch64-worker" "ch64-worker2"]
When it is red 1
the server could not find the requested resource (rollouts)
Cause. CRDs not installed.
Fix, step by step
- Apply the install manifest again.
- kubectl get crd | grep argoproj.
When it is red 2
Rollout stuck at Progressing with no canary Ingress
Cause. stableIngress name wrong or not in the same namespace.
Fix, step by step
- Check spec.strategy.canary.trafficRouting.nginx.stableIngress.
When it is red 3
AnalysisRun Error
Cause. Job could not start or the template has a typo.
Fix, step by step
- kubectl describe analysisrun.
- kubectl logs of the Job pod.
When it is red 4
Pods duplicated after converting a Deployment
Cause. Both the Deployment and the Rollout manage the same labels.
Fix, step by step
- Use workloadRef, or scale the Deployment to 0 after the Rollout is healthy.
When it is red 5
Degraded rollout does not retry
Cause. Aborted rollouts wait for a new change or retry.
Fix, step by step
- kubectl argo rollouts retry rollout cart.
Practice tasks
Easy Task 1: Install
Why: Setup.
What to do: Install Argo Rollouts and the kubectl plugin.
- Pinned manifest, official docs.
Solution
kubectl argo rollouts versionEasy Task 2: Rollout
Why: Create.
What to do: Apply rollout.yaml.
- Services and Ingress first.
Solution
kubectl argo rollouts get rollout cart -n arMedium Task 3: Release
Why: Watch.
What to do: Release v2 and watch steps.
- --watch.
Solution
kubectl argo rollouts get rollout cart -n ar --watchMedium Task 4: Analysis
Why: Add.
What to do: Apply analysis.yaml and the steps patch.
- Job provider.
Solution
kubectl get analysistemplate -n arMedium Task 5: Abort
Why: Bad.
What to do: Release ERROR v3.
- Watch Degraded.
Solution
kubectl get analysisrun -n arMedium Task 6: Undo
Why: Recover.
What to do: Undo and promote full.
- fix.sh.
Solution
kubectl argo rollouts get rollout cart -n arHard Task 7: Blue-green
Why: Variant.
What to do: Run bluegreen.yaml and promote.
- previewService.
Solution
kubectl argo rollouts get rollout booking -n arHard Task 8: Meesho
Why: Main task.
What to do: 10, 30, 60, 100 with analysis and blueGreen.
- Two releases.
Solution
kubectl argo rollouts get rollout -n arHomework: try at home
For Meesho's catalog service, convert a Deployment to a Rollout with steps 10, 30, 60 and 100 through ingress-nginx, add a Job-based analysis after each weight step, show one release that reaches 100% and one that is aborted automatically, then switch the same app to blueGreen with manual promotion.
Recap
- Argo Rollouts replaces Deployments with Rollouts that have canary or blueGreen strategies.
- Steps such as setWeight, pause and analysis are declared, not typed by hand.
- trafficRouting drives ingress-nginx, Gateway API, ALB or a mesh for exact weights.
- AnalysisTemplates turn metrics or Jobs into automatic promote or abort decisions.
- The kubectl plugin gives watch, promote, abort, retry and undo.
FAQ
Q. Does Argo Rollouts need Argo CD?
No. They work well together, but Rollouts is a separate controller you can use with any deployment tool, including plain kubectl and Helm.
Q. Can I keep my Deployment and still use Rollouts?
Yes, with workloadRef: the Rollout points at the Deployment's template, and you scale the Deployment to zero. This makes migration gradual.
Q. Is Flagger an alternative?
Yes. Flagger from the Flux project does similar progressive delivery and keeps your Deployment, creating its own primary and canary copies. Choose based on your router and GitOps tool.
Q. Does the Rollout handle database migrations?
No. Run migrations in a separate step, such as a Job in a pre-sync hook, and keep them backward compatible so an abort is safe.
Interview questions
-
What problem does Argo Rollouts solve?
Model answer: It automates canary and blue-green steps, traffic shifting and metric-based promotion or rollback that Deployments do not offer.
-
How is a Rollout different from a Deployment?
Model answer: Same template and selector, but a richer strategy section, and the Rollout controller owns the ReplicaSets.
-
How does automatic rollback work?
Model answer: An AnalysisRun evaluates metrics; when it fails beyond failureLimit the controller aborts, setting canary weight to 0.
-
Canary without a traffic router?
Model answer: Weights are approximated by replica counts, so percentages are coarse.
Quick quiz
Q1. What replaces the Deployment?
A Rollout.
Q2. Without trafficRouting how is weight done?
By replica counts.
Q3. What decides pass or fail?
An AnalysisTemplate.
Q4. What happens on failed analysis?
Abort: weight 0, Degraded.
Q5. How do you skip remaining steps?
promote --full.
Samajla ka?
Lab
- Create a fresh kind cluster named ch64 with one control plane and two workers.
- Keep YAML files in a folder named k8s-ch64.
- Run a curl loop in a second terminal during every release so you can see any errors.
- Install ingress-nginx in 64.5 and keep it for 64.6.
- Delete the cluster at the end with kind delete cluster --name ch64.
Practice task
Release three versions of one shop frontend with a rolling update, a blue-green switch and a canary, roll back one broken release, and prove each step with a request loop that counts versions and errors.
Ravindra Bagale's Tip
Interview madhe 'rolling update kasa kaam karto', 'rollback kasa karal' aani 'blue-green aani canary madhla farak' he prashna nakki yetat. Lab karun uttar dya.
In short
- A Deployment rollout replaces pods gradually and waits for readiness.
- Every template change creates a new ReplicaSet revision that you can roll back to.
- Blue-green switches a Service selector; canary splits traffic by replicas or ingress weights.
- Argo Rollouts automates canary steps and analysis.