In this blog post, we will have a closer look to Kubernetes Deployments. We will explore, how Kubernetes Deployments relate to ReplicaSets of the last post, and which features in terms of the rollout/rollback they offer to the Kubernetes administrator.

References

Step 0: Access the Kubernetes Playground

As always, we start by accessing the Katacode Kubernetes Playground.

Step 1: Create a Deployment

Let us try to create a Deployment converting the ReplicaSet YAML of the last blog post to a Deployment:

cat <<EOF | kubectl apply -f -
# frontend-minimalistic-deploy.yaml
apiVersion: apps/v1
kind: Deployment                    #<------------- ReplicaSet -> Deployment
metadata:
  name: frontend-deploy             #<------------- changed rs -> deploy
spec:
  # modify replicas according to your case
  replicas: 3      
  selector:
    matchLabels:
      tier: my-matching-label
  template:
    metadata:
      labels:
        tier: my-matching-label
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
EOF

# output: deployment.apps/frontend-deploy created

You can see, that there is almost no difference to a ReplicaSet, apart from exchanging ReplicaSet with Deployment. Moreover, the Deployment is creating a ReplicaSet automatically:

kubectl get deploy
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
frontend-deploy   3/3     3            3           15s

kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
frontend-deploy-85c49c7b5d   3         3         3       21s

Step 2: Compare ReplicaSets and Deployments

So, what is the difference between deployment and ReplicaSet? To research on this topic, let us export the deployment and the ReplicaSet to YAML files and compare them:

kubectl get deploy -o yaml > deploy.yam
kubectl get rs -o yaml > rs.yaml
diff deploy.yam rs.yaml

4c4
<   kind: Deployment
---
>   kind: ReplicaSet
6a7,8
>       deployment.kubernetes.io/desired-replicas: "3"
>       deployment.kubernetes.io/max-replicas: "4"
10c12,15
<     name: frontend-deploy
---
>     labels:
>       pod-template-hash: 85c49c7b5d
>       tier: my-matching-label
>     name: frontend-deploy-85c49c7b5d
12,14c17,26
<     resourceVersion: "1825"
<     selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/frontend-deploy
<     uid: 3bb03ca5-b488-11e9-8200-0242ac11002e
---
>     ownerReferences:
>     - apiVersion: apps/v1
>       blockOwnerDeletion: true
>       controller: true
>       kind: Deployment
>       name: frontend-deploy
>       uid: 3bb03ca5-b488-11e9-8200-0242ac11002e
>     resourceVersion: "1824"
>     selfLink: /apis/extensions/v1beta1/namespaces/default/replicasets/frontend-deploy-85c49c7b5d
>     uid: 3bb1ac99-b488-11e9-8200-0242ac11002e
16d27
<     progressDeadlineSeconds: 600
18d28
<     revisionHistoryLimit: 10
20a31
>         pod-template-hash: 85c49c7b5d
22,26d32
<     strategy:
<       rollingUpdate:
<         maxSurge: 25%
<         maxUnavailable: 25%
<       type: RollingUpdate
30a37
>           pod-template-hash: 85c49c7b5d
47,59c54
<     conditions:
<     - lastTransitionTime: "2019-08-01T18:14:44Z"
<       lastUpdateTime: "2019-08-01T18:14:44Z"
<       message: Deployment has minimum availability.
<       reason: MinimumReplicasAvailable
<       status: "True"
<       type: Available
<     - lastTransitionTime: "2019-08-01T18:14:42Z"
<       lastUpdateTime: "2019-08-01T18:14:44Z"
<       message: ReplicaSet "frontend-deploy-85c49c7b5d" has successfully progressed.
<       reason: NewReplicaSetAvailable
<       status: "True"
<       type: Progressing
---
>     fullyLabeledReplicas: 3
63d57
<     updatedReplicas: 3

An important difference (in blue above) is the new feature update strategy. Its default is „RollingUpdate“.

However, we will come to that later. Let us scale up the Deployment first.

Step 3: Scale-up the Number of Replicas

Let us scale up the number of replicas. First, we check the ReplicaSet, before we scale up to 5 replicas and then we print out the status of the ReplicaSet again.

kubectl get rs

kubectl scale deploy frontend-deploy --replicas 5

kubeclt get deploy

kubectl get rs

The ID of the ReplicaSet does not change. The number of replicas can be changed without deletion and

Step 4: Change Image

In this step, we will compare, what happens, if an Image of the POD template is changed for a ReplicaSet vs a Deployment. Even though a Deployment is creating a ReplicaSet, we will see, that there is a major difference.

Step 4.1: Change Image of a ReplicaSet

First, we create the minimalistic ReplicaSet of our last blog post, before we change the image version from v3 to v2 with kubectl edit. We will see, that the PODs are not changed by this. For updating the image, you need to delete a POD manually, so a new POD is created from the updated template.

Step 4.1.1 Create ReplicaSet

We create a minimalistic RepicaSet by cutting and pasting the following code into the terminal:

cat <<EOF | kubectl apply -f -
# frontend-minimalistic-rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend-rs
spec:
  # modify replicas according to your case
  replicas: 3
  selector:
    matchLabels:
      tier: my-matching-label-rs     #<------- changed to avoid conflicts with the Deployment
  template:
    metadata:
      labels:
        tier: my-matching-label-rs   #<------- changed to avoid conflicts with the Deployment
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
EOF

# output: replicaset.apps/frontend-rs created

Let us check the image version of the created PODs:

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3

Step 4.1.2 Update Image

We now update the image version

kubectl edit rs frontend-rs
...
        - image: gcr.io/google_samples/gb-frontend:v2  # <---- change v3 -> v2

Step 4.1.3 Check POD Image Versions

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3

Different from what you might have expected, the POD image versions did not change. However, we can force it to change by deleting a POD. A new POD with the updated image is created automatically:

Step 4.1.4 Delete POD and check POD Versions

kubectl get pods
NAME                READY   STATUS    RESTARTS   AGE
frontend-rs-5szv4   1/1     Running   0          9m54s
frontend-rs-gvpgt   1/1     Running   0          9m54s
frontend-rs-rcd27   1/1     Running   0          9m54s

kubectl delete pod frontend-rs-5szv4
pod "frontend-rs-5szv4" deleted

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v3

Here, we can see, that the image of the PODs is updated only if the POD has been deleted. More precisely, the image of a POD cannot be changed, and changing the POD template of a ReplicaSet does not change the existing PODs in any way.

Step 4.1.5 Clean ReplicaSet

Let us now delete the ReplicaSet, so it does not confuse us later on.

kubectl delete rs frontend-rs

Step 4.2: Change Image of a Deployment

Step 4.2.1 Create Deployment

We first re-create the deployment of step 1 above:

kubectl delete frontend-deploy

cat <<EOF | kubectl apply -f -
# frontend-minimalistic-deploy.yaml
apiVersion: apps/v1
kind: Deployment                    #<------------- ReplicaSet -> Deployment
metadata:
  name: frontend-deploy             #<------------- changed rs -> deploy
spec:
  # modify replicas according to your case
  replicas: 3      
  selector:
    matchLabels:
      tier: my-matching-label
  template:
    metadata:
      labels:
        tier: my-matching-label
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
EOF

# output: deployment.apps/frontend-deploy created

Let us check the image version of the created PODs:

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3

Step 4.2.2 Update Image

We now update the image version of the Deployment the same way, as we have previously done with the ReplicaSet:

kubectl edit deploy frontend-deploy
...
        - image: gcr.io/google_samples/gb-frontend:v2  # <---- change v3 -> v2

Step 4.2.3 Observe ReplicaSet

We observe the ReplicaSets right after having changed the image version:

kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
frontend-deploy-68b8c659     1         1         0       6s
frontend-deploy-85c49c7b5d   3         3         3       7m24s

kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
frontend-deploy-68b8c659     2         2         1       23s
frontend-deploy-85c49c7b5d   2         2         2       7m41s

kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
frontend-deploy-68b8c659     3         3         2       25s
frontend-deploy-85c49c7b5d   1         1         1       7m43s

kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
frontend-deploy-68b8c659     3         3         3       28s
frontend-deploy-85c49c7b5d   0         0         0       7m46s

Step 4.2.4 Check POD Image Versions

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2

So, here we see a difference between ReplicaSets and Deployments: while ReplicaSets do not update the PODs, if we change an immutable parameter of the POD template, the Deployment does so. First, the Deployment automatically creates a new ReplicaSet. Then, it gradually spins up PODs in the new ReplicaSet, while scaling down the old ReplicaSet. In the end, only PODs with the new template parameters exist.

Step 5: Rollout, Rollback

Step 5.1: Review the Rollout History

Now we will explore another feature of the Deployments: Rollout and Rollback. We start by looking at the rollout history:

kubectl rollout history deploy frontend-deploy
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

The first revision was the one, which we initially created, using Image version v3, while the second revision has Image version v2:

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2

Step 5.1: Rollout Undo

kubectl rollout undo deploy frontend-deploy
deployment.extensions/frontend-deploy rolled back

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3

kubectl describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3
    Image:          gcr.io/google_samples/gb-frontend:v3

We have rolled back to the original version v3.

The undo command supports an option –to-revison. Let us test it by going back to revision 2 again:

k rollout undo deploy frontend-deploy --to-revision=2
deployment.extensions/frontend-deploy rolled back

k describe pods | grep Image:
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2
    Image:          gcr.io/google_samples/gb-frontend:v2

Note: per default, only the last two revisons are kept. This can be changed with the optional parameter .spec.revisionHistoryLimit

Previous:

ReplicaSets

Next:

Daemonsets (link to be provided)

One comment

  1. Distinguished Kaiser employees, consider this: a singular, impregnable portal crafted to give you unfettered access to your vital professional and personal facets. My HR KP stands as an emblem of modernity, offering you not just a way to peruse benefits, scrutinize pay details, or refine contact specifics but a streamlined voyage through your professional realm.
    kaiser my hr

Comments

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.