Right, so you’ve done it. You’ve issued a kubectl apply -f deployment.yaml with the serene confidence of a master engineer, only to watch your application immediately catch fire and start screaming in a language you don’t understand. The new container image you just deployed is a complete dud. Maybe it’s a bug. Maybe you forgot to build the binary. Maybe it’s Maybelline. It doesn’t matter. What matters is that you need to get back to the last known good state, and you need to do it now. This is where kubectl rollout undo earns its place in the hall of fame of indispensable commands.

Think of a Deployment not as a static declaration but as a timeline. Every time you update the Deployment—changing the image, environment variables, resource limits, anything—Kubernetes records a new “revision” of it. It’s like version control for your desired state. The rollout undo command is simply telling Kubernetes: “Hey, remember that revision from right before I so brilliantly broke everything? Yeah, let’s just pretend I meant to do that one instead.”

How rollout undo Actually Works (It’s Not Magic)

Contrary to what the name might imply, undo doesn’t perform some complex, stateful reversal. It doesn’t surgically remove the bad Pods. It’s much simpler, and therefore more robust: it literally rolls back to a previous revision. Here’s the play-by-play:

  1. You run kubectl rollout undo deployment/my-app.
  2. The Kubernetes API server looks up the Deployment’s history. It finds the current revision (the broken one, let’s call it revision 5) and the previous one (the good one, revision 4).
  3. It effectively reapplies the entire Pod template spec from revision 4. It’s as if you had run kubectl apply with the old YAML file from five minutes ago.
  4. The Deployment controller notices the Pod template has changed (back to the old spec) and kicks off a new rolling update, exactly like it did when you deployed the bad version, but in reverse. It starts bringing up Pods from revision 4 and gracefully terminating Pods from revision 5.

The beauty is that it uses the exact same, battle-tested rolling update mechanism you used to deploy forward. You’re not invoking some special, less-tested “rollback” procedure. You’re just deploying an old version, which is something Kubernetes does all day long.

The Most Basic (and Lifesaving) Command

The syntax is so simple it feels like cheating. To revert your my-app deployment to its previous state:

kubectl rollout undo deployment/my-app

That’s it. Watch the magic happen with:

kubectl rollout status deployment/my-app

You should see the new Pods (with the old, working image) come up and the bad ones get terminated. The Deployment will update its revision history. Your previously “current” revision (the broken one) becomes revision 6, and the reverted state becomes the new current revision (which is identical to the old revision 4). Yes, the numbering can get a bit confusing. Which brings us to…

Going Beyond “Just Undo”

What if the previous revision isn’t the one you want? Maybe you’ve already done one undo, or you need to jump back several versions. This is why you need to be friends with the history command.

First, view the rollout history to see your options:

kubectl rollout history deployment/my-app

You’ll get a list that looks something like this:

REVISION  CHANGE-CAUSE
1         kubectl apply --filename=deployment.yaml --record=true
4         kubectl apply --filename=deployment-v1.1.yaml --record=true
6         kubectl apply --filename=deployment-v1.2-broken.yaml --record=true

See those CHANGE-CAUSE fields? They’re gold. They only get populated if you used the --record flag with your kubectl apply or kubectl create commands. This is a crucially important habit. Without it, the history is just a list of revisions with no clue what each one did.

Now, to revert to a specific revision, not just the previous one:

kubectl rollout undo deployment/my-app --to-revision=4

This command tells Kubernetes to use the Pod template from revision 4 as the new desired state.

Common Pitfalls and The “Oh Crap” Moment

  • No History: The biggest pitfall is having no history. If you only ever use kubectl set image deployment/my-app my-app=my-image:new-tag to update your Deployments, you’re not creating new revision history. You’re just editing the live object. The undo command will have very little to work with. Always, always manage your Deployments via declarative YAML files applied with kubectl apply. Using --record is a good second line of defense.
  • What’s in a Revision? The revision history stores the entire Pod template. It’s not just the image. If you changed a resource limit or an environment variable between revisions 4 and 5, rolling back to 4 will revert those changes too. This is usually what you want, but it’s good to be aware of.
  • History Limits: By default, a Deployment’s revision history is limited to 10 revisions. Old ones are cleaned up. You can change this with the revisionHistoryLimit field in your Deployment spec, but be mindful that storing thousands of revisions is probably overkill.

So, the next time you deploy a howler, don’t panic. Just undo. It’s the closest thing to a time machine we’ve got in this business.