Roll back a bad deployment with kubectl rollout undo

By Hackademy. Updated . Output from a real Kubernetes v1.35 cluster.

The short answer

kubectl rollout undo deployment/NAME rolls a Deployment back to its previous revision. Every change to a Deployment's pod template, such as a new image, environment variable or probe, creates a new ReplicaSet and a new revision, and the old ReplicaSets are kept scaled to zero so a rollback can reuse them. Use it when a deploy is stuck on a bad image, crashes, or misbehaves and you need the last working version back before you find out why. First run kubectl rollout history deployment/NAME to list the revisions and --revision=N to see what one contained. Then run kubectl rollout undo deployment/NAME, or add --to-revision=N to pick an older one, and follow it with kubectl rollout status. The rollback is itself a rolling update, so it respects maxSurge and maxUnavailable, and the restored template gets a new revision number. A paused Deployment must be resumed first, and changes to replicas, ConfigMaps or Secrets are not rolled back.

Spot a rollout that has gone wrong

A bad deploy rarely announces itself. The Deployment keeps serving from its old pods, and the rollout simply never finishes. kubectl rollout status with a timeout makes that visible, which is why a pipeline should always run it:

$ kubectl rollout status deployment/web --timeout=5s
Waiting for deployment "web" rollout to finish: 3 out of 5 new replicas have been updated...
error: timed out waiting for the condition

Here the new image tag did not exist, so the new pods sat in ImagePullBackOff. Other bad deploys look different: new pods in CrashLoopBackOff, pods Running but never Ready because a probe fails, or pods that are healthy but serve the wrong thing. In every case the quickest way back to a working service is the revision before.

Read the rollout history

kubectl rollout history lists the revisions the Deployment remembers, one per pod template:

$ kubectl rollout history deployment/web
deployment.apps/web
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

CHANGE-CAUSE is filled from the kubernetes.io/change-cause annotation, so it reads <none> unless your pipeline sets it. To see what a revision actually ran, ask for it by number:

$ kubectl rollout history deployment/web --revision=2
deployment.apps/web with revision #2
Pod Template:
  Labels:	app=web
	pod-template-hash=5974c5bb9c
  Containers:
   nginx:
    Image:	nginx:1.27
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>
  Node-Selectors:	<none>
  Tolerations:	<none>

How far back you can go is set by the Deployment's revisionHistoryLimit, 10 by default. Older ReplicaSets are deleted and their revisions with them.

Undo to the previous or a chosen revision

With no flags, undo goes back one revision, which is what you want straight after a bad deploy:

$ kubectl rollout undo deployment/web
deployment.apps/web rolled back

The history afterwards shows how undo works. It does not rewind: it copies the old template forward as a new revision. Revision 2 has gone from the list and come back as revision 4, after the failed revision 3:

$ kubectl rollout history deployment/web
deployment.apps/web
REVISION  CHANGE-CAUSE
1         <none>
3         <none>
4         <none>

That matters if you undo twice: the second undo goes back to the bad revision, because it is now the previous one. To land on a specific version, read the history and name it with --to-revision. A number that is no longer in the history is refused:

$ kubectl rollout undo deployment/web --to-revision=9
error: unable to find specified revision 9 in history

Pause a rollout that is still spreading

If a bad version is still replacing pods, kubectl rollout pause deployment/NAME stops it where it is, so fewer pods run the bad version while you read the history. Undo is refused while the Deployment is paused, because an undo is itself a rollout:

$ kubectl rollout undo deployment/web --to-revision=2
error: you cannot rollback a paused deployment; resume it first with 'kubectl rollout resume' and try again

Resume and undo straight after, then follow the rollback to the end:

  • kubectl rollout resume deployment/web
  • kubectl rollout undo deployment/web --to-revision=2
  • kubectl rollout status deployment/web until it prints successfully rolled out

Know what undo does not roll back

  • Only the pod template is versioned. The replica count, the update strategy and other Deployment fields stay as they are.
  • ConfigMaps and Secrets are separate objects. If a bad config change caused the outage, undoing the Deployment brings back the old template but not the old values, unless each version of the config has its own name.
  • If you manage manifests in Git or with a tool such as Helm, the next apply will put the bad version back. Revert it at the source too.

The missions below put this under pressure: a deploy that breaks mid-shift, and a release that has to be stopped before it reaches every pod. They check the cluster's state when you are done, so rolling forward with a fixed image passes too.

Practise it on a simulated cluster

These missions in the Kubernetes Simulator break a cluster in this way and leave you to fix it. Free in your browser, nothing to install.

Start Ship v2

Questions

Does kubectl rollout undo cause downtime?

No more than any other rollout. The rollback replaces pods using the Deployment's rolling update settings, so with the defaults some pods stay ready throughout. Because the old ReplicaSet still exists, the rollback starts immediately.

Can I roll back a StatefulSet or DaemonSet?

Yes. kubectl rollout history and kubectl rollout undo also work on StatefulSets and DaemonSets, which keep their revisions as ControllerRevisions. A StatefulSet rollback does not undo changes to data in its volumes.

Is it better to roll back or roll forward?

Roll back when you need the service working now and do not yet know the cause: the previous revision is known to work. Roll forward with a fix when it is small and certain. Either way, record what happened so the next deploy does not repeat it.

AboutGuidesCompare

PrivacyCookiesTerms

Hackademy is a trading name of Mather Software Ltd, registered in England and Wales, company number 17443861. ICO registration ZC256628.

Contact: support@mathersoftware.com© 2026 Mather Software Ltd