Kubernetes Deployment Rolling Update and Rollback

Next, use a resource called Deployment to perform Rolling Update and Rollback, or zero-downtime updates, for Pods.

When deploying Pods, Deployment creates a new ReplicaSet, then performs the steps of stopping Pods managed by the old ReplicaSet while creating Pods managed by the new ReplicaSet. By placing the updated application, such as a version-up application, in the new ReplicaSet, updates can be performed without downtime.

In addition to updates, rollback, meaning returning to the original state, is also possible. In this case as well, stopping and starting are performed step by step, so rollback without downtime is possible.

Creating a Deployment

To create this Deployment, use the kubectl create deployment command.

In the example below, helloworld with tag 1.0 is switched to helloworld with tag 2.0. First, because it is hard to see the switch with only one Pod, scale up to five Pods.

kubectl create deployment --image [image name] [deployment name]

Start the helloworld Pod with tag 1.0.

kubectl create deployment --image gcr.io/google-samples/hello-app:1.0 helloworld

Result:

% kubectl create deployment --image gcr.io/google-samples/hello-app:1.0 helloworld
deployment.apps/helloworld created

Check the deployment.

% kubectl get deployment
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
helloworld   1/1     1            1           16s

Scale up.

% kubectl scale --replicas=5 deploy/helloworld
deployment.apps/helloworld scaled

Check the deployment again.

% kubectl get deployment
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
helloworld   5/5     5            5           34s

Check the list of deployed Pods.

% kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
helloworld-7b8f9795b8-4878c   1/1     Running   0          15s
helloworld-7b8f9795b8-6rc9m   1/1     Running   0          15s
helloworld-7b8f9795b8-9k6cg   1/1     Running   0          42s
helloworld-7b8f9795b8-b55sv   1/1     Running   0          15s
helloworld-7b8f9795b8-b9qwr   1/1     Running   0          15s

Rolling Update

Next, perform a rolling update. To do that, first find the name of the Pod group. In the method above, each Pod receives a name different from helloworld. There is a way to align the names, but it is not explained here. Output the YAML file that makes up the created deployment. You can output it with the following command.

kubectl get deployment helloworld --output yaml

Result:

% kubectl get deployment helloworld --output yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2022-09-08T04:36:12Z"
  generation: 2
  labels:
    app: helloworld
  name: helloworld
  namespace: default
  resourceVersion: "541"
  uid: 5fe7a79c-8b4a-4961-974d-f6ebc52f00a8
spec:
  progressDeadlineSeconds: 600
  replicas: 5
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: helloworld
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: helloworld
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:1.0
        imagePullPolicy: IfNotPresent
        name: hello-app   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Pod group name
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 5
  conditions:
  - lastTransitionTime: "2022-09-08T04:36:12Z"
    lastUpdateTime: "2022-09-08T04:36:17Z"
    message: ReplicaSet "helloworld-7b8f9795b8" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  - lastTransitionTime: "2022-09-08T04:36:41Z"
    lastUpdateTime: "2022-09-08T04:36:41Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  observedGeneration: 2
  readyReplicas: 5
  replicas: 5
  updatedReplicas: 5

In this output, spec-template-spec-containers-name is the Pod group name. Here, the group name is hello-app, so use that. Use the following command for rolling updates.

kubectl set image deploy/[deployment name] [name obtained above]=[image name]

Start the helloworld Pod with tag 2.0.

kubectl set image deploy/helloworld hello-app=gcr.io/google-samples/hello-app:2.0

Result:

% kubectl set image deploy/helloworld hello-app=gcr.io/google-samples/hello-app:2.0
deployment.apps/helloworld image updated

The intermediate output is as follows.

% kubectl get pod
NAME                          READY   STATUS              RESTARTS   AGE
helloworld-666776755c-jfsfd   0/1     ContainerCreating   0          4s
helloworld-666776755c-mgc95   1/1     Running             0          4s
helloworld-666776755c-s96qf   0/1     ContainerCreating   0          0s
helloworld-666776755c-w57b5   0/1     ContainerCreating   0          4s
helloworld-7b8f9795b8-4878c   1/1     Terminating         0          84s
helloworld-7b8f9795b8-6rc9m   1/1     Running             0          84s
helloworld-7b8f9795b8-9k6cg   1/1     Running             0          111s
helloworld-7b8f9795b8-b55sv   1/1     Running             0          84s

The final output is as follows.

$ kubectl get pod
helloworld-666776755c-jfsfd   1/1     Running   0          25s
helloworld-666776755c-mgc95   1/1     Running   0          25s
helloworld-666776755c-s96qf   1/1     Running   0          21s
helloworld-666776755c-vcmzc   1/1     Running   0          20s
helloworld-666776755c-w57b5   1/1     Running   0          25s

Looking at the output, you can confirm that the old helloworld Pods were gradually deleted and new helloworld Pods were created. In this output, the number of existing Pods became eight during the intermediate process. This is because creation happens while termination is in progress, so the number of existing Pods increases. This maximum number may vary depending on operating environment resources, such as memory, and it is also possible to specify the maximum number that can exist.

Details will be explained again later.

Rollback

Finally, rollback is performed with the following command.

$ kubectl rollout undo deploy/helloworld
deployment.apps/helloworld rolled back

The intermediate output is as follows.

% kubectl get pod
NAME                          READY   STATUS              RESTARTS   AGE
helloworld-666776755c-mgc95   1/1     Running             0          4m32s
helloworld-7b8f9795b8-99qsq   0/1     ContainerCreating   0          5s
helloworld-7b8f9795b8-lk8b9   0/1     ContainerCreating   0          5s
helloworld-7b8f9795b8-xnhnt   1/1     Running             0          6s
helloworld-7b8f9795b8-zbfc7   1/1     Running             0          6s
helloworld-7b8f9795b8-zn6vn   1/1     Running             0          6s

The final output is as follows.

% kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
helloworld-7b8f9795b8-99qsq   1/1     Running   0          16s
helloworld-7b8f9795b8-lk8b9   1/1     Running   0          16s
helloworld-7b8f9795b8-xnhnt   1/1     Running   0          17s
helloworld-7b8f9795b8-zbfc7   1/1     Running   0          17s
helloworld-7b8f9795b8-zn6vn   1/1     Running   0          17s

The behavior is similar to Rolling Update, with Pods being replaced gradually.