Kubernetes Deployment: Strategies, Explanation, and Examples

In Kubernetes, you can deploy a container in a pod with a simple one-line command. Such a level of simplicity is what makes Kubernetes a great container orchestration tool. However, when you want your application to be able to scale up or down, maintain replicas, and use custom services, you need a deployment.

In this blog post, we’ll cover the role of deployments, their benefits, how to create them, and how to use them.

What Is Kubernetes Deployment?

According to the Kubernetes documentation:

A Deployment provides declarative updates for Pods and ReplicaSets.

You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate.”

Notice the words highlighted with bold text. Deployments are effectively managing a collection of Pods. And their focus is on "declarative updates." Going from point A to point B, from current state to desired state "at a controlled rate."

At the end of the day, Kubernetes is a complex automation machine. We feed it definitions and tell it, "Hey, I want these objects, and I want things to run this way!" And it makes sure the objects exist and that things run that way.

Try the Kubernetes Deployments Lab for free

Kubernetes Deployments Lab
Kubernetes Deployments Lab

Try the Kubernetes Services Lab for free

The Role Kubernetes Deployments

It helps us change our applications' definitions. For instance, assume we don't want 100 Pods to run Nginx version 1.22.0 anymore - we want the newer version, 1.22.1. Deployments ensure that there are smooth transitions from the old definition to the newer definition.

Deployments can also be used for scaling up and down the number of Pods/replicas. For instance, we might want to run 100 Pods in the daytime when incoming traffic is high and a lower number at night when traffic is low. Deployments make it possible to automatically adjust the number of pods based on the users' traffic.

In a nutshell, Deployments help us periodically update large collections of Pods. It helps us scale the number of Pods as needed. And it even lets us undo an update action if things go wrong. This is called a rollback. We'll explore all of these possibilities in the last half of our blog; see actual commands we can use to do these things.

Deployment Strategies

Now imagine a Deployment that only handles 2 Pods. Let's say we want to upgrade the container definitions in our Pods. Instead of Nginx 1.22.0, we will use 1.22.1. There are two problems:

  1. Our Pods are actively receiving and processing users' requests.
  2. Kubernetes has to destroy the old Pods and create new ones that match our new definition.

But let's say this is fast. Kubernetes will destroy the two pods with Nginx 1.22.0. In a few seconds, two new pods with Nginx 1.22.1 are created. The problem? In those few seconds, while this happens, application users can't reach our service.

But Deployments are smarter than that. They support different deployment strategies which tell Kubernetes how to transition a collection of Pods. Let's see an example that would solve the problem we mentioned before.

Rolling Update Strategy (also Known as Incremental)

Now imagine the same situation as above. 2 Pods that we want to transition to run a newer version of some app. Instead of blindly destroying the old Pods, this deployment strategy will be more organized.

First of all, it will not touch the old Pods in the beginning. It will leave them alone so they can do their job, serving our users, even while we update. The Deployment will start out with a safer action.

It will add the new Pods. Once one new Pod is created, it can start to reroute traffic from the old pods to the new one, running the newer app. Since one new Pod is available, it can safely remove one or more old ones. And this way, our users can always reach our service.

While Kubernetes is replacing Pods, some users will reach the old Pods. But once the new Pods are ready, all users' traffic will be directed to them. And old Pods will be gradually removed until they're all gone.

For a setup with 100 Pods, it could go something like this: 3-4 new Pods get created, 3-4 old Pods get removed. Next, this step repeats, again and again, until bit by bit, all new Pods are added, and all old Pods are removed. At one point, we'd be in a situation where 50 new Pods are available, but 50 old Pods are still around. So it could be that 50% of our users are still reaching the old Pods, while 50% are reaching the new ones. This continues until 100% of old Pods are replaced with new Pods.

What is the advantage of this strategy? There is no downtime for our users.
The disadvantage? It can take a while until all Pods are replaced.

Here is an example of how we could pick this Deployment strategy in a manifest file:

spec:
  replicas: 10
  strategy:
        type: RollingUpdate
        rollingUpdate:
           maxSurge: 25%
           maxUnavailable: 25%  
  template:
  ...

maxSurge refers to the total number of Pods (old + new pods) that can exist during the update process. For instance, if we have a Deployment where we declare we want 100 Pods total. With a maxSurge of 25%, there can never be more than 125 total Pods during this update process.

maxUnavailable refers to how many Pods can be unavailable during the update process. Let's say we have the same 100 Pod Deployment. If maxUnavailable is set to 25%, there can never be fewer than 75 Pods during the update. This includes both old Pods and new Pods. It limits how many old Pods Kubernetes can remove while transitioning the Deployment to the new state.

Recreate Strategy

This is a two-stage process:

  1. First, all old Pods are deleted.
  2. Once all old Pods are destroyed, the new Pods are created.

This leads to downtime because once the Pods are deleted, the service is no longer available. Our users need to wait until all the new Pods are created to access the service again. That's why this strategy isn't recommended for production environments. Preferably, it should only be applied in testing environments.

Here's an example of a manifest file where we use the "Recreate" strategy for deployment.

​​spec:
  replicas: 3
  strategy:
    type: Recreate
  ...

Blue / Green (or Red / Black) Deployments

With this strategy, you leave the old Deployment alone. This will be the so-called "blue version." Next, you also launch a "green version" with the new Deployment. So you have blue and green running side by side. The disadvantage is that you have double the amount of Pods you require. If there were 300 Pods in your blue Deployment, you'd also have 300 in your green one. But only half of them are actively used, 300 in this case. But the advantages are many.

First, you can freely run tests on your new deployment and see if things run as expected. Once satisfied with the tests, you can transition your users to the green Deployment. And you get to the biggest advantage of this strategy: instant migration. You just tell Kubernetes to reroute all users' traffic from the blue Deployment to the green one. And that's all there is to it. Instant upgrade, essentially, as far as user experience is concerned. Of course, the last step would be to remove the old blue Deployment.

Here's an example of how we could switch traffic from a blue to a green Deployment. In a nutshell, we tell Kubernetes: "Hey, when you use this Service, send traffic to apps with this selector label."

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
    version: "03"

Canary

The canary deployment strategy involves routing a small group of users to the new version of an application, running on a smaller set of pods. This approach tests functionality on a smaller group of users instead of impacting the entire user base. Doing this contains the blast radius in the event of errors. Thus canary deployments help understand how new features will impact the overall system operation while containing the possible spillover to a small group of users.

This strategy is adopted to test new functionality in a production environment on real users. Once the application is tested and the results are satisfactory, replicas of the new version are scaled up while the old version is scaled down. We're essentially replacing the old version with the new one, but gradually.

Canary deployments can be rolled back very fast if there's a need. That's because they start out with a small percentage of new Pods. So a rollback has very few new Pods to revert.

Dark deployments or A/B Deployments

A dark deployment strategy is a variation of the canary deployment. The difference between a dark deployment and a canary is that dark deployment usually deals with features in the front end rather than the back end, as with canaries.

Dark deployments are also known as A/B Deployments. This approach introduces a new feature to a small set of users instead of all the users. The users are unaware they are treated as testers for a new feature; they are in the “dark” about their role as testers. In parallel, metrics are collected to track the user experience. Things like these can be monitored:

  • How are the users interacting with the feature?
  • Are they finding it intuitive and easy to use?
  • How many choose to disable this new feature?
  • And so on.

To learn more about when to use each of these deployment strategies, Check out this Kubernetes course:

Kubernetes for the Absolute Beginners – Hands-on Tutorial | KodeKloud
Learn Kubernetes with simple, easy lectures and hands-on labs

Creating a Kubernetes Deployment

There are two ways we can create a Deployment. One uses the imperative approach, and another uses the declarative approach. We will cover both approaches.

In a nutshell, the imperative is when we use commands, and the declarative is when we write YAML manifest files.

How to Create a Deployment Using the Imperative Approach

To create a deployment, we can use the command below. We'll need to specify the deployment_name and the image_name that we want to be used in the Pods.

$ kubectl create deployment <deployment_name> --image=<image_name>

Creating an Nginx Deployment using the imperative approach

Using the imperative approach, we can now create an Nginx Deployment:

$ kubectl create deployment mywebsite --image=nginx

This command creates a deployment called "mywebsite". The deployment will initially have an nginx Pod. We can scale the deployment to the desired number of Pods we want. Kubernetes will do the work of maintaining the desired state of the deployment.

We can check the deployment details using:

$ kubectl get deployment mywebsite

Deleting the Nginx Deployment

We can delete the Deployment with the following command:

$ kubectl delete deployment/mywebsite

Note how we first had to specify the resource type, "deployment", before actually specifying the deployment's name, "mywebsite".

$ kubectl delete <resource_type>/<resource_name>

The resource_type can be anything: Pod, Deployment, Service, Ingress, Config Map, Secret, Persistent Volume, etc.

How to Create a Deployment Using the Declarative Approach

Using the declarative approach, we can define a Deployment along with its configuration in a YAML file. Here's an example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mywebsite
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.22.0
        ports:
        - containerPort: 80

This configuration can be applied to create a Deployment exactly like the one we created using the imperative approach. If we'd save the content above, in a file called deploy.yaml, we could then apply this to Kubernetes with the following command:

$ kubectl apply -f deploy.yaml

Update Kubernetes Deployment

We can use the set command to make changes to an object's image, resources (compute resources such as CPU and memory), or other configuration fields.

For example, to update a Deployment from nginx version 1.22.0 to 1.22.1 run the following command:

$ kubectl set image deployment mywebsite nginx=nginx:1.22.1

Deployment Rollouts: Check History, Pause, Resume, or Undo/Rollback Changes

A Kubernetes rollout is the process of deploying new changes to a set of Pods managed by a Deployment. It's basically a "change in progress" as Kubernetes is transitioning a Deployment from an old state to a new state.

We can check the status of a rollout using the rollout command as shown below:

$ kubectl rollout status deployment mywebsite
Waiting for deployment "mywebsite" rollout to finish: 1 out of 3 new replicas have been updated...

To pause a rollout, we can use the following command:

$ kubectl rollout pause deployment mywebsite

To resume a deployment, we can use the following command:

$ kubectl rollout resume deployment mywebsite

To see the history of rollouts a Deployment has been through:

$ kubectl rollout history deployment mywebsite

The history will show a list of so-called "revisions". We'll see what these are in the next command after this one.

To see the details of a specific revision, for example, revision 1:

$ kubectl rollout history deployment mywebsite --revision 1

Whenever we make a change to a deployment, we arrive at something called a new revision. This serves as a sort of snapshot, a state we can return to if there's ever a need. To undo a deployment change and revert to the previous revision, we can use the following command:

$ kubectl rollout undo deployment mywebsite

To revert to a specific revision, we can use the following command:

$ kubectl rollout undo deployment mywebsite --to-revision 1

Scaling Kubernetes Deployment

Manually

Once a deployment is created, we can use the scale command to scale the deployment up or down to match our requirements. The following command can be used to scale the deployment to 3 Pods (called replicas since these are identical):

$ kubectl scale deployment mywebsite --replicas=3

If we want to delete all the Pods in the Deployment without deleting the Deployment itself, we can scale the replicas to 0. A neat trick to keep the deployment available while effectively deleting all Pods.

$ kubectl scale deployment mywebsite --replicas=0

To verify if the scale command took effect, you can check the status of this deployment:

$ kubectl get deployment mywebsite
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
mywebsite   0/0     0            0           7m48s

By Configuring an Auto-Scaling Rule

A HorizontalPodAutoscaler (HPA) automatically updates a Deployment or StatefulSet. The HPA autoscales the resources based on the demand. HPA does not apply to objects that can't be scaled like a DaemonSet.

The HPA spins up new Pods in response to an increase in the load. Scaling is performed based on memory or CPU usage. We have the option of defining the max and min scale limits, which means that we can set the maximum number of Pods that can be scaled and the minimum number of Pods. Once the load decreases, the HPA scales down the pods.

Now, we can deploy an application on the cluster and then enable the horizontal pod autoscaler. This can be done using the following command:

$ kubectl autoscale deployment mywebsite --cpu-percent=50 --min=1 --max=10

The --cpu-percentage flag is used to define the CPU percentage based upon which the autoscaling happens. For example, if the mywebsite Pods exceed 50% CPU the autoscaler will create a new Pod. The --min and --max flags are used to define the minimum and maximum number of Pods that the autoscaler can scale to.

We can check the HPA by running the kubectl get hpa command as shown below:

$ kubectl get hpa
NAME         REFERENCE                TARGET CURRENT MINPODS MAXPODS AGE
mywebsite    Deployment/mywebsite/scale   50%    310%    1       10      2m

Want to learn more about the basics of Kubernetes? Check out this video.

Conclusion

We hope this gives you a basic idea of what you can do with Deployments. If you're still new to Kubernetes, you can check out this Kubernetes Course for Beginners.

Kubernetes certification exams

To boost your professional credibility, you can earn certifications like CKAD, CKA, and CKS, which will attest to your expertise in Kubernetes. The courses below will help you prepare for these three in-demand certifications.

Don’t know where to start your certification journey, check out the blog CKAD vs. CKA vs. CKS.

To learn more about the three certifications, check out our CKA, CKAD, CKS - Frequently Asked Questions blog.


More on Kubernetes: