Introduction to Kubernetes
With containerization growing in popularity and altering the process of developing, distributing, and sustaining applications, there was a need to handle these containers effectively. To manage the lifetime of these containers in large-scale systems, many container orchestration solutions have been introduced.
Provisioning and deployment, resource allocation and load distribution, service discovery, and high availability are just a few of the many functions handled by orchestration tools like Kubernetes. With this platform, we can break down our applications into smaller systems (known as microservices) during development and then compose (or orchestrate) these systems together during deployment.
The use of a cloud-native strategy has led to an increase in the development of micro-service-based applications. Deployment is a significant issue for these kinds of apps. It is critical to have a well-thought-out deployment strategy. There are several ways to release an application in Kubernetes, and you must choose the best technique to ensure the reliability of your infrastructure during the deployment or update of an application. You must constantly ensure that end-users will not be affected by any downtime in a production environment, for example. The optimal method for Kubernetes orchestration ensures the effective management of various container image versions. To summarize, the focus of this post will be on Kubernetes’ many deployment options.
What is Kubernetes Deployment?
In Kubernetes, a Deployment is a resource object that defines the desired state of our program. Deployments are declarative, which means that we do not define how the state is achieved. Rather than that, we declare the intended state and let the Deployment-controller determine the most efficient path to that state. A deployment enables us to specify the lifecycle of an application, including which images to use, the number of pods to utilize, and how they should be updated.
The Advantages of Kubernetes Deployment
Manually updating containerized programs is a time-consuming and arduous operation. A Kubernetes deployment automates and repeats this operation. The Kubernetes backend manages deployments entirely, and the entire update process occurs purely on the server-side, without client interaction.
Additionally, the Kubernetes deployment controller monitors the health of pods and nodes at all times. It can be used to replace a failing pod or to bypass down nodes, ensuring the continued operation of mission-critical applications.
Features of Kubernetes Deployment
A Deployment possesses the following characteristics:
- Create a Replica Set and its associated Pods
- Replica Set Update
- Scale-up/Scale-down a Deployment
- Continuation/Pause of a Deployment
- Revert to a prior version
- Eliminate unused Replica Sets
Creating a Kubernetes Deployment Strategy
We will design a Deployment that deploys a ReplicaSet and starts three instances of an Nginx Pod. To complete this experiment, you must have a working Kubernetes cluster with the kubectl command-line tool configured and linked to it. Consult the KubeOne documentation for instructions on setting up a Kubernetes cluster using KubeOne. Following this hands-on experience, it is recommended that you have a working knowledge of Pod and ReplicaSet.
Generating a Deployment is similar to creating a ReplicaSet, except that Deployment is the value of the kind property. In addition, strategy properties and values must be included in the manifest file.
Step 1: Create a my-deployment.YAML manifest file. YAML on the command line with vim
$ Vim my-deployment.YAML
Step 2: Paste the configuration below into your YAML file and save it.
—————————————————————————————————————
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 metadata.name field in the above configuration file defined a Deployment object named my-deployment, 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 the 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: To avoid errors, the file must be properly indented.
Step 3: To create a Deployment, run this command
—————————————————————————————————————-
$ kubectl create -f my-deployment.YAML
deployment.apps/my-deployment created
—————————————————————————————————————-
Step 4: Check the status of the deployment 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
—————————————————————————————————————-
If you get an output like this, it signifies the Deployment is still in the process of being generated. Wait a few seconds before rerunning the kubectl get command. This is what the output will look like after it’s finished.
—————————————————————————————————————-
$ kubectl get deployment my-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 3/3 3 3 95s
—————————————————————————————————————-
The following is a breakdown of the status output:
—————————————————————————————————————-
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 5: Verify that the desired number of Pods is running by checking the Pod status.
—————————————————————————————————————-
$ 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 Pod’s instances:
—————————————————————————————————————-
$ kubectl delete pod my-deployment-6b9b97d749-4fv5n
pod “my-deployment-6b9b97d749-4fv5n” deleted
—————————————————————————————————————-
Check to see whether it was 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
—————————————————————————————————————-
Three instances of Pod are currently running, while the previous ones have been destroyed or deleted. This was made feasible through ReplicaSet. One of the most critical functions of a ReplicaSet in a Deployment is to ensure that the desired instances of a Pod are always up to date and operating on the cluster. The number of running instances is determined by the value of the ReplicaSet attribute in the YAML manifest.
To view the Deployment’s description:
—————————————————————————————————————-
$ 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 next section expands on the deployment description:
—————————————————————————————————————-
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.
—————————————————————————————————————-
Kubernetes Deployment Update
You can update a Deployment by changing the container image from one version to another, adjusting the ReplicaSet value to decrease or increase the number of instances, and so on. For example, the Nginx container image we’ve been utilizing in our exercises comes in a variety of flavors. The newest version will be pulled from the image repository if no version is given in the manifest YAML file. As an example, we’ll update the current image version to a different one.
There are two ways to update deployment to use a fresh image:
Method 1: Using the kubectl command-line tool, you can give the updated image tag straight to the Deployment. We’ll update our manifest file’s Nginx to utilize 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
—————————————————————————————————————-
The name of the Deployment is my-deployment, and the name of the container is my-deployment-container, as defined in the YAML file. Examine the description once more and compare it to the original setup.
—————————————————————————————————————-
$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-97cfc859f to 3 |
—————————————————————————————————————-
We adjusted the image version from Nginx to nginx:1.18.0 as indicated in the Pod template by comparing the description outputs of the original and modified versions. In addition, compared to before the update, there are more events outlining the rolling update’s internal procedures. The Deployment updated the Pods by generating and scaling a new ReplicaSet of three replicas and destroying the old one, as shown above. For more information, look at the ReplicaSet status.
—————————————————————————————————————
$kubectl get replicaset
NAME DESIRED CURRENT READY AGE
my-deployment-79f645dc59 3 3 3 76s
my-deployment-97cfc859f 0 0 0 4m53s
—————————————————————————————————————-
Method 2: Editing the manifest YAML file directly. Alternatively, you can execute the following command to modify the Deployment YAML file and update the current image version from nginx:1.18.0 to nginx:1.19.1, then save and quit the terminal:
—————————————————————————————————————-
$kubectl edit deployment.v1.apps/my-deployment
deployment.apps/my-deployment edited
—————————————————————————————————————-
We still have three deployments ready, as you can see from the Deployment Status page.
—————————————————————————————————————-
$kubectl get deployment my-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 3/3 3 3 29m
—————————————————————————————————————-
To see if the image has been updated, look at the Deployment’s description.
—————————————————————————————————————-
$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-97cfc859f to 3 |
Normal | ScalingReplicaSet | 2m39s | deployment-controller | Scaled down replica set my-deployment-97cfc859f to 0 |
Normal | ScalingReplicaSet | 2m31s | deployment-controller | Scaled up replica set my-deployment-97cfc859f to 3 |
—————————————————————————————————————-
Finally, we started a new Deployment and scaled it up to 3 replicas, while the old one was scaled down to 0. Check the state of the ReplicaSet:
—————————————————————————————————————-
$ 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: Using the kubectl delete command, delete the Deployment.