Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 17

Managing Rolling Updates and Rollbacks

Recommended resources

Hello! Let's continue our journey through Kubernetes.

In our last lesson, we saw how to use a Deployment to run and scale a stateless application, ensuring a specific number of Pods are always available. This solved the problems of availability and basic scalability. But in the real world of platform engineering, applications are never static; they evolve constantly.

This brings us to a critical question: how do you update a running application to a new version without causing downtime for your users? Today's lesson will answer that by diving into one of the most powerful features of Kubernetes Deployments. We will focus on how to perform rolling updates to deploy new versions of your application seamlessly and how to perform rollbacks to quickly revert to a stable state if something goes wrong. This is a core competency for any DevOps or Platform Engineer.

1. The Rolling Update Strategy

When you update a Deployment, you don't want to terminate all old Pods at once and then create new ones. That would cause an outage. Instead, Kubernetes uses a rolling update strategy by default. This strategy gradually replaces old Pods with new ones, ensuring the application remains available throughout the process.

This process is controlled by two key parameters in your Deployment's manifest, under spec.strategy.rollingUpdate:

  • maxUnavailable: The maximum number of Pods that can be unavailable during the update. This can be an absolute number (e.g., 1) or a percentage of the total replicas (e.g., 25%). A lower value ensures higher availability.
  • maxSurge: The maximum number of Pods that can be created above the desired number of replicas. This can also be an absolute number or a percentage. This allows Kubernetes to bring up new Pods before taking down old ones, speeding up the update.

The following video provides a clear, concise explanation of how these two parameters work together to orchestrate a zero-downtime deployment.

Most Common Kubernetes Deployment Strategies (Examples & Code)

Let's start with a clear visual explanation from Anton Putra on the default rolling update strategy and the roles of maxUnavailable and maxSurge.

Watch from 01:36 to 03:42. Focus on how Kubernetes uses the default 25% for both parameters to gradually roll out a new version without interrupting service.

As the video explains, if you have 4 replicas and the default settings (maxUnavailable: 25%, maxSurge: 25%), Kubernetes will:

  1. Ensure no more than 1 Pod (25% of 4) is unavailable at any time.
  2. Allow the creation of at most 1 new Pod (25% of 4) above the desired replica count of 4, for a temporary total of 5 Pods.

The process typically looks like this:

  1. A new Pod with the new image version is created (total Pods: 5).
  2. Kubernetes waits for the new Pod to become Ready (this is where readiness probes are critical!).
  3. Once the new Pod is ready, an old Pod is terminated (total Pods: 4).
  4. This cycle repeats until all Pods are running the new version.

resource_title

A visual comparison of the Recreate strategy (left), which causes downtime, and the Rolling Update strategy (right), which maintains availability by incrementally replacing Pods. This diagram is from the KodeKloud article "Rolling Updates Rollbacks", which we will refer to later.


2. Performing a Rolling Update

Now, let's trigger an update. The most common ways are:

  • Declarative (Recommended): Modify the image tag in your Deployment YAML file and apply it with kubectl apply -f your-deployment.yaml. This aligns with GitOps principles, where your Git repository is the source of truth.
  • Imperative (Quick & Easy): Use the kubectl set image command. This is great for quick changes or scripting.

Let's focus on the imperative command for now. If you have the nginx-deployment from the previous lesson, you can update its container's image like this:

# First, check the current image of your pods
kubectl describe deployment nginx-deployment | grep Image

# Now, trigger the update to a new version
kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3

As soon as you run this command, the Deployment controller starts the rolling update process.

Kubernetes Deployments: A Guide to the Rolling Update ...

This article from Semaphore provides a detailed walkthrough of the entire update process, from configuration to execution and monitoring.

Read the section 'Performing a Rolling Update'. It demonstrates how to use kubectl set image to trigger the update and how to use kubectl get pods to observe the Pods being terminated and created. Also, pay close attention to the kubectl rollout status and kubectl rollout history commands, which are essential for monitoring.

Monitoring the Rollout

While the update is in progress, you can monitor it in real-time. Open a new terminal and run:

kubectl rollout status deployment/nginx-deployment

You'll see messages indicating the progress, like "Waiting for rollout to finish: 2 of 3 new replicas have been updated...".

You can also use the --watch flag to see the Pods cycling through their states:

kubectl get pods -l app=nginx --watch

You will see old Pods Terminating and new Pods ContainerCreating, then Running.


3. Handling Failed Updates and Rolling Back

What happens if you accidentally push a bad image tag, like nginx:1.99.9 (which doesn't exist)? The rolling update will start, create a new Pod, but that Pod will fail to pull the image and get stuck in an ImagePullBackOff state.

Because the new Pod never becomes Ready, Kubernetes is smart enough to halt the rollout. Your application remains available, running on the remaining old Pods, but the deployment is in a broken, partially-updated state.

This is where rollbacks become your safety net.

Checking Deployment History

Kubernetes keeps a history of each change you make to a Deployment. You can view this history with:

kubectl rollout history deployment/nginx-deployment

This will show you a list of "revisions". Each time you update the Deployment's template (e.g., change the image), a new revision is created.

Performing a Rollback

If you detect an issue with your latest deployment (revision), you can immediately revert to the previous stable revision with a single command:

kubectl rollout undo deployment/nginx-deployment

This command triggers another rolling update, but this time the "new" version is the configuration from the previous revision. The process is identical: old (broken) Pods are gradually replaced by new (working) Pods.

The following video demonstrates a full cycle: updating, seeing the rollout, and then using undo to roll back.

Most Common Kubernetes Deployment Strategies (Examples & Code)

Let's watch a practical demonstration that includes not just the update, but also the crucial undo command for rollbacks.

Watch the segment from 06:17 to 07:53. The presenter first triggers an update, then demonstrates using kubectl rollout pause, resume, and finally undo to revert the deployment to its previous version.

You can also roll back to a specific, older revision if needed. For example, if you know revision 2 was the last stable one:

kubectl rollout undo deployment/nginx-deployment --to-revision=2
Test your understanding!

You have deployed a new version of your application. Your monitoring system starts firing alerts, and you suspect the new code is buggy. You check the rollout history and see the following:

REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment/webapp webapp=app:v1.1 --record
3         kubectl set image deployment/webapp webapp=app:v1.2 --record

You are currently on revision 3, which is faulty. You want to go back to the last known stable version, v1.1. What command should you run?

Show answer

You should run the command:
kubectl rollout undo deployment/webapp --to-revision=2

While kubectl rollout undo deployment/webapp would also work in this case (as it rolls back to the previous revision, which is 2), explicitly specifying --to-revision=2 is more precise and safer, especially if there were intermediate failed rollouts. The CHANGE-CAUSE column, populated by the --record flag, helps you identify which revision corresponds to which version tag.


Conclusion

You now have the tools to manage the complete lifecycle of a stateless application in Kubernetes. By leveraging rolling updates, you can deploy changes with confidence, knowing that your application will remain available. And with rollbacks, you have a powerful safety mechanism to quickly recover from failed deployments.

Key Takeaways:

  • Rolling Updates are the default strategy for Deployments, ensuring zero downtime by gradually replacing Pods.
  • The rollout process is fine-tuned using maxSurge and maxUnavailable.
  • Updates are triggered declaratively with kubectl apply or imperatively with kubectl set image.
  • You can monitor a rollout with kubectl rollout status and view past changes with kubectl rollout history.
  • If a new version is faulty, you can instantly revert to the previous stable version using kubectl rollout undo.
  • Kubernetes automatically halts a rollout if new Pods fail to become Ready, preventing a complete outage.

In our last few lessons, we've focused on running the application itself. But applications need configuration—database URLs, API keys, feature flags, etc. Hardcoding these into your container image is a bad practice. In our next lesson, we will explore ConfigMaps and Secrets, the Kubernetes-native way to manage application configuration and sensitive data.