Kubernetes Basics – Deployments

Introduction

In previous posts on Kubernetes basics, We learned that Kubernetes is all about running containerized apps. A Kubernetes cluster consists of masters and nodes which we can manage through an API using kubectl command line tool.

We also learned that Pods are the smallest deployable unit in Kubernetes API and Pod hosts the container(s). Then we covered Services in Kubernetes and saw that they provides stable networking to ephemeral pods.

If you are new to these topics, I will suggest to first check out the previous posts in this series as we will be building on top of what we have covered already.

Another common set of requirements with applications are ability to recover from crashes, hardware failures, ability to horizontally scale and rollbacks to previous versions if needed.

Today, we will cover Deployments and how they provide self-healing, scaling, rolling updates and rollbacks to our application.

Official kubernetes website describe them as “In kubernetes a deployment provides declarative updates for Pods and Replica-sets”.

Like Pods and services, deployments are fundamental objects in kubernetes API. The following pictures illustrate how deployment wraps the pods. However, there is another object called Replica-Set which sit between the pods and the deployment, so its actually replica-set which does the self-healing and scaling stuff.

We normally do not deal with replica-sets, we actually deal with deployment and then deployment handles all the replica-set stuff behind the scenes.

Setting the Scene

Before we create the deployment, lets see what’s running in our cluster:

As you can see that, we have one pod and one service running from previous posts. I then deleted the Pod using kubectl command and now if we check again we do not have any pod running and also no deployment and no replica-sets as well.

Create a Deployment

Like we did with Pods and Services, we can create a deployment using a YAML file.

That’s what a deployment YAML file looks like. As you can see that it follows the similar structure like we have for pods and services. I also showed that how a deployment wraps a pod.

So we have a containerized app, then a pod wraps it and then a deployment wraps the pod. We also mention replicas: 5 in the deployment section; we are telling that we want 5 copies of our pod. Notice the selector with matchLabels which will be matched with labels defined in pod section. That’s how a deployment is associated to a Pod.

Next, lets apply this deployment using kubectl as shown below:

kubectl apply -f deploy.yaml

here is the command output:

So, our deployment is created. Next, lets run kubectl get all command again to see what is the effect of applying the deployment:

As you can see that, we now have 5 pods which matches with replicas:5 we defined in the deployment. Services are just like before, we had in previous post (no change here). Then we have two new objects and those are deployment and replicaset, the deployment we just created and replicaset we did not created directly, however it is created by deployment behind the scene.

Now, we have 5 pods running, to connect to them we need a service and we already have a service which we created in previous post, lets do the Postman API test (please check the previous post for details) as shown below:

Now, lets try to access this endpoint from a browser:

Notice the issuer value is changed, and if you match this value with pods name shown above, you will see that our http requests are being load-balanced (thanks to services).

Self Healing and Scaling

So, we have our 5 pods running. But we also get self-healing and scaling automatically as are baked into kubernetes and are easy to use. Behind the scenes, Replica-sets handles these stuff.

Self Healing

So, we have five pods, and stuff on control-plane watching that we have our desired state of 5 pods. Everything is good and calm. Let’s delete a pod using kubectl as shown below:

so, desired-state says 5 pods, we remove one pod. Kubernetes will go into action and will create a new pod to match desire state. If we list pods again, you will notice that a new Pod is automatically spin up by kubernetes. Kubernetes detected that and because the desired state of cluster is not matching, it does the necessary actions and created a new pod to match the desired state (i.e. 5 pods).

This is called self-healing and deployments (by virtue of replica-sets) provide self healing capabilities to our apps.

Also, if we take the node itself down it will also recover from that too. As I am running a single-node cluster (docker desktop), we will not go into more details today. However in some later posts we will cover it when we will use some cloud provider for kuberetes.

Scaling

We can easily scale up or down our applications. We just need to update the YAML file (replicas) and apply it as shown below:

and as you can see that kubernetes will start new pods to match the desired state. In the similar fashion we can reduce the number of pods by changing the replicas value and apply the deployment and that’s how we can scale up or scale down as needed.

Kubernetes also support auto-scaling based on matrices too.

Service Endpoints

When we scaled up, service detected that new Pods have arrived and it automatically added those to endpoint object.

We can get the list of endpoints and then describe then further inspect it using following kubectl command:

kubectl get ep
kubectl describe ep tokengen

Here is the output:

Notices the Addresses item, it lists healthy pods that match label selector. So labels are dynamic and are properly associating pods with service.

Rolling Updates and Rollbacks

We said earlier that Replica-Sets handle replicas and self-healing and deployments are in-charge of like update and rollback stuff.

Rolling Update

I’ve updated the application a little bit and also pushed updated image to docker hub:

docker image build -t jawadhasanshani/dotnettokengen:v2
docker push jawadhasanshani/dotnettokengen:v2

So, we have an updated image of our application in docker-hub, lets see how can we apply this update using kubernetes.

Lets update the deploy.yaml file with following section:

Just above the pod template, insert the shown section.

type: RollingUpdate = This says that anytime we update container (image) section then instead of updating all updates at once, do it in kind of Rolling Update fashion.

maxUnavailable:0 = When doing updates we can have at most 0 less than 10 (10 being replicas), so never drop below 10 replicas.

maxSurge:1 = Says, during update, we are allowed to surge 1 more than desired state, so we can go to 11 during this update.

So, kubernetes will deploye 1 new pod, taking from 10 to 11 pods. Once thats up and running for minReadySeconds:5 (5 seconds) after that it will terminate an old pod and takes us pack to 10 and repeat till the update is completed.

I have opened three power-shell windows for following commands as shown below:

kubectl get pods --watch
kubectl apply -f deploy.yaml
kubectl rollout status deploy tokengen

So, I can apply the deployment and then check the status using rollout status deploy command and following pictures shows that pods are being updated in rolling fashion:

With our updates deployed, lets call the application endpoint and see the updates:

Rollbacks

Even we deployed the update, old replicas stick around. Lets run the following command:

kubectl get rs

here is the command output:

As you can see that we still have old replica-set, its not managing any pods, but its still there.

Lets describe this replica-set with following command:

As you can see that old replica-set points to older version. This very characteristic enables roll backs.

We can see the deployment history using following command:

kubectl rollout history deploy tokengen

here is the command output:

Now to roll-back to previous version (Revision 1) we can execute following command:

kubectl rollout undo deploy tokengen --to-revision=1

You can use split powershell windows to see the rollback updates (as we did in previous section) and here is the command output of this rollback:

and just with that, our application is rolled-back to previous version and we can test the API call to confirm that (notice version value is not in the response):

Deleting a Deployment

The following command shows how to delete a deployment:

kubectl delete deployment tokengen

As you can see that deleting a deployment also deletes the replica-sets and pods:

With this we will end this learning here. I hope that it provides you some useful information about role of deployments in kubernetes.

Summary

In this post we learned how deployments provides a declarative way to enrich our applications with self-healing, scalability, rolling updates and rollbacks capabilities. There is more to deployment and you can find more information on official kubernetes documentation online.

You can download the source code from this git repository.

Let me know, if you have some questions or comments. Till next time, Happy Coding.

My Recent Books