Share the love

One of the most common scenarios that we come across is managing Kubernetes rolling updates. In this post we will cover how to do it and the changes required in YAML file.

You should keep a note of your application as well if you’re doing rolling updates. If running multiple versions of the same application isn’t going to work out for you, then rolling updates are not for you. In such a scenario you should consider the type “recreate”. Rolling updates help in update deployments with no downtime at all.

Kubernetes Rolling Update Process

Most of you would be aware of the fact that deployments would deploy replicasets. These replicasets will be deploying the pods. When updates are applied, deployment creates a new replicaset and creates new pods. At the same moment older pods are deleted. The total number of pods are managed by maxSurge and maxUnavailable.

maxSurge

Maxsurge tells us how many pods we can go up then the required number of pods. Lets say our current deployment has created a replicaset with 3 pods. Now if we set maxSurge to 2, then temporarily we can have up to 5 pods.

maxUnavailable

MaxUnavailable tells us how much “under” can we go. Similar to above scenario, if we keep MaxUnavailable value as 1, it means that it will always maintain minimum 2 pods at all times.

Note: maxSurge and maxUnavailable could also be set as percentage.

Tutorial: Kubernetes Rolling Updates

Lets go ahead and use sample YAML from Kubernetes deployment documentation page with a slight change. You check the YAML file in my GitHub. If you don’t know how to work with YAML files, here’s a detailed post on how to create Kubernetes YAML files.

     1  apiVersion: apps/v1
     2  kind: Deployment
     3  metadata:
     4    name: nginx-deployment
     5    labels:
     6      app: nginx
     7  spec:
     8    replicas: 3
     9    strategy:
    10      type: RollingUpdate
    11      rollingUpdate:
    12        maxSurge: 2
    13        maxUnavailable: 1
    14    selector:
    15      matchLabels:
    16        app: nginx
    17    template:
    18      metadata:
    19        labels:
    20          app: nginx
    21      spec:
    22        containers:
    23        - name: nginx
    24          image: nginx:1.14.2
    25          ports:
    26          - containerPort: 80

Line 8: Replicaset is set to 3. We will have 3 pod replicas running at any given time.
Line 9 – 13: This shows the strategy part. We are using rolling updates. maxSurge is set to 2, i.e. we can have up to 5 pods temporarily. maxUnavailable is set to 1 which means that at least 2 pods will always be running at a given moment.

We will deploy this on the Kubernetes cluster using following command.

# Create deployment
kubectl create -f nginx.yaml

Here’s the output.

$ kubectl create -f nginx.yaml
deployment.apps/nginx-deployment created

lets check the rollout history.

$ kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
1         <none>

As you could see that only 1 revision is there. Now, we will change the version of the image to 1.16.1 and then apply the change.

...
    22        containers:
    23        - name: nginx
    24          image: nginx:1.16.1
    25          ports:
...
$ kubectl apply -f nginx.yaml
deployment.apps/nginx-deployment configured


$ kubectl get all
NAME                                    READY   STATUS        RESTARTS   AGE
pod/nginx-deployment-559d658b74-hw68c   1/1     Running       0          4s
pod/nginx-deployment-559d658b74-qhhsf   1/1     Running       0          4s
pod/nginx-deployment-559d658b74-xphmx   1/1     Running       0          4s
pod/nginx-deployment-66b6c48dd5-96fg7   0/1     Terminating   0          50s
pod/nginx-deployment-66b6c48dd5-j6m8l   0/1     Terminating   0          50s
pod/nginx-deployment-66b6c48dd5-nmhwg   0/1     Terminating   0          50s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   6d19h

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           50s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-559d658b74   3         3         3       4s
replicaset.apps/nginx-deployment-66b6c48dd5   0         0         0       50s

As seen from above output, a new replicaset has been created and previous one is empty. Lets take a deeper look into events that took place on deployment.

kubectl describe deployment command to check what happened during Kubernetes rolling updates.

As you could see the replicaset was scaled up to 2 which means there were 5 pods at a certain moment. Post that older replicaset scaled down by 2 and newer one scaled up tp 3, again giving a total of 5 pods. Once all pods are up and older ones are deleted and 3 pods are maintained while the old replicaset is empty.

Check differences in various revisions

Lets check what was there in first revision and what got changed in second revision.

# Check the details of first revision.
kubectl rollout history deployment nginx-deployment --revision=1
Get details of first revision
# Check details of revision 2
kubectl rollout history deployment nginx-deployment --revision=2
get details of second revision.

Undo the changes deployed in Kubernetes rolling updates

How often we update the app and conclude that we made a huge mess somewhere. How do we roll back the changes? Just a simple command.

# Undo the changes
kubectl rollout undo deployment nginx-deployment

Run “kubectl get all” and check the difference for yourself. At the same time, you should also see a revision 3. Lets check the details:

Check the details of Kubernetes deployment after reverting the changes.

Next Steps

You can try deploying an AKS and try Kubernetes rolling changes in there for simplicity.