Kubernetes Pod, ReplicaSet and Deployment
What is Kubernetes?
Kubernetes is an open source container orchestration engine for automating deployment, scaling, and management of containerized applications. It’s supported by all hyperscaller cloud providers and widely used by different companies. Amazon, Google, IBM, Microsoft, Oracle, Red Hat, SUSE, Platform9, IONOS and VMware offer Kubernetes-based platforms or infrastructure as a service (IaaS) that deploy Kubernetes.
Pod
A Pod is the smallest Kubernetes deployable computing unit. It contains one or more containers with shared storage and network. Usually, Pods have a one-to-one relationship with containers. To scale up, we add more Pods and to scale down, we delete pods. We don't add more containers to a pod for scaling purposes.
A Pod can have multiple containers with different types. We use a multi-container Pod when the application needs a helper container to run side by side with it. This helper container will be created when the application container is created and it will be deleted if the application container is deleted. They also share the same network (which means that they can communicate with each other using localhost) and same storage (using volumes).
We can create a pod using the following command,
This command will create a Pod named nginx
using the nginx
docker image available in docker-hub. To confirm the pod is created successfully, We can run the following command that will list pods in the default namespace,
We also can create Pods using yaml configuration file,
To create this redis Pod, run the following command,
We also can create a multi-container Pod using yaml file,
To create this Pod, run the following command,
This will deploy a logging agent alongside with our web app container to process the logs and send it to a central logging service for example. This pattern is called sidecar
.
Replicaset
A replicaset ensures that the specified number of Pods (replicas) are running at all times. If a Pod goes down for any reason, It automatically creates a new one using the template specified in the yaml file. Here is an example replicaset definition file,
To create this repicaset, run the following command,
Note: In order for the replicaset to work, the spec.selector.matchLabels
must match the spec.template.labels
because the replicaset uses this template to create pods when needed.
Deployment
A Deployment is the recommended choice when it comes to deploy stateless applications in Kubernetes. It automatically creates a replicaset under the hood to ensure the specified number of Pods are running at all times. It also describe how to deploy a new version using deployment strategy, here is an example yaml definition file for a deployment,
To create this nginx Deployment, run the following command,
This will create a deployment named example-nginx-deploy
using the nginx
docker image available in docker-hub. To confirm the deployment is created successfully, We can run the following command that will list deployments in the default namespace,
This will create a ReplicaSet
under the hood to make sure all replicas are up all time,
It will also create 5 replicas using the same docker image specified in the yaml definition file, It uses the name of the deployment as a prefix for the name of the pod as shown below,
Note: In order for the deployment to work, the spec.selector.matchLabels
must match the spec.template.labels
because the deployment uses this template to create pods when the current number of pods doesn't match the desired number of pods.
Scaling a Deployment
When creating a Deployment, We need to specify the number or replicas (default is one). Sometimes we need to scale up (increase the number of replicas) or scale down (decrease the number of replicas) manually. We can do this by running the following commands:
Scaling up example-nginx-deply
from 5 replicas to 10 replicas:
To confirm, We can list all pods in the default namespace. As you can see below, There are five new replicas created.
Scaling down example-nginx-deply
from 10 replicas to 3 replicas:
To confirm, We can list all pods in the default namespace. As you can see below, There are only three replicas running and the rest are terminating.
Zero downtime Deployment
The main point of using a deployment in Kubernetes is that we can easily deploy a new version of our application using the deployment strategy defined in the deployment and we can also roll it back easily if this new version didn't work as expected with zero downtime.
We use .spec.strategy
to specify how we want to deploy this new version. We have two types of deployment strategies, Recreate
and RollingUpdate
. RollingUpdate
is the default value.
Recreate
Deployment Strategy means that all current pods with the old version will be killed and new pods will be created using the new version. This will cause the application to be down for sometime (depends on how long it takes to start the app). This is not the preferred option because of the downtime.
RollingUpdate
Deployment Strategy means that it will run both versions (the old and new one) for sometime until the deployment is completed. based on the .spec.strategy.rollingUpdate.maxUnavailable
and .spec.strategy.rollingUpdate.maxSurge
values, it will create new pods with the new version and delete old pods with the old version. if we configured this correctly, we can assure that the deployment is zero downtime deployment.
Here is an example to make it more clear,
In this example deployment, we have ten replicas and RollingUpdate strategy with maxSurge
is 30% (it can also be an absolute number) which means that this deployment can run 30% more replicas if needed (instead of creating 10 replicas, it can create 13 replicas temporary for both old and new versions) and maxUnavailable
is 20% (it can also be an absolute number) which is the maximum number of unavailable pods during the update process (20% of ten replicas is two pods)
The default value for maxSurge
and maxUnavailable
is 25%.
Rollout and Rollback a Deployment
To deploy a new version of a deployment we use the following command,
Note: The record flag is deprecated but there is no alternative to it yet. for more info check this.
To check the status of the deployment,
As you can see from the logs, it first created two pods with the new version. Once they are up and running it starts to terminate old pods (using old version) and create new pods (using new version) one by one to make sure the application is up and running at all times.
we can see this more clearly from the deployment events,
$ kubectl describe deployments
Name: example-nginx-deploy
Namespace: default
CreationTimestamp: Sun, 18 Sep 2022 11:42:41 +0200
Labels: app=example-nginx-deploy
Annotations: deployment.kubernetes.io/revision: 2
Selector: app=example-nginx-deploy
Replicas: 5 desired | 5 updated | 5 total | 5 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 20% max unavailable, 30% max surge
Pod Template:
Labels: app=example-nginx-deploy
Containers:
nginx:
Image: nginx:1.16.1
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: example-nginx-deploy-78788d9bbd (5/5 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 8m13s deployment-controller Scaled up replica set example-nginx-deploy-78788d9bbd to 2
Normal ScalingReplicaSet 8m13s deployment-controller Scaled down replica set example-nginx-deploy-bbc95f979 to 4
Normal ScalingReplicaSet 8m13s deployment-controller Scaled up replica set example-nginx-deploy-78788d9bbd to 3
Normal ScalingReplicaSet 4m57s deployment-controller Scaled down replica set example-nginx-deploy-bbc95f979 to 3
Normal ScalingReplicaSet 4m57s deployment-controller Scaled up replica set example-nginx-deploy-78788d9bbd to 4
Normal ScalingReplicaSet 4m53s deployment-controller Scaled down replica set example-nginx-deploy-bbc95f979 to 2
Normal ScalingReplicaSet 4m53s deployment-controller Scaled up replica set example-nginx-deploy-78788d9bbd to 5
Normal ScalingReplicaSet 4m49s deployment-controller Scaled down replica set example-nginx-deploy-bbc95f979 to 1
Normal ScalingReplicaSet 4m46s deployment-controller Scaled down replica set example-nginx-deploy-bbc95f979 to 0
Let's say nginx 1.16.1 is a buggy version and we want to rollback to the previous version. First we need to check the rollout history,
kubectl rollout history deployment/example-nginx-deploy
deployment.apps/example-nginx-deploy
REVISION CHANGE-CAUSE
1 <none>
3 kubectl set image deployment/example-nginx-deploy nginx=nginx:1.14.2 --record=true
4 kubectl set image deployment/example-nginx-deploy nginx=nginx:1.16.1 --record=true
To rollback to previous version, Run the following command,
Conclusion
A Pod is the smallest Kubernetes deployable computing unit. It contains one or more containers with shared storage and network. A replicaset ensures that the specified number of Pods (replicas) are running at all times. If a Pod goes down for any reason, It automatically creates a new one using the template specified in the yaml file. A Deployment is the recommended choice when it comes to deploy stateless applications in Kubernetes. It automatically creates a replicaset under the hood to ensure the specified number of Pods are running at all times. It can be easily scaled up or down using kubectl scale
command. It also enables us to easily rollout a new version of our application using the specified deployment strategy and rollback to previous version if needed.