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:
Next:
Daemonsets (link to be provided)
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