In the last part of this series, you learnt about ReplicaSet and its functionalities to make the management of Kubernetes applications easier. We will take a step further in this part by introducing you to Kubernetes Deployment. You will learn how to use Deployment to create a Pod, upgrade or downgrade your application with zero downtime and other Deployment actions using hands-on practice in this part of the series. Questions like why do we need Deployment, and the relationship between Deployment and ReplicaSet will be answered in this section.
What is a Deployment in Kubernetes?
A Deployment is one of the Kubernetes objects that is used to manage Pods via ReplicaSets in a declarative way. It provides updates, control as well as rollback functionalities. This means you can update or downgrade an application to the desired version without experiencing a user blackout as well as roll back to the previous version in case the new version is unstable or filled with bugs. Also, using a declarative management style for Deployment allows it to bring the desired states of the defined application in a YAML file into reality.
Deployment Features
A Deployment has the following features:
- Create a ReplicaSet and Pods
- Update a ReplicaSet
- Scale-up/down a Deployment
- Pause/continue a Deployment
- Rollback to the previous version
- Clean up unwanted ReplicaSets
Creating a Kubernetes Deployment
We will create a Deployment that will roll out a ReplicaSet to bring up three instances of an nginx Pod. You must have a running Kubernetes cluster with the kubectl command-line tool configured and connected to it to follow this exercise. Check KubeOne doc for a guide on getting a running Kubernetes cluster using KubeOne. Basic knowledge of Pod and ReplicaSet is suggested to follow this hands-on practice.
Creating a Deployment is the same as creating a ReplicaSet, but Deployment is the kind property’s value
. Moreso, strategy property and values
need to be added to the manifest file.
Step1: Create a YAML manifest file named my-deployment.yaml
using vim on the command line.
$ vim my-deployment.yaml
Step2: Copy, paste, and save the configuration below into your YAML file.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-deployment-container
image: nginx
The above configuration file defined a Deployment object named my-deployment
under the metadata.name
property with Deployment
as the value of its kind
property.
spec.replicas: ## the Deployment will create the number of replicated Pods specified in this field
spec.strategy.type: ## the desired strategy type is declared in this field
The strategy is a child of the spec while type is a child of the strategy and grandchild of spec
spec.selector: ## this field defines how the Deployment determines which Pods to manage
spec.containers: ## the container name and image are declared in this field
NOTE: The file must be correctly indented to avoid errors.
Step2: Run this command to create a Deployment:
$ kubectl create -f my-deployment.yaml
deployment.apps/my-deployment created
Step3: Check the Deployment status to see if it has been created.
$ kubectl get deployments my-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 0/3 0 0 2s
When you see an output like this, it means the Deployment is still being created. Wait for a few seconds and run the kubectl get
command once again. Once it is ready, the output will look like this.
$ kubectl get deployment my-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 3/3 3 3 95s
The status output is further broken down below:
Name: ## Shows the name of the Deployment as declared in the manifest file
Ready: ## This shows the number of replicas that are ready for use. In this case, all 3 out of 3 are ready for use
Up-To-Date: ## This shows the up-to-date number of replicas out of the desired number declared in the YAML file
Available: ## This shows the number of replicas that are available for use
Age: ## Shows the duration the application has been running
Step 4: Check the Pod status to confirm if the desired number of Pods are running.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-deployment-6b9b97d749-4fv5n 1/1 Running 0 3m58s
my-deployment-6b9b97d749-lscf2 1/1 Running 0 3m58s
my-deployment-6b9b97d749-p422m 1/1 Running 0 3m58s
To delete one of the instances of the Pod:
$ kubectl delete pod my-deployment-6b9b97d749-4fv5n
pod "my-deployment-6b9b97d749-4fv5n" deleted
Check if it has been deleted.
$kubectl get pods
NAME READY STATUS RESTARTS AGE
my-deployment-6b9b97d749-lscf2 1/1 Running 0 8m3s
my-deployment-6b9b97d749-p422m 1/1 Running 0 8m3s
my-deployment-6b9b97d749-t2zmh 1/1 Running 0 54s
As seen above, three instances of Pod are running while the old ones have already been terminated or deleted. This was made possible with the help of ReplicaSet. One of the importance of ReplicaSet in a Deployment is to ensure that the desire instances of a Pod are up-to-date and are continually running on the cluster. The number of running instances depends on the ReplicaSet value
declared in the YAML manifest file.
To view the description of the Deployment:
$ kubectl describe deployments my-deployment
Name: my-deployment
Namespace: default
CreationTimestamp: Mon, 27 Jul 2020 17:22:40 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=my-app
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: Recreate
MinReadySeconds: 0
Pod Template:
Labels: app=my-app
Containers:
my-deployment-container:
Image: nginx
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: my-deployment-97cfc859f (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 7m25s deployment-controller Scaled up replica set my-deployment-97cfc859f to 3
The Deployment description is further expantiated below:
Name: ## The name of the Deployment as specified in the manifest file.
Namespace: ## It is always a default if no namespace is specified in the manifest file.
Replicaset: ## The desired number of replicas specified in the manifest file.
Strategy.recreate: ## The strategy to be used for the Deployment. You can find more info on Deployment strategy in the next part of this series.
Containers.image: ## This field specifies the container and container image names.
Events: ## Shows the Deployment activities since it was created.
Updating a Kubernetes Deployment
You can edit a Deployment by changing the container image from one version to the other, decreasing or increasing the number of instances by changing the ReplicaSet value. etc. For example, the container image nginx
we have been using in our exercises has many versions. When no version is specified in the manifest YAML file, the latest version will be pulled from the image repository. We will change the current image version to another as an example.
A Deployment can be updated to use a new image in two ways:
Method 1: You can pass the new image tag directly to the Deployment using flags with the kubectl command-line tool
.
We will change the nginx
in our manifest file to use the nginx:1.18.0
version.
$kubectl --record deployment.apps/my-deployment set image deployment.v1.apps/my-deployment my-deployment-container=nginx:1.18.0
deployment.apps/my-deployment image updated
or
$kubectl set image deployment/my-deployment my-deployment-container=nginx:1.18.0 --record
deployment.apps/my-deployment image updated
In the above command, my-deployment
is the name of the Deployment and my-deployment-container
is the container name as declared in the YAML file.
Check the description again and compare it to the original configuration.
$kubectl describe deployment my-deployment
Name: my-deployment
Namespace: default
CreationTimestamp: Mon, 27 Jul 2020 17:22:40 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 2
kubernetes.io/change-cause:
kubectl deployment.apps/my-deployment set image deployment.v1.apps/my-deployment my-deployment-container=nginx:1.18.0 --record=true
Selector: app=my-app
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: Recreate
MinReadySeconds: 0
Pod Template:
Labels: app=my-app
Containers:
my-deployment-container:
Image: nginx:1.18.0
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: my-deployment-79f645dc59 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set my-deployment-97cfc859f to 3
Normal ScalingReplicaSet 32s deployment-controller Scaled down replica set my-deployment-97cfc859f to 0
Normal ScalingReplicaSet 23s deployment-controller Scaled up replica set my-deployment-79f645dc59 to 3
Comparing the description outputs of the original and updated versions, we have changed the image version from nginx
to nginx:1.18.0
as it is stated in the Pod template. In addition, there are more events compared to before the update describing the internal processes of the rolling update. It shows here that the Deployment updated the Pods by creating and scaling a new ReplicaSet of 3 replicas and destroying the old one. Check the ReplicaSet status for clarity.
$kubectl get replicaset
NAME DESIRED CURRENT READY AGE
my-deployment-79f645dc59 3 3 3 76s
my-deployment-97cfc859f 0 0 0 4m53s
Method 2: Directly editing the manifest YAML file.
Alternatively, you can edit the Deployment YAML file and change the current image version from nginx:1.18.0
to nginx:1.19.1
by running the below command then save and exit the terminal:
$kubectl edit deployment.v1.apps/my-deployment
deployment.apps/my-deployment edited
Check the status of the Deployment to see that we still have 3 deployments ready.
$kubectl get deployment my-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 3/3 3 3 29m
Check the description of the Deployment to see that the image has been updated.
$kubectl describe deployment my-deployment
Name: my-deployment
Namespace: default
CreationTimestamp: Mon, 27 Jul 2020 18:18:58 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 3
kubernetes.io/change-cause: kubectl set image deployment/my-deployment my-deployment-container=nginx:1.18.0 --record=true
Selector: app=my-app
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: Recreate
MinReadySeconds: 0
Pod Template:
Labels: app=my-app
Containers:
my-deployment-container:
Image: nginx:1.19.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: my-deployment-5997f87f5f (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 30m deployment-controller Scaled up replica set my-deployment-97cfc859f to 3
Normal ScalingReplicaSet 27m deployment-controller Scaled down replica set my-deployment-97cfc859f to 0
Normal ScalingReplicaSet 27m deployment-controller Scaled up replica set my-deployment-79f645dc59 to 3
Normal ScalingReplicaSet 2m39s deployment-controller Scaled down replica set my-deployment-79f645dc59 to 0
Normal ScalingReplicaSet 2m31s deployment-controller Scaled up replica set my-deployment-5997f87f5f to 3
Finally, checking the ReplicaSet status, you can see that we created a new Deployment and scaled it up to 3 replicas while the old one was scaled down to 0. Check the ReplicaSet status:
$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
my-deployment-5997f87f5f 3 3 3 72s
my-deployment-79f645dc59 0 0 0 25m
my-deployment-97cfc859f 0 0 0 29m
Clean-up:
Delete the Deployment using the kubectl delete
command.
Summary:
The exercises and concepts we walked you through demonstrate how using Kubernetes Deployments rather than Pods to manage your application is one of the best Kubernetes practices. Deployments make the scaling up and down of Pod via ReplicaSet easier and flexible.
Next in our series, we will look at Deployment strategies, types, and their functionalities. We encourage you to contact us with any questions you have.
Learn More
- Learn more about Kubernetes Deployment on Kubernetes official website
- Read more on rolling update Deployment here