Rolling updates are an important part of the lifecycle of a modern app, with users constantly expecting new features and zero downtime. While Kubernetes used Replication Controllers to enable this functionality in the past, newer versions recommend using Deployments.
This tutorial will show you how to perform rolling updates using Kubernetes Deployments. This method allows you to quickly update your apps and achieve zero downtime while ensuring rollback support.
- A Kubernetes cluster
- Access to a terminal window
- The kubectl command-line tool
Enable Rolling Updates
Kubernetes Deployments act as wrappers around ReplicaSets, which are Kubernetes controllers in charge of pod management. Deployments provide additional functionality to ReplicaSets - they perform health checks, rolling updates, and rollbacks.
1. First, create a yaml file with deployment specifications in a text editor, such as Nano:
The example file contains the basic declarations necessary for a Kubernetes Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 4 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
2. Create the deployment using the
kubectl create command. Specify the yaml file you have just created:
kubectl create -f nginx-test.yaml
3. Check the deployment:
kubectl get deployment
The output confirms that the deployment is ready:
4. Check the ReplicaSets:
kubectl get rs
The example file specified four replicas, which all show as ready:
5. Finally, check if the pods are up:
kubectl get pod
The output shows pods as ready and running:
Ensure Zero Downtime
To configure rolling updates with zero downtime, first, specify the update strategy.
Add the following declaration to the deployment yaml file under the
minReadySeconds: 5 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1
minReadySecondsrow tells Kubernetes how long it should wait until it creates the next pod. This property ensures that all the application's pods are in the ready state during the update.
maxSurgespecifies the maximum number (or percentage) of pods above the specified number of replicas. In the example above, the maximum number of pods will be 5 since 4 replicas are specified in the yaml file.
maxUnavailabledeclares the maximum number (or percentage) of unavailable pods during the update. If
maxSurgeis set to 0, this field cannot be 0.
Adding the above specification to the deployment yaml file is enough to start performing Kubernetes rolling updates. However, it does not guarantee zero downtime. Kubernetes cannot tell when a new pod is ready - it eliminates the old pod as soon as the new one is created. This problem causes downtime until the new pod becomes able to accept requests.
To fix this problem, Kubernetes features the concept of Readiness Probes. The probes check the state of pods and allow for a rolling update to proceed only when a specified amount of ready pods are available. Pods are considered ready when the readiness probe is successful and after the time specified in
minReadySeconds has passed.
To set up Readiness Probes, add the following to the deployment file's
readinessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1
initialDelaySecondsspecifies how long the probe has to wait to start after the container starts.
periodSecondsis the time between two probes. The default is 10 seconds. The minimal value is 1 second.
successThresholdis the minimum number of consecutive successful probes after a failed one for the entire process to be considered successful. The default and minimal values are both 1.
The entire deployment file properly configured for rolling updates should look like this:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 4 selector: matchLabels: app: nginx minReadySeconds: 5 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.0 ports: - containerPort: 80 readinessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1
Save the file and exit. Then use
kubectl apply to apply the changes:
kubectl apply -f nginx-text.yaml --record
--record flag will serve a purpose in the rollback process.
The output shows that the deployment has been configured successfully.
Perform Rolling Update
Rolling updates can be performed in three ways. For example, to change the app image:
- You can use
kubectl setto perform the action on the command line:
kubectl set image deployment nginx-deployment nginx=nginx:1.14.2 --record
2. Alternatively, modify the image version in the
spec.templates.spec.containers section of the yaml file. Then use
kubectl replace to perform the update:
kubectl replace -f nginx-test.yaml
3. You can also use
kubectl edit to edit the deployment directly:
kubectl edit deployment nginx-deployment --record
4. Make the necessary changes in the editor that opens:
The changes are applied when you close the editor.
Check Rollout Status
Check the rollout status of the deployment using the following syntax:
kubectl rollout status deployment nginx-deployment
The output confirms the successful rollout:
Pause and Resume Rolling Update
Pause and Resume rolling updates with the respective
kubectl rollout commands.
To pause the update, run:
kubectl rollout pause deployment nginx-deployment
To resume the update, run:
kubectl rollout resume deployment nginx-deployment
Schedule Pods for Deployment
Use affinity and anti-affinity properties to control on which nodes Kubernetes schedules specific pods in your deployment.
There are two types of affinity currently available in Kubernetes:
requiredDuringSchedulingIgnoredDuringExecutiontells Kubernetes to only run pods on nodes that satisfy certain criteria, such as a specific processor type.
preferredDuringSchedulingIgnoredDuringExecutionallows pods to be run elsewhere, if and only if no nodes satisfy given criteria.
These properties are listed in the PodSpec file. For example, a pod may be specified as follows:
apiVersion: v1 kind: Pod metadata: name: affinity-test spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/test-name operator: In values: - test1 - test2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: example-node-label-key operator: In values: - example-node-label-value containers: - name: affinity-test image: k8s.gcr.io/pause:2.0
The file above tells Kubernetes to run the pod only on a node with a label whose key is
kubernetes.io/test-name and whose value is either
test2. Furthermore, Kubernetes will prefer nodes whose key is
example-node-label-key, with the
Pod anti-affinity is useful if you do not want all the pods to run on the same node. It functions similarly to affinity, with the same two types available -
The following example specifies an anti-affinity rule that tells Kubernetes to preferably avoid scheduling the "test" app pods to nodes that already have the "test" pods:
podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - test topologyKey: Kubernetes.io/hostname
If something goes wrong with the update process, you can rollback changes and revert to a previous version of the app. Use the following
kubectl rollout command:
kubectl rollout history deployment nginx-deployment
The output lists the available revisions, created by adding the
--record flag when performing an update:
Choose the revision you want and type the following command to rollback the changes:
kubectl rollout undo deployment nginx-deployment --to-revision=1
The command above rolls back to revision 1 and produces the following output:
After reading this tutorial, you should be able to perform zero-downtime rolling updates using Kubernetes Deployments.
If you wish to expand your knowledge about deployment types in Kubernetes, read How to do Canary Deployments on Kubernetes.