Rollback
Summary
- A rollback returns a Deployment to a previous known-good revision by re-activating the ReplicaSet that revision points to.
- Insight: rollback is cheap and fast precisely because old ReplicaSets are kept at zero replicas, not deleted, so nothing has to be rebuilt.
- Key Concepts: revisions, revisionHistoryLimit,
kubectl rollout undo, and change-cause annotations. - When to Use: the moment a rollout ships a bad version and you need to restore service faster than you can debug.
- Limitations: rollback reverts the Pod template only, not external state like database migrations or config in other objects.
- Related: rolling update mechanics, parameters, and best practices.
Recipe
Undo the last rollout, or roll back to a specific revision.
# Revert to the immediately previous revision
kubectl rollout undo deployment/web
# Inspect available revisions first
kubectl rollout history deployment/web
# Roll back to a specific revision number
kubectl rollout undo deployment/web --to-revision=7Working Example
Suppose you ship a broken image and need to recover.
First, confirm the rollout is failing.
kubectl rollout status deployment/web --timeout=60s
# error: deployment "web" exceeded its progress deadlineList the revision history to see what you can return to.
kubectl rollout history deployment/webREVISION CHANGE-CAUSE
5 kubectl apply --filename=web.yaml
6 kubectl apply --filename=web.yaml
7 kubectl set image deployment/web web=web:2.0.0Roll back to the previous good revision and confirm recovery.
kubectl rollout undo deployment/web --to-revision=6
kubectl rollout status deployment/web
kubectl get pods -l app=webThe controller scales the ReplicaSet for revision 6 back up and scales the broken one down, using the same rolling update mechanics as a forward deploy.
Note that a rollback itself creates a new revision. Rolling back from revision 7 to 6 produces revision 8 whose template matches 6.
Deep Dive
What a revision actually is
Each change to the Pod template produces a new ReplicaSet, and the Deployment records it as a revision.
The revision number lives in the deployment.kubernetes.io/revision annotation on both the Deployment and its ReplicaSets.
Old ReplicaSets are retained at zero replicas so their templates remain available for rollback.
Controlling history depth
revisionHistoryLimit caps how many old ReplicaSets are kept; the default is 10.
spec:
revisionHistoryLimit: 10Set it too low and you lose the ability to roll back more than a step or two. Set it to zero and you lose rollback entirely, so avoid that.
Recording the change-cause
The CHANGE-CAUSE column is populated from the kubernetes.io/change-cause annotation, which you set deliberately.
kubectl annotate deployment/web \
kubernetes.io/change-cause="deploy web:2.0.0 for ticket OPS-412" --overwriteWithout this, history shows the raw command or nothing useful, which makes choosing a rollback target harder during an incident.
Pausing and resuming
You can pause a Deployment to batch several template edits into one rollout, then resume.
kubectl rollout pause deployment/web
kubectl set image deployment/web web=web:2.1.0
kubectl set resources deployment/web -c web --limits=memory=512Mi
kubectl rollout resume deployment/webA paused Deployment does not roll out changes until resumed, which also means it will not react to a bad edit until you resume it.
Gotchas
Rollback does not revert database migrations. If the bad version ran a forward-only migration, rolling back the image can leave the old code reading a schema it does not understand. Design migrations to be backward compatible.
revisionHistoryLimit: 0 disables rollback. With no retained ReplicaSets there is nothing to roll back to. Keep a nonzero limit.
Scaling is not a revision. kubectl scale does not create a revision, so you cannot roll back a replica-count change with rollout undo.
GitOps and manual rollback fight each other. If Argo CD or Flux owns the Deployment, a manual rollout undo is reverted at the next sync. Roll back in Git instead by reverting the commit.
The rollback is itself a rollout. It is gated by readiness and the same surge/unavailable window, so a cluster too full to schedule Pods can stall the rollback too.
Alternatives
Git revert under GitOps is the correct rollback when Argo CD or Flux is the source of truth. Revert the commit and let the controller reconcile.
Helm rollback (helm rollback <release> <revision>) reverts an entire release, including Services and ConfigMaps, not just the Deployment template. Use it when the bad change spanned multiple objects.
Roll forward with a fixed image is sometimes safer than rolling back, especially when state has already moved forward. Choose based on whether the previous version can still operate on current data.
FAQs
Does rollback create a new revision? Yes. Rolling back to revision 6 creates a new highest-numbered revision whose template matches revision 6.
How many revisions are kept?
revisionHistoryLimit controls it, defaulting to 10 old ReplicaSets.
Can I roll back a scale change?
No. Scaling does not create a revision, so rollout undo only reverts template changes.
Why is CHANGE-CAUSE empty?
You did not set the kubernetes.io/change-cause annotation for that rollout. Set it on every deploy for readable history.
Is rollback instant? It is fast because the target ReplicaSet already exists, but it still obeys readiness and the rolling update window, so it takes as long as scaling those Pods up.
Related
- How Rolling Updates Actually Work
- Rolling Update Parameters
- Deployments Basics
- Deployments Best Practices
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).