This tutorial provides a comprehensive guide on understanding deployments in Kubernetes. Deployments in Kubernetes play a crucial role in managing containerized applications, ensuring scalability, availability, and efficient updates. This comprehensive guide aims to provide a clear understanding of what deployments are, how to create and manage them, and their essential functionalities like rollout and rollback.
Table of Contents
Comprehensive Guide Understanding Deployments in Kubernetes
What is a Deployment in Kubernetes?
In Kubernetes, Deployment is a high-level controller object that defines the desired state for a set of replica Pods. It manages the deployment and scaling of a set of Pods, ensuring that the specified number of replicas are running at any given time. Deployments are declarative and provide an abstraction layer above Pods, allowing for automated rollouts and rollbacks, scaling, and self-healing capabilities.
Deployments are categorized as workloads in Kubernetes, representing a higher-level abstraction for managing Pods and ReplicaSets. As a workload type, Deployments encapsulate the logic for managing the lifecycle of application instances, ensuring they run as intended and can be scaled, updated, or rolled back seamlessly.
With the Kubernetes Deployment all you need to do is to either declaratively or imperatively define the desired state of your application by specifying details like the name of the deployment, container image, number of replicas (number of application to run concurrently), resource requirements like how much CPU, memory, and storage each replica needs and maybe environment variables (configuration settings for your application). The Deployment controller, then takes care of the rest and ensures your app pods reach and maintain that desired state.
Key Concepts in Kubernetes Deployments?
What are the key concepts or components of a deployment?
- Pods: These are the basic unit of deployment in Kubernetes, comprising one or more containers that share storage and networking.
- ReplicaSets: This is a Kubernetes resource that defines a specific set of replica pods and ensures that they are running in the cluster at any given time. It essentially guarantees a desired state for your application by maintaining the specified number of identical pods. Deployments manage ReplicaSets to achieve the desired state.
- Labels and Selectors:
- Labels are key-value pairs attached to Kubernetes objects like Pods to define identifying attributes. They are like tags for your pods. You can add multiple labels to a pod, allowing for granular categorization.
- Selectors: Selectors are used by Deployments to filter and identify pods based on their labels. They are like the search queries targeting pods with specific labels. Selectors use a key-value matching syntax similar to labels.
- Strategy: Deployment strategy defines how to replace old Pods with new ones. There are two types of strategies:
- Recreate strategy: This strategy requires that all existing Pods are killed before new ones are created. Until all previous pods are terminated, new pods wont be created. This is the default strategy.
- RollingUpdate: This strategy updates Pods incrementally, ensuring that a specified number of Pods are available throughout the deployment process. It gradually replaces old Pods with new ones, maintaining application availability
Creating a Kubernetes Deployment
Now that you have an understanding of what a Kubernetes deployment is and the core concepts, let’s check how to create a Kubernetes Deployment.
There are different approaches you can use to create a Kubernetes Deployment.
- Declarative approach using YAML Manifests files: The declarative approach involves creating a Deployment via a configuration file in YAML format, here in called, a manifest file.
- Imperative Approach: This involves the use kubectl create deployment command to create your deployment.
Creating Kubernetes Deployment using Declarative Approach
As already stated, you can use a manifest file to define specific configuration of your Kubernetes deployment.
Here is an example of a manifest YAML file to create a deployment.
cat my-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app-image:latest
port:
- containerPort: 80
Where:
- apiVersion: apps/v1: specifies that the manifest conforms to the deployments API version “apps/v1”.
- kind: Deployment: declares that the resource being defined is a “Deployment”.
- metadata: provides metadata about the deployment, including its name.
- name: my-app-deployment: This assigns the name “my-app-deployment” to the deployment.
- spec: This section defines the desired state of the deployment, specifying how you want your application to run. Here’s what’s included:
- replicas: 2: This sets the desired number of replicas for your application. In this case, you want two identical pods running for your “my-app”.
- selector: This section defines how the deployment identifies the pods it manages.
- matchLabels: This key-value pair specifies the label selector. The deployment will manage pods that have the label
app: my-app
.
- matchLabels: This key-value pair specifies the label selector. The deployment will manage pods that have the label
- template: This section defines the template for the pods that will be created by the deployment. Any pods created by this deployment will be based on this template.
- metadata: This section defines metadata for the pods, including labels.
- labels: app: my-app: This assigns the label
app: my-app
to the pods created by the deployment. This label allows the deployment to identify and manage these pods using the selector defined earlier.
- labels: app: my-app: This assigns the label
- spec: This section defines the container configuration for the pods.
- containers: This defines the containers that will be running inside each pod. Here, we have only one container:
- name: my-app: This assigns the name “my-app” to the container within the pod.
- image: my-app-image:latest: This specifies the container image to use. The image name is “my-app-image” and the tag is “latest”.
- port: This section defines the ports the container exposes. Here, you have one port:
- containerPort: 80: This exposes port 80 within the container. This is likely where your application listens for traffic.
- containers: This defines the containers that will be running inside each pod. Here, we have only one container:
- metadata: This section defines metadata for the pods, including labels.
In essence, this deployment configuration creates two pods, each running a container based on the image “my-app-image:latest” in the default namespace. The pods are labeled with app: my-app
, allowing the deployment to manage them. The containers within the pods expose port 80, where your application listens for incoming requests.
If you want to create the deployment on a different namespace other than the default namespace, you can specify the name of the respective namespace under the metadata section;
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
namespace: my-namespace
To deploy the application defined in the YAML manifest file, use the kubectl apply command:
kubectl apply -f my-app.yaml
This command instructs Kubernetes to create or update resources defined in the my-app.yaml file.
Creating Kubernetes Deployment using Imperative Approach
In some scenarios, you might need to use imperative commands to manage Deployments. For example, to create a Deployment imperatively in the default namespace:
kubectl create deployment example-deployment --image=nginx:latest --replicas=3
If you want to create the deployment in a different namespace, specify the namespace using the -n NS|–namespace=NS where NS is the name of the specific namespace.
Viewing and Managing Deployments
Listing Available Deployments:
To view Deployments in Kubernetes, use:
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
example-deployment 3/3 3 3 11m
This command lists all Deployments along with their current status, such as the number of desired, current, and available replicas in the default namespace.
If you want to list Deployments in other namespaces, pass –n|–namespace option specify the namespace you want. For example, to list deployments in the apps namespace;
kubectl get deployments -n apps
Demystifying the output of kubectl get deployments command.
- NAME: This column shows the name of the deployment, in this case, it’s
example-deployment
. - READY: This column indicates the current state of the deployment’s pods. The format
3/3
means:- The deployment has a desired number of 3 replicas (specified in the deployment configuration).
- All 3 replicas are currently running and ready.
- UP-TO-DATE: This column shows how many of the deployed pods are up to date with the latest deployment configuration. A value of
3
means all 3 pods are running the latest version of the application as defined in the deployment. - AVAILABLE: This column indicates the number of pods that are available for serving traffic. It should match the number of replicas (
3
in this case), meaning all pods are ready to accept requests. - AGE: This column shows the amount of time since the deployment was created.
Describing a Deployment
To get detailed information about a specific Deployment, use kubectl describe deployment command:
kubectl describe deployment example-deployment
This command provides information about the Deployment’s configuration, current status, events, and more.
Sample output;
Name: example-deployment
Namespace: default
CreationTimestamp: Fri, 21 Jun 2024 17:26:05 +0000
Labels: app=example-deployment
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=example-deployment
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=example-deployment
Containers:
nginx:
Image: nginx:latest
Port:
Host Port:
Environment:
Mounts:
Volumes:
Node-Selectors:
Tolerations:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets:
NewReplicaSet: example-deployment-5c5699c8df (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 31m deployment-controller Scaled up replica set example-deployment-5c5699c8df to 3
The output is a little bit self-explanatory.
Just under the deployment strategy, we have;
- StrategyType:
RollingUpdate
- MinReadySeconds:
0
(minimum seconds for which a newly created pod should be ready without any of its containers crashing, for it to be considered available) - RollingUpdateStrategy:
25% max unavailable
: During updates, at most 25% of the desired number of replicas can be unavailable.25% max surge
: During updates, the deployment can increase its size by up to 25% of the desired number of replicas.
Scaling Deployments
You can scale the deployments up or down depending on the usage needs.
Scaling Up a Deployment:
To scale a Deployment to increase the number of replicas (e.g., from 3 to 5):
kubectl scale deployment example-deployment --replicas=5
This command scales the Deployment example-deployment
to 5 replicas, distributing the workload across more Pods.
Scaling Down a Deployment:
To scale a Deployment down to decrease the number of replicas (e.g., from 5 to 3):
kubectl scale deployment example-deployment --replicas=3
Deployment Rollout and Rollback
Rolling Updates:
Rollout refers to the process of updating the pods in a Kubernetes Deployment to a new version of your application. Here’s how it typically works:
- Updating the Deployment: When you update the Docker image, configuration, or other parameters of your application in a Deployment manifest (usually done via
kubectl apply
or by editing the YAML directly), Kubernetes initiates a rollout. - Pods Replacement: Kubernetes replaces the existing pods (running the old version) with new pods (running the updated version) gradually. It does this by creating new pods based on the updated Deployment specification while gradually terminating the old pods.
- Rolling Update Strategy: By default, Deployments use a RollingUpdate strategy, where Kubernetes ensures that a certain number of pods from the old Deployment are running alongside the new pods during the update. This strategy helps in minimizing downtime and ensures that your application remains available throughout the update process.
- Monitoring and Progress: Check the monitoring rollout status section below.
A sample command to update the image version of the application:
kubectl set image deployment example-deployment nginx=nginx:1.20
This command updates the Deployment to use the nginx:1.20
image.
You can annotate this update to set the cause of the change;
kubectl annotate deployment/example-deployment kubernetes.io/change-cause="Updated nginx image to version 1.20"
Monitoring Rollout Status:
You can monitor the rollout progress using kubectl rollout status deployment <deployment-name>
;
kubectl rollout status deployment example-deployment
or by viewing the Deployment details (kubectl describe deployment <deployment-name>
). Kubernetes ensures that the desired number of replicas (pods) are available and healthy before moving on to the next step in the rollout.
Sample rollout status command;
Waiting for deployment "example-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "example-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "example-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "example-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "example-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "example-deployment" successfully rolled out
Rollback to Previous Version:
Rollback provides a safety net in case something goes wrong during a deployment update. It allows you to revert to a previous stable version of your application quickly.
- Triggering a Rollback: If issues are detected during the rollout (e.g., application crashes, unexpected errors), you can trigger a rollback manually using
kubectl rollout undo deployment <deployment-name> --to-revision=N
. - Reverting to Previous State: Kubernetes will revert the Deployment to the previous known good state by scaling down the new ReplicaSet (created during the rollout) and scaling up the old ReplicaSet. This effectively switches traffic back to the previous version of your application.
- Rollback History: Kubernetes keeps track of Deployment revisions, allowing you to rollback to any previous revision if needed. You can view the revision history using
kubectl rollout history deployment <deployment-name>
.
When you update your deployment, you will see that the old replicaset is kept for rollback, just in case.
kubectl get replicasets -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
example-deployment-7648d6474 0 0 0 8m52s nginx nginx:1.18 app=example-deployment,pod-template-hash=7648d6474
example-deployment-77d66d9f6f 3 3 3 7m29s nginx nginx:1.20 app=example-deployment,pod-template-hash=77d66d9f6f
Sample rollback command;
kubectl rollout undo deployment example-deployment
This command reverts the Deployment to the previous stable version, minimizing downtime and impact on users.
You can monitor the rollback status using the rollout status command above.
kubectl rollout status deployment example-deployment
Waiting for deployment "example-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "example-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "example-deployment" successfully rolled out
kubectl get replicasets -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
example-deployment-7648d6474 3 3 3 13m nginx nginx:1.18 app=example-deployment,pod-template-hash=7648d6474
example-deployment-77d66d9f6f 0 0 0 12m nginx nginx:1.20 app=example-deployment,pod-template-hash=77d66d9f6f
As you can see, the update replicaset is kept!
Similarly, annotate:
kubectl annotate deployment/example-deployment kubernetes.io/change-cause="Reverted nginx image to version 1.18"
You can check the rollout history;
kubectl rollout history deployment example-deployment
REVISION CHANGE-CAUSE
4 Updated nginx image to version 1.20
5 Reverted nginx image to version 1.18
To rollback to specific revision number;
kubectl rollout undo deployment <deployment-name> --to-revision=N
For example;
kubectl rollout undo deployment example-deployment --to-revision 4
If you want to get details about a specific revision;
kubectl rollout history deployment <deployment> --revision Rev_No
For example;
kubectl rollout history deployment example-deployment --revision 5
deployment.apps/example-deployment with revision #5
Pod Template:
Labels: app=example-deployment
pod-template-hash=7648d6474
Annotations: kubernetes.io/change-cause: Reverted nginx image to version 1.18
Containers:
nginx:
Image: nginx:1.18
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
In essence, deployment rollout and rollback features provides these benefits;
- Continuous Delivery: Enables seamless updates of your applications without downtime.
- Fault Tolerance: Provides a safety mechanism to quickly revert to a stable state in case of issues.
- Version Control: Maintains a history of changes, making it easier to track and manage updates over time.
Deleting Kubernetes Deployment
If you have the necessary permissions to delete a deployment, then you can use kubectl
to remove the deployment. It’s important to ensure you are deleting the correct deployment to avoid unintended consequences. Always verify your actions, especially in production environments.
As usual, list all deployments to find the one you want to delete.
kubectl get deployments [-n NAMESPACE]
Once you have identified the deployment you want to delete, use the kubectl delete deployment command followed by the deployment name. For example, if your deployment is named my-deployment, you would delete it with:
kubectl delete deployment my-deployment
If the deployment you want to delete is in a different namespace, specify the namespace using -n
or --namespace
flag:
kubectl delete deployment my-deployment -n my-namespace
By default, when you delete a deployment, Kubernetes also deletes the pods that are managed by that deployment. If you want to keep the pods running even after deleting the deployment, you can use the --cascade=orphan
flag:
kubectl delete deployment my-deployment --cascade=orphan
Confirm by listing the pods!
To ensure that the deployment has been successfully deleted, you can list the deployments again. If the deployment no longer appears in the list, it has been successfully deleted.
Conclusion
Deployments are fundamental to managing containerized applications effectively in Kubernetes. They provide automated management of application lifecycle, including scaling, updates, and fault tolerance. By understanding both declarative and imperative approaches to creating, managing, scaling, you can leverage this flexibility for robust and scalable application deployments.
Further Reading Kubernetes Deployments.