Kubernetes: Deployment

What is a Deployment?

A deployment is an object in Kubernetes that helps you to manage a group of identical pods. A Deployment runs multiple replicas of your application and automatically replaces any instances that fail or become unresponsive.

This way, Deployments ensure that one or more instances of your application are available to serve user requests.

The following are typical use cases for Deployments

  • A Deployment can be used to rollout a ReplicaSet. Each rollout updates the revision of the Deployment.
  • Provide a new definition to the Pods by simply updating the PodTemplateSpec in the Deployment. As a result, a new ReplicaSet will be created.
  • Deploment can be used to Rollback to an earlier Deployment revision in case the existing or the updated revision of the Deployment is not stable.
  • Pause the rollout to apply fixes to the PodTemplateSpec and then resume it to start a new rollout.
  • Scale up or down for better load management.

Configuring a Deployment

Just like any other resource, the Deployment manifest file consist of four main sections as below.

apiVersion:
kind: 
metadata:
[ . . . ]

spec:
    replicas:
    selector:
        [ . . . ]
    template:
        [ . . . ]

  1. apiVersion: Defines the Kubernetes API that supports Deployment.
  2. kind: Specifies the Kubernetes object we wish to create.
  3. metadata: Contains information about the Deployment object.
    • We can specify name and labels associated with the Deployment.
  4. spec: There are three sections under spec namely replicas, selector and template.
    • replicas: Specifies the number of replicas of the pod
    • selector: The selector is used to identify which pod the ReplicaSet is responsible for.
    • template: Defines the pod template that the ReplicaSet uses when creating pods and adding them to meet the required number of replicas.

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

Apply the deployment manifest file and verify the status of the deployment.

# kubectl apply -f deployment.yml --record
deployment.apps/nginx-deployment created

# kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           17s
  • NAME lists the names of the Deployments.
  • READY shows how many replicas of the application are available to your users. It follows the pattern ready/desired.
  • UP-TO-DATE specifies the number of replicas that have achieved the desired state.
  • AVAILABLE displays how many replicas of the application are available to your users.
  • AGE specifies how long the application has been running.

To see the ReplicaSet and Pods created by ReplicaSet run the below mentioned commands. The created ReplicaSet ensures that three instance of the nginx application as specified under spec.replicas are running at any given time.

# kubectl get replicaset
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-579c9dfc44   3         3         3       14s

# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-579c9dfc44-qmfrb   1/1     Running   0          19s
nginx-deployment-579c9dfc44-f7k4d   1/1     Running   0          19s
nginx-deployment-579c9dfc44-kq46r   1/1     Running   0          19s

To see detailed information about the Deployment run the below command.

# kubectl describe deployment nginx-deployment

Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Sun, 08 Jan 2023 17:48:11 +0000
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 1
                        kubernetes.io/change-cause: kubectl apply --filename=deployment.yml --record=true
Selector:               app=nginx
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=nginx
  Containers:
   nginx:
    Image:        nginx:1.22.1
   [ . . . ]
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-deployment-579c9dfc44 (3/3 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  34s   deployment-controller  Scaled up replica set nginx-deployment-579c9dfc44 to 3

Updating the Deployment

A Kubernetes Deployment upgrade can be triggered by updating the Pod template. In such scenarios the Deployment will rollout and create a new ReplicaSet which will be responsible for managing the updated Pod. Changes other than Pods spec.template will not trigger a rollout.

A rollout creates a new ReplicaSet which manages the updated Pods whereas changes made to block other than spec.template won’t result in rollout. This means that the existing ReplicaSet will be responsible for managing application Pods. One such example is scaling the deployment.

To rollout a deployment follow the below steps.

Update the image of the existing Pods from 1.22.1 to 1.23.3

# kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3 --record
deployment.apps/nginx-deployment image updated

Verify the status of Deployment.

# kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           4m31s

# kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out

Run kubectl get replicaset to verify that Deployment created a new ReplicaSet and scaling it to three replicas. Additionally, the existing ReplicaSet was scaled down to 0 replicas.

# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-866c5d4565   3         3         3       12s
nginx-deployment-579c9dfc44   0         0         0       3m42s

Describe the deployment to see detailed information of the rollout.

# kubectl describe  deployment/nginx-deployment

Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Sun, 08 Jan 2023 17:48:11 +0000
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 2
                        kubernetes.io/change-cause: kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3 --record=true
Selector:               app=nginx
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=nginx
  Containers:
   nginx:
    Image:        nginx:1.23.3
 
  [ . . . ]
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-deployment-866c5d4565 (3/3 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  5m31s  deployment-controller  Scaled up replica set nginx-deployment-579c9dfc44 to 3
  Normal  ScalingReplicaSet  2m1s   deployment-controller  Scaled up replica set nginx-deployment-866c5d4565  to 1
  Normal  ScalingReplicaSet  115s   deployment-controller  Scaled down replica set nginx-deployment-579c9dfc44 to 2 from 3
  Normal  ScalingReplicaSet  115s   deployment-controller  Scaled up replica set nginx-deployment-866c5d4565 to 2 from 1
  Normal  ScalingReplicaSet  113s   deployment-controller  Scaled down replica set nginx-deployment-579c9dfc44 to 1 from 2
  Normal  ScalingReplicaSet  113s   deployment-controller  Scaled up replica set nginx-deployment-866c5d4565 to 3 from 2
  Normal  ScalingReplicaSet  111s   deployment-controller  Scaled down replica set nginx-deployment-579c9dfc44 to 0 from 1

In the events you can see that the new ReplicaSet(nginx-deployment-866c5d4565) was first scaled up to 1 replica and waits for it to achieve the Ready state.

It then scales down the existing/old ReplicaSet(nginx-deployment-579c9dfc44) from 3 to 2 and scales up the new ReplicaSet to 2. It will continue scaling down the old and scaling up the new ReplicaSet till all the Pods have been updated with the latest image. It will not kill an existing Pod until a sufficient number of new Pods have come up and vice-versa.

How many Pods should be scaled down or scaled up at a given point of time is controlled by RollingUpdateStrategy which is set to a default value of 25% max unavailable, 25% max surge.

25% max unavailable means how many Pods can be unavailable during the upgrade procedure. Hence ensuring that at least 75% of the desired Pods are up. This value can be an absolute number or a percentage value.

25% max surge means how many additional Pods can be created above the desired number during the upgrade procedure. This value can be an absolute number or a percentage value.

Rollback an update

Deployment upgrade can be rolled back in case of upgrade failure or because of an unexpected behavior of the application. You can see the revision and details of each revision. Run the below commands.

# kubectl rollout history deployment nginx-deployment

deployment.apps/nginx-deployment
 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=deployment.yml --record=true
2         kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3 --record=true

To see more information of a revision.

# kubectl rollout history deployment/nginx-deployment --revision=2

deployment.apps/nginx-deployment with revision #2
Pod Template:
  Labels:       app=nginx
        pod-template-hash=866c5d4565
  Annotations:  kubernetes.io/change-cause: kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3 --record=true
  Containers:
   nginx:
    Image:      nginx:1.23.3
    Port:       80/TCP
    Host Port:  0/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

By default, a revision is rolled back to an immediate previous revision. However, it is possible to roll back to a specific revision as well.

For example, to rollback from revision 2 to revision 1 run the below command.

# kubectl rollout undo deployment/nginx-deployment
deployment.apps/nginx-deployment rolled back

To rollback to a specific revision use the below command.

# kubectl rollout undo deployment/nginx-deployment –to-revision=<revision_number>

Check the rollout history

# kubectl rollout history deployment/nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
2         kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3 --record=true
3         kubectl apply --filename=deployment.yml --record=true

Also verify the status of the ReplicaSet.

# kubectl get rs

NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-579c9dfc44   3         3         3       14m
nginx-deployment-866c5d4565   0         0         0       10m

You can see in the above output that Pods have been migrated back to the older ReplicaSet.

Scaling a deployment

A deployment can be scaled up or down by updating the replica count either in the manifest file or by passing the replica count via command line.

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

Apply the updated manifest file to the cluster.

# kubectl apply -f deployment.yml 
deployment.apps/nginx-deployment configured

# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-866c5d4565   0         0         0       16m
nginx-deployment-579c9dfc44   5         5         5       19m

# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-579c9dfc44-sgszk   1/1     Running   0          4m54s
nginx-deployment-579c9dfc44-km7d5   1/1     Running   0          4m53s
nginx-deployment-579c9dfc44-p6dvp   1/1     Running   0          4m51s
nginx-deployment-579c9dfc44-h67qm   1/1     Running   0          4s
nginx-deployment-579c9dfc44-mjvlz   1/1     Running   0          4s

To scale down the replicas run the below command.

# kubectl scale deployment/nginx-deployment --replicas=2
deployment.apps/nginx-deployment scaled

# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-866c5d4565   0         0         0       26m
nginx-deployment-579c9dfc44   2         2         2       29m

# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-579c9dfc44-sgszk   1/1     Running   0          16m
nginx-deployment-579c9dfc44-km7d5   1/1     Running   0          16m

Final Thoughts

In this post, we showed you how to use Kubernetes Deployment to achieve High availability, easy rollout and scaling of application for better traffic management. Deployment is a great option for stateless applications.

More

1 thought on “Kubernetes: Deployment”

  1. Pingback: Kubernetes: What is a ReplicaSet – Learn and Implement DevOps

Leave a Comment

Your email address will not be published. Required fields are marked *