startkubernetes

Kubernetes 101 - Free Online Course

Learn the basics of Kubernetes

Deployments

Creating Deployments

A deployment resource is a wrapper around the ReplicaSet that allows doing controlled updates to your Pods. For example, if you want to update image names for all Pods, you can edit the Pod template, and the deployment controller will re-create Pods with the new image.

If we continue with the same example as we used before, this is how a Deployment would look like:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
  labels:
    app.kubernetes.io/name: hello
spec:
  replicas: 5
  selector:
    matchLabels:
      app.kubernetes.io/name: hello
  template:
    metadata:
      labels:
        app.kubernetes.io/name: hello
    spec:
      containers:
        - name: hello-container
          image: busybox
          command: ["sh", "-c", "echo Hello from my container! && sleep 3600"]

The YAML for Kubernetes Deployment looks almost the same as for a ReplicaSet. There's the replica count, the selector labels, and the Pod template.

Save the above YAML contents in deployment.yaml and create the deployment:

$ kubectl apply -f deployment.yaml --record
deployment.apps/hello created

NOTE: Why the --record flag? Using this flag, we are telling Kubernetes to store the command we executed in the annotation called kubernetes.io/change-cause. Record flag is useful to track the changes or commands that you executed when the deployment was updated. You will see this in action later on when we do rollouts.

To list all deployments, we can use the get command:

$ kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
hello   5/5     5            5           2m8s

The output is the same as when we were listing the ReplicaSets. When we create the deployment, controller also creates a ReplicaSet:

$ kubectl get rs
NAME               DESIRED   CURRENT   READY   AGE
hello-6fcbc8bc84   5         5         5       3m17s

Notice how the ReplicaSet name has the random string at the end. Finally, let's list the Pods:

$ kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
hello-6fcbc8bc84-27s2s   1/1     Running   0          4m2s
hello-6fcbc8bc84-49852   1/1     Running   0          4m1s
hello-6fcbc8bc84-7tpvs   1/1     Running   0          4m2s
hello-6fcbc8bc84-h7jwd   1/1     Running   0          4m1s
hello-6fcbc8bc84-prvpq   1/1     Running   0          4m2s

When we created a ReplicaSet previously, the Pods got named like this: hello-fchvr. However, this time, the Pod names are a bit longer - hello-6fcbc8bc84-27s2s. The random middle section in the name 6fcbc8bc84 corresponds to the random section of the ReplicaSet name, and the Pod names get created by combining the deployment name, ReplicaSet name, and a random string.

Deployment, ReplicaSet, and Pod naming

Just like before, if we delete one of the Pods, the Deployment and ReplicaSet will make sure awalys to maintain the number of desired replicas:

$ kubectl delete po hello-6fcbc8bc84-27s2s
pod "hello-6fcbc8bc84-27s2s" deleted

$ kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
hello-6fcbc8bc84-49852   1/1     Running   0          46m
hello-6fcbc8bc84-58q7l   1/1     Running   0          15s
hello-6fcbc8bc84-7tpvs   1/1     Running   0          46m
hello-6fcbc8bc84-h7jwd   1/1     Running   0          46m
hello-6fcbc8bc84-prvpq   1/1     Running   0          46m

How to scale the Pods up or down?

There's a handy command in Kubernetes CLI called scale. Using this command, we can scale up (or down) the number of Pods controlled by the Deployment or a ReplicaSet.

Let's scale the Pods down to three replicas:

$ kubectl scale deployment hello --replicas=3
deployment.apps/hello scaled

$ kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
hello-6fcbc8bc84-49852   1/1     Running   0          48m
hello-6fcbc8bc84-7tpvs   1/1     Running   0          48m
hello-6fcbc8bc84-h7jwd   1/1     Running   0          48m

Similarly, we can increase the number of replicas back to five, and ReplicaSet will create the Pods.

$ kubectl scale deployment hello --replicas=5
deployment.apps/hello scaled

$ kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
hello-6fcbc8bc84-49852   1/1     Running   0          49m
hello-6fcbc8bc84-7tpvs   1/1     Running   0          49m
hello-6fcbc8bc84-h7jwd   1/1     Running   0          49m
hello-6fcbc8bc84-kmmzh   1/1     Running   0          6s
hello-6fcbc8bc84-wfh8c   1/1     Running   0          6s

Updating the Pod templates

When we were using a ReplicaSet we noticed that ReplicaSet did not automatically restart the Pods when we updated the image name. However, Deployment can do this.

Let's use the set image command to update the image in the Pod templates from busybox to busybox:1.31.1.

You can use the set command to update the parts of the Pod template, such as image name, environment variables, resources, and a couple of others.

$ kubectl set image deployment hello hello-container=busybox:1.31.1 --record
deployment.apps/hello image updated

If you run the kubectl get pods right after you execute the set command, you might see something like this:

$ kubectl get po
NAME                     READY   STATUS        RESTARTS   AGE
hello-6fcbc8bc84-49852   1/1     Terminating   0          57m
hello-6fcbc8bc84-7tpvs   0/1     Terminating   0          57m
hello-6fcbc8bc84-h7jwd   1/1     Terminating   0          57m
hello-6fcbc8bc84-kmmzh   0/1     Terminating   0          7m15s
hello-84f59c54cd-8khwj   1/1     Running       0          36s
hello-84f59c54cd-fzcf2   1/1     Running       0          32s
hello-84f59c54cd-k947l   1/1     Running       0          33s
hello-84f59c54cd-r8cv7   1/1     Running       0          36s
hello-84f59c54cd-xd4hb   1/1     Running       0          35s

The controller terminated the Pods and has started five new Pods. Notice something else in the Pod names? The ReplicaSet section looks different, right? That's because Deployment scaled down the Pods controlled by the previous ReplicaSet and create a new ReplicaSet that uses the latest image we defined.

Remember that --record flag we set? We can now use rollout history command to view the previous rollouts.

$ kubectl rollout history deploy hello
deployment.apps/hello
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=deployment.yaml --record=true
2         kubectl set image deployment hello hello-container=busybox:1.31.1 --record=true

The history command shows all revisions you made to the deployment. The first revision is when we initially created the resource and the second one is when we updated the image.

Let's say we rolled out this new image version, but for some reason, we want to go back to the previous state. Using the rollout command, we can also roll back to an earlier revision of the resource.

To roll back, you can use the rollout undo command, like this:

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

With the undo command, we rolled back the changes to the previous revision, which is the original state we were in before we updated the image:

$ kubectl rollout history deploy hello
deployment.apps/hello
REVISION  CHANGE-CAUSE
2         kubectl set image deployment hello hello-container=busybox:1.31.1 --record=true
3         kubectl apply --filename=deployment.yaml --record=true

Let's remove the deployment by running:

$ kubectl delete deploy hello
deployment.apps "hello" deleted

Enjoying this course? Subscribe for more content from Peter.

Peter Jausovec

Peter Jausovec
Full-Stack Developer

Peter is a software engineer focused on developing distributed systems and cloud-native solutions using Docker, Kubernetes, and Istio. I am an author of multiple books, speaker, and trainer.