Kubernetes Camp

Learn Kubernetes on your Coffee Break

2. Scale and upgrade your application

Part of Running an application is being able to scale it to meet traffic demands, and to upgrade it when new versions of the software is available.

Thankfully Kubernetes makes both of these things really easy. In the previous steps we ran an application by creating a Deployment. A Deployment is a Controller with special properties to help you both scale and upgrade your workload.

Do

Validate your running workload

We currently have a matching set of a Deployment, a ReplicaSet and a Pod in our cluster. Run kubectl get all:

Note: If these resources are missing you can go back to the previous step and rerun the commands to deploy an application.

$ kubectl get all
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/first   1/1     1            1           15h

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/first-7f77d57ccc   1         1         1       15h

NAME                         READY   STATUS    RESTARTS   AGE
pod/first-7f77d57ccc-8gwkp   1/1     Running   0          15h

You can see that the ReplicaSet shows a DESIRED and a CURRENT count of pods under its control. The ReplicaSet is managed by the Deployment, and is itself managed by the Deployment. The ReplicaSet will create or destroy Pods in order to make the current state match the desired state.

Scale your application out

You can run kubectl scale to change the desired state like so:

Note: since the ReplicaSet is managed by the Deployment we actually want to point the scale command at the Deployment resource.

$ kubectl scale --replicas=3 deployment/first
deployment.extensions/first scaled

Since our image is quite small, it should take just a few seconds for the scale event to occur which we can check with another kubectl get all:

$ kubectl get all
NAME                         READY   STATUS    RESTARTS   AGE
pod/first-7f77d57ccc-7h9ch   1/1     Running   0          4s
pod/first-7f77d57ccc-8gwkp   1/1     Running   0          20h
pod/first-7f77d57ccc-c2j4x   1/1     Running   0          4s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   20h

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/first   3/3     3            3           20h

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/first-7f77d57ccc   3         3         3       20h

You can see that the Deployment was updated to expect 3, which updated the ReplicaSet which created two more pods.

Note: If we had scaled the ReplicaSet directly, it would immediately be changed back to the original size as the reconciliation loop of the Deployment controller would see the actual state of the ReplicaSet no longer matches the Desired state. Try it and see what happens if you run kubectl scale --replicas=5 rs/first-7f77d57ccc (change the name to match your output).

Upgrade your application

If you remember that very first command we used to create this Deployment (kubectl create deployment first image=nginx) you’ll note that we didn’t specify a version of nginx to run.

It’s always a good idea to be as specific as possible, so lets upgrade our application to be a very specific version of nginx. We can do this with the kubectl set command:

$ kubectl set image deployment/first nginx=nginx:1.17.2
deployment.extensions/first image updated

Immediately re-run kubectl get all and if you’re fast enough you’ll catch the Deployment mid-upgrade:

Note: if you’re fast enough you’ll see new Pods starting to run, and you’ll see the old Pods being Terminated as the Deployment controller juggles a pair of ReplicaSets.

$ kubectl get all
NAME                         READY   STATUS              RESTARTS   AGE
pod/first-765d49ddcb-f6hb4   1/1     Running             0          3s
pod/first-765d49ddcb-gcgkn   0/1     ContainerCreating   0          1s
pod/first-844f75c9b8-4cvgv   1/1     Running             0          4m10s
pod/first-844f75c9b8-kzzhs   1/1     Running             0          4m17s
pod/first-844f75c9b8-wwmkg   0/1     Terminating         0          4m7s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   21h

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/first   3/3     2            3           20h

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/first-765d49ddcb   2         2         1       3s
replicaset.apps/first-844f75c9b8   2         2         2       4m17s

Learn

In this Lesson you utilized the scaling and upgrade capabilities of the Deployment controller. By changing the image version in the Deployment you signaled to the Deployment controller that you had a new desired state. In order to bring the actual state into line with the desired state the Deployment controller creates a second ReplicaSet and it scales that new ReplicaSet up as it scales the old ReplicaSet down in a way to ensure that the actual number of Pods running always matches the desired number (in this case 3).

This rolling upgrade of your application is completely transparent to you, the Deployment controller manages it for you, and it does it in a way to ensure as little disruption to end users as possible.

Speaking of end users, wouldn’t it be nice if you could set up access to the application? We can’t expect everyone to run kubectl port-forward to access our app.

Next Creating services to provide access into your application.