Introduction: Production-Ready Deployment Management

In the previous lesson, you successfully updated your Deployment from nginx:1.25 to nginx:1.26 using Kubernetes' default rolling update behavior. The update worked smoothly, but you relied entirely on Kubernetes' default settings for how quickly the update happened and how many Pods could be unavailable at once. In production environments, you need more control. What if your application needs to stay highly available during updates, or what if you need to update faster because you're fixing a critical security vulnerability? Even more importantly, what happens when an update introduces a bug and you need to quickly revert to the previous working version?

This lesson teaches you how to take control of your deployment strategy by configuring the maxSurge and maxUnavailable parameters to balance speed and availability. You'll also learn how to track your deployment history and perform rollbacks to recover from failed updates. These skills are essential for managing production releases safely and confidently.

Controlling Update Pace with maxSurge and maxUnavailable

When Kubernetes performs a rolling update, it needs to make decisions about how aggressively to replace old Pods with new ones. Should it create all new Pods at once for maximum speed, or should it be more conservative to minimize resource usage? Should it allow some Pods to be unavailable during the update, or should it guarantee that the full replica count is always available? These decisions are controlled by two parameters: maxSurge and maxUnavailable. Understanding these parameters gives you precise control over how your updates behave.

The maxSurge parameter defines how many Pods can exist above your desired replica count during an update. Think of it as your "burst capacity" during the transition. If you have a Deployment with 3 replicas and set maxSurge: 1, Kubernetes can temporarily create a 4th Pod while the update is in progress. This extra Pod allows Kubernetes to bring up new Pods before terminating old ones, which speeds up the update and ensures you always have at least your desired number of Pods running. You can specify maxSurge as an absolute number (like 1 or 2) or as a percentage (like 25% or 50%). A higher maxSurge value makes updates faster but uses more resources temporarily. A lower value conserves resources but slows down the update.

Let's look at concrete examples. With maxSurge: 1 on a 3-replica Deployment, Kubernetes can have 4 Pods running simultaneously during the update. It creates one new Pod, waits for it to become ready, then terminates one old Pod. With maxSurge: 2, Kubernetes could have up to 5 Pods running at once, creating two new Pods before terminating any old ones. This makes the update faster because more new Pods can start in parallel. With on a 3-replica Deployment, Kubernetes calculates 50% of 3 (which rounds up to 2), so it can have up to 5 Pods running during the update, just like setting explicitly.

Defining the Rolling Update Strategy in YAML

Now that you understand what maxSurge and maxUnavailable control, let's see how to configure them in your Deployment manifest. Kubernetes uses a strategy section in the Deployment spec to define how updates should be performed. This section sits at the same level as replicas and selector in your YAML file. By explicitly defining your strategy, you take control away from Kubernetes' defaults and specify exactly how you want updates to behave.

The strategy section has two main components: the type field and the rollingUpdate configuration. The type field tells Kubernetes which update strategy to use. The two options are RollingUpdate (the default, which gradually replaces Pods) and Recreate (which terminates all old Pods before creating new ones, causing downtime). For this lesson, you'll use RollingUpdate because it maintains availability. Even though RollingUpdate is the default, it's good practice to specify it explicitly so anyone reading your YAML knows your intention.

Inside the rollingUpdate section, you define your maxSurge and maxUnavailable values. These parameters only apply when using the RollingUpdate strategy. Let's build a complete example that sets conservative values to prioritize availability. You'll use to allow one extra Pod during updates and to allow one Pod to be unavailable, which provides a balanced approach between speed and availability.

Tracking Deployment History

Before you start updating your Deployment, it's important to understand how Kubernetes tracks the history of changes. Every time you update a Deployment's Pod template (by changing the image, environment variables, or other container settings), Kubernetes creates a new revision. These revisions are numbered sequentially, starting from 1. Kubernetes keeps track of these revisions so you can see what changed over time and, more importantly, so you can roll back to a previous revision if needed.

The revision history is stored in the ReplicaSets that Kubernetes creates for each version of your Deployment. Remember from the previous lesson that when you update a Deployment, Kubernetes creates a new ReplicaSet for the new version while keeping the old ReplicaSet around with zero replicas. Each of these ReplicaSets represents a revision in your deployment history. By default, Kubernetes keeps the last 10 ReplicaSets, which means you can roll back up to 10 versions. You can change this limit by setting the revisionHistoryLimit field in your Deployment spec, but 10 is usually sufficient.

Kubernetes provides the kubectl rollout history command to view your deployment's revision history. This command shows you a list of all revisions, along with information about what changed in each revision. Let's create your Deployment and look at its initial history:

You'll see confirmation that the Deployment was created:

Now check the rollout history:

You'll see output showing the current revision:

Right now, you only have revision 1 because you just created the Deployment. The CHANGE-CAUSE column is empty because you haven't annotated your changes with descriptions. In production environments, it's helpful to add a kubernetes.io/change-cause annotation to your Deployment to document what each revision changed. For example, you might annotate a revision with "Updated to nginx 1.26 for security patch" so your team knows why the change was made. For this lesson, we'll keep it simple and not worry about change-cause annotations.

Applying the Update and Watching the Rollout

Now let's trigger a rolling update by changing the container image from nginx:1.25 to nginx:1.26. This will create a new revision and let you observe how your custom maxSurge and maxUnavailable settings affect the update process. Create a new file called deployment-strategy-updated.yaml with the updated image version:

The only change is the image: nginx:1.26 line in the container specification. Everything else, including your strategy configuration, remains the same. Apply this updated manifest:

You'll see confirmation that the Deployment was updated:

Immediately after applying the update, watch the rollout progress in real time:

You'll see output tracking the update as it happens:

Rolling Back to Previous Versions

Sometimes updates don't go as planned. Maybe the new version of your application has a bug that wasn't caught in testing. Maybe it performs poorly under production load. Maybe it's incompatible with another service in your cluster. Whatever the reason, you need a way to quickly revert to the previous working version. This is where rollback becomes essential. Kubernetes makes rollback simple by leveraging the ReplicaSet history it maintains for your Deployment.

When you roll back a Deployment, Kubernetes doesn't actually undo your changes or modify your YAML files. Instead, it scales up the old ReplicaSet (the one from the previous revision) and scales down the current ReplicaSet. This is the same rolling update process you've already seen, just in reverse. The old Pods come back, and the new Pods are terminated. From Kubernetes' perspective, a rollback is just another rolling update — it's updating from the current version back to a previous version.

The kubectl rollout undo command performs a rollback. By default, it rolls back to the immediately previous revision, but you can also specify a particular revision number if you want to roll back further. Let's roll back your Deployment from nginx:1.26 (revision 2) back to nginx:1.25 (revision 1):

You'll see confirmation that the rollback started:

Immediately watch the rollback progress:

You'll see output similar to a regular rolling update:

The rollback uses the same maxSurge and maxUnavailable settings you configured, so it proceeds with the same balance of speed and availability. Kubernetes is creating Pods with the image (from revision 1) and terminating Pods with the image (from revision 2). Your application is now running the previous version again.

Summary and Practice Preview

You now know how to control the pace of rolling updates using the maxSurge and maxUnavailable parameters in your Deployment's strategy section. These settings let you balance update speed, resource usage, and availability guarantees based on your application's needs. You've learned how Kubernetes tracks deployment history through revisions, how to view that history with kubectl rollout history, and how to perform rollbacks using kubectl rollout undo to quickly recover from problematic updates.

These skills are essential for managing production deployments safely — you can update confidently knowing you have a quick escape hatch if something goes wrong. In the upcoming practice exercises, you'll experiment with different strategy configurations and practice rolling back deployments to build confidence in these critical production skills.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal