Kubernetes Deployments: Basic to Deployment Strategies

Kubernetes works highly distributedly, as multiple different components are used to deploy an application and ensure that it stays healthy. The smallest unit of Kubernetes is a pod. The container that is running the application code runs inside the pod. One of the major challenges of running an application in pods is that pods are ephemeral by nature. If the pod gets destroyed, it will not be recreated. 

Kubernetes has a few ways of ensuring that pods are recreated if they are destroyed. Whenever a pod is destroyed, Kubernetes can recreate it to ensure that the application continues running without any kind of service disruption. This process of self-healing the pod is done by a Kubernetes object known as a deployment. To learn more about all the different types of Kubernetes workloads, please read this blog.

In this blog, we will be taking a deep dive into the Kubernetes deployment object, what it does, and how to create it. We will also be looking at some deployment strategies which can be defined using the Deployment object.

What is a Kubernetes Deployment?

A Kubernetes deployment is an object that helps deploy and run the application in any Kubernetes environment. It allows you to declaratively define the application's state, such as the image being used, its environment variables, the desired number of pod replicas, and more. Once the Kubernetes deployment is created, the backend of Kubernetes manages the application’s entire lifecycle without requiring any actions from the user.  

The Kubernetes Deployment object allows you to templatize the creation of your pods in a declarative manner and helps manage the pod in a way similar to the GitOps approach. The Deployment object creates and manages the actual pods. In case the pod gets destroyed, the Kubernetes mechanisms take over to re-create the pod and ensure that the cluster is in the desired state. This removes the manual intervention from users for manually updating and deploying applications which can be both time-consuming and prone to human error. If you wish to learn about the different mechanisms of Kubernetes, please check out our blog on the Kubernetes architecture.

The Kubernetes deployment object also supports two deployment strategies out of the box which helps deploy pods with updated configurations while ensuring that there is no downtime for applications. The two strategies include rolling updates and a recreate strategy. Later in this blog, we will be looking at these deployment strategies more in-depth.

Kubernetes Deployments vs Pods

Pods and Deployments are both critical Kubernetes components needed to run applications in any environment. However, Both Deployments and Pods serve two very different purposes. Pods and Deployments work together to ensure that the application is running at all times.

A Pod is the smallest deployable unit in Kubernetes. Inside a pod, you have the actual application container which contains the application code, dependencies, and other components required to run the application. A pod also has its own distinct network and storage resources attached to it. These network and storage resources are shared between all the containers within the pod. These pods can host the entire application, or if you choose a microservice architecture, the pod can have an individual component of the entire application.

When a developer or cluster operator creates a pod for running an application, Kubernetes automatically runs and manages the pods. When the pod has been defined, Kubernetes decides on which node should each pod run on, and it automatically restarts the pod in case it fails. This process of assigning nodes to pods is known as Kubernetes Scheduling. Please read this blog to learn about the Kubernetes scheduling mechanisms.

A Kubernetes Deployment object is a tool that helps automatically control and manage the behaviour of pods. By default, Kubernetes creates only one instance of a pod, and if the pod gets deleted, it is gone forever. By using the deployment object, you can have multiple instances of the pods. If the actual number of pods does not meet the desired number of pods, the Kubernetes Deployment will recreate pods to match the desired state. Behind the scenes, the Deployment object creates a ReplicaSet to manage the number of pods that are running.

A Kubernetes deployment object eliminates the need for cluster administrators and developers to manually control the pod's behaviour. It allows users to declaratively configure all the steps needed to run the pod, including the number of replicas, the image to be used, the storage resources, etc. This helps operators save time, as they have to write a single file to apply changes or updates to the entire cluster. 

Kubernetes Deployments vs StatefulSets

A StatefulSet is a Kubernetes API Object designed for deploying and managing stateful workloads such as databases on Kubernetes. When a StatefulSet is created, it is ensured that the pods are created in a specific order and there is a persistent volume assigned to the pods. StatefulSets also have persistent networks which ensures that the IP address of the pods stays the same even if the pod is deleted or rescheduled.

StatefulSets are similar to deployments in the sense that they manage the behaviour and lifecycle of pods. However, the key difference between the two is that Deployments are designed to run stateless applications whereas statefulSets are designed to run stateful applications. When a statefulSet is used to deploy an application, the pods of the statefulset have a unique identifier that makes it possible to maintain a persistent state across the pod’s entire lifecycle.

When you create a deployment and a statefulset, you can notice that the pods created by the deployment have a random value assigned to the pod name. On the other hand, the pods of the statefulset are numbered sequentially to ensure that each pod has its own unique identifier and that the state can be maintained.

[Fig.1] Deployment vs StatefulSets

Deployment

StatefulSet

Designed for stateless application deployments

Designed for stateful application deployments

Pods have a random identifier to ensure uniqueness

Pods have a sequential identifier to the main read/write order to persistent storage

All Replicas share the same volume and PersistentVolumeClaim

All Pod replicas have unique volumes and PersistentVolumeClaims

Kubernetes Deployments vs ReplicaSets

A ReplicaSet is a Kubernetes object that ensures that the pod stays running at all times. Within a ReplicaSet, you can define a certain number of pods that should be running at all times. The ReplicaSet ensures that the desired number of pods are met. The goal of using a ReplicaSet is to ensure that the application has enough resources in the pod and that there are enough pods to handle the incoming traffic requests.

When a pod faces an error or gets destroyed, the ReplicaSet ensures to immediately create a new pod to replace the failed pod. At any given point in time, if the actual number of running pods does not match the number of desired pods, the ReplicaSet will quickly scale the number of pods and create new pods based on the pod template defined in the ReplicaSet’s configurations. A ReplicaSet can also help distribute the traffic among the different pods that are created by it.

A Kubernetes deployment, on the other hand, is a higher-level object than a ReplicaSet. A Deployment is essentially used to manage a Kubernetes Replica Set. A Replica Set can only ensure that the desired number of pods are created and that they stay running. If you wish to pass updates to your deployment configuration, such as changing the image or changing environment variables, a Replica Set falls short in this regard. A Deployment can help to declaratively define the state of the application container and progressively update the applications.

Within the official Kubernetes documentation, it is recommended that users do not directly work with ReplicaSets. Instead, as a user you can create a deployment and StatefulSet, and allow these objects to create the replicaset to handle their own management activities.

Kubernetes Deployment Status and Lifecycle

When a deployment object is created, there are a few different stages that it goes through. Let’s take a look at how the entire lifecycle of the Deployment progresses.

  • Progressing Deployment: When you create the deployment, it will first be progressing. During the progressing state, it will create all the necessary objects with the desired components. The tasks that occur in this stage include the creation of the ReplicaSet, the Scaling of the ReplicaSets, and the creation of required pods.
  • Complete Deployment: When all the Kubernetes components have been successfully created, the deployment is marked as completed. The deployment is marked as completed when all the ReplicaSets have been created, or updated in case of rolling updates, and when there are no replicas for the older version of the pod.
  • Failed Deployment: There are times when the deployment can encounter some issues while creating its required pods and replicasets. In these scenarios, the deployment object will have a failed state. Some common causes for deployment failures include insufficient resource quotas, image pull errors, readiness probe failures, insufficient permissions, or application runtime misconfigurations. To understand why the deployment is failing you can use the command: kubectl rollout status <deployment-name>

Kubernetes Deployment Example

Let’s take a look at how you can create a deployment object declaratively using YAML files. 

We will be using the below YAML file to create a Deployment object for an nginx pod. The below file will create a replicaset, which will then proceed to create 5 replicas of the nginx pod. The pods will be using the nginx:latest image. We will break down everything going on in this YAML file shortly.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deployment
  name: nginx-deployment
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx-deploy
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      containers:
        - name: nginx
          image: nginx:1.26
          ports:
            - containerPort: 80

Let’s understand what’s happening in the above YAML manifest.

  • Kind: The type of Kubernetes resource being deployed. In this case, it’s a deployment
  • Labels: Labels to identify the resource. 
  • Name: Name of the deployment. Here, we are calling it as nginx-deployment
  • Spec: The configuration files for the deployment object
  • Replicas: The number of pod replicas to maintain at any given point in time. Here, we are defining that we want 5 pod replicas to be running at any given time.
  • Selector: The deployment object uses the selector to identify the pods to manage
  • Template: The template used to create the pod.

Save the above YAML manifest in a file called as deployment.yaml, and run the below command to start creating the deployment, replicasets, and pods.

kubectl apply -f deployment.yaml

You can check the status of the deployment and resources by using the below commands

kubectl get deployments # Check the Deployments
kubectl get replicasets # Check the replicasets
kubectl get pods # Check the Pods
[Fig.2] Deployments Deployed

Once you see that all the pods are up and running, you have successfully created a deployment object. If you wish to scale the deployment, you can do so using the kubectl scale deployment command.

Kubernetes Deployment Strategy

A deployment strategy is used to progressively roll out application updates without facing service disruptions. 

By default, Kubernetes has two deployment strategies that it provides out of the box; Rolling updates and Recreate. Let’s explore these deployment strategies as well as more advanced strategies.

Recreate Deployment

When using the recreate deployment strategy, all the pods of the older version are instantly destroyed. These pods are then replaced with pods that contain the application's newer configuration. Using this strategy in a production environment is not recommended, as it will lead to significant downtime. 

The Recreate strategy should only be used in environments where downtime is acceptable, such as developer environments where the developers may not actively be using the instances. 

Rolling Update Deployment

A rolling update deployment strategy is a way to progressively roll out a new application version while ensuring that there is no downtime experienced. A Kubernetes deployment supports the rolling update strategy out of the box. When using this strategy, the older pods will slowly get replaced by the pods with the newer configurations. 

The rolling updates deployment strategy can help you to upgrade applications to newer versions safely and without experiencing downtime. However, the rolling strategy can take some time to fully update every pod depending on the scale of the application. While the deployment is progressing, it can be difficult to trigger a rollback or interrupt the process.

Blue/Green Deployment

The blue/green deployment strategy helps you to quickly switch from an older application version to a newer application version. This also helps test the newer version in production while ensuring that users can easily be rolled back to a previous version. The older deployment version is called the “blue” version while the newer version is called as the “green” version. 

After the “green” application version is fully deployed to the cluster, you can start routing the traffic from the old “blue” version to the newer “green” deployment. Please check out our in-depth guide on Blue/Green Deployments to learn more about them.

Canary Deployment

Similar to the blue/green deployment, in a canary deployment there are two versions of the application that are deployed at the same time. A small number of users are redirected to the newer version of the application. There are a small number of pods running the new application version to test how it behaves in a production environment. If no major bugs are found in the newer version, the Canary version is gradually expanded until the older version is completely replaced. 

Canary deployments are useful for releasing an application to a small group of users and testing it in production environments. In case there are any errors, a canary deployment can easily be rolled back to the previous version. Due to this, Canary deployments are very useful for seeing how newer code will affect the entire system as a whole. 

Please check out our blog on Canary Deployments to learn more about them.

A/B Testing

Within the A/B testing deployment strategy, the newer version of the software is released to only a small group of users. While A/B testing is generally confused with blue-green deployments, the two are not the same. The biggest difference between the two is that the A/B testing strategy is mainly used to test new features in your applications such as a new design, a new UX, noticeability, etc. 

The main distinction is that the blue-green strategy is used for actually releasing the updates in batches so that rollbacks are easier to perform in case of any errors. A/B testing on the other hand is for measuring functionality in the application.

Shadow Deployment

When choosing the Shadow deployment strategy, any changes to an application are deployed in a parallel environment that mimics the production environment. The deployed changes are not visible to the end-users, hence the term “shadow.” This kind of hidden deployment makes it possible to observe the application's behaviour and the impact of its changes without causing any service disruption to the live application. 

The primary purpose of shadow deployment is to test real-world application behaviour under load, identify performance bottlenecks, and ensure that the application changes don’t affect the user experience negatively. It allows developers to test changes in an environment that closely replicates the live production environment, thereby reducing the risk of unforeseen issues cropping up post-deployment.

Shadow deployments provide a safety net to developers and help ensure a smooth transition when the changes are finally deployed to the live environment.

Challenges of Kubernetes Deployment Mechanism

Out of the box, the Kubernetes deployment object only supports the Recreate and RollingUpdates deployment strategies. Recreate is not a strategy that can progressively update applications. It destroys the older version and deploys the newer version which will lead to downtime. RollingUpdates on the other hand can help progressively deliver an application without downtime, but provides only a basic set of safety guarantees during an update. It is suitable for some application update scenarios but can be lacking in others.

The rolling updates deployment strategy has many limitations such as limited control over the speed of the rollout, cannot control traffic flow to the new version, is not suitable for stress tests or one-time tests, cannot query external metrics to verify an update, and not able to abort and rollback the application update. 

In critical production environments, rolling updates that are supported by the Kubernetes deployment object can fall short. Depending on the configurations of the deployment object, the rollout may occur too quickly and developers may not have adequate time to test the impact of the changes. There is also no automated rollback option if something goes wrong.

Progressive Deployments in Kubernetes with Devtron

Devtron is an open source Kubernetes management platform, that helps you to deploy and manage your applications in any Kubernetes environment. It makes it very easy to update application configurations and trigger a deployment for the newer version. You can also very easily select your preferred deployment strategy whether you wish to use a Recreate, Rolling Updates, Blue/Green, or Canary deployment strategy.

While creating the deployment pipeline in Devtron, you simply need to select the deployment strategy that you wish to use for delivering application updates. Devtron will automatically implement the strategy. You can also configure the deployment strategy and set the different configurations such as minimum outages.

[Fig.3] Devtron's Deployment Strategy

Additionally, Devtron helps you easily deploy applications using the GitOps principles. This can help you easily manage application drifts and maintain a history of application configurations in a Git Repository.

Conclusion

Kubernetes deployments provide a great way to deploy, manage, and release updates in a Kubernetes environment. They help ensure that application pods always stay running without any downtime. Deployments help abstract and enhance the functions of a ReplicaSet and a consistent number of pods. Deployments also help scale the application up or down, and can easily trigger a rollback in case of a faulty application.

We also saw some of the key differences between deployments and pods, statefulsets, and replicasets. Kubernetes also has a several deployment strategies that can help progressively roll out application updates without experiencing any downtime.

If you have any questions, or want to discuss any specific usecase, feel free to connect with us or ask them in our actively growing Discord Community.