Introduction to ReplicaSets & Deployment

Kubernetes September 2, 2020

In this part of our series, we are focusing on ReplicaSets and Deployment. Just like the previous parts, there will be hands-on practice to allow you to get acquainted with the features and functionalities of ReplicaSets and Deployment. These functionalities include using ReplicaSet to scale applications up or down as well as using Deployment to create a Pod, upgrade or downgrade your application with zero downtime. These Kubernetes objects make Kubernetes application management easier.

ReplicaSets

A ReplicaSet is a process that runs multiple instances of a Pod and keeps the specified number of Pods constant. Its purpose is to maintain the specified number of Pod instances running in a cluster at any given time to prevent users from losing access to their application when a Pod fails or is inaccessible.

ReplicaSet helps bring up a new instance of a Pod when the existing one fails, scale it up when the running instances are not up to the specified number, and scale down or delete Pods if another instance with the same label is created. A ReplicaSet ensures that a specified number of Pod replicas are running continuously and helps with load-balancing in case of an increase in resource usage.

Creating a ReplicaSet

We will create an example ReplicaSet using the below configuration file, just like we created a Pod in part 3 of this series.

Before we begin, you should already have a running Kubernetes cluster and configured the kubectl command-line tool to communicate with the cluster. Otherwise, details on how you can get a cluster running using KubeOne can be found here.

Step 1:

Create a YAML file using vim on the command line:

$vim replicaset-app.yaml

Step 2:

Copy, paste, and save the configuration below into your YAML file. The indentation is crucial!

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-replicaset
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx

Step 3:

Create the ReplicaSets with this command:

$kubectl create -f replicaset-app.yaml

Step 4:

Once the ReplicatSet is running, you can check its status:

$kubectl get replicasets

NAME            	DESIRED    CURRENT    READY   	AGE
my-replicaset  	    2          2          2       17s

Name: This is the name of the ReplicaSet declared as the child of the metadata property
Desired: This is the replica number specified in the YAML manifest file
Current: This equates to the current state of the ReplicaSet; that two replicas are up
Ready: The two replicas specified are ready and in the running state
Age: How long the replicas have been in the running state

Step 5:

Next, you can check the status of the Pods running in the ReplicaSet:

$kubectl get pods

NAME                 	  READY         STATUS    RESTARTS     AGE
my-replicaset-ccjfj   	 1/1         Running     0          5m18s
my-replicaset-m4bb7      1/1         Running  	 0          5m18s

Scaling Your Application

An application can either be scaled up or down depending on the situation in two ways. Using the first method, you can edit the configuration file we created earlier in this exercise by changing the replicas property value to a higher number to scale up or a lower number to scale down.To scale up, edit the manifest file and change the replicas value from 2 to 5. Save and exit the vim terminal and then run the below command.

$kubectl replace -f replicaset-app.yaml
replicaset.apps/my-replicaset replaced

To get the status:

$kubectl get replicasets

NAME              DESIRED   CURRENT   READY   AGE
my-replicaset       5         5        5      12m

Next, you can check the status of the Pods running in the ReplicaSet:

$kubectl get pods

NAME                  	READY   STATUS    RESTARTS   AGE
my-replicaset-bq9wz     1/1     Running     0        15m
my-replicaset-c5h4x   	1/1     Running     0        3m43s
my-replicaset-hj59z     1/1     Running     0        3m43s
my-replicaset-hpvxr     1/1     Running     0        15m
my-replicaset-xgwfx     1/1     Running     0        3m43s

As seen in the ReplicaSet and Pod statuses, there are 5 Replicas running and ready for use, as well as 5 Pods.
To scale down, change the value of the replicas in the manifest file from 5 to 1, then run the command below again.

$kubectl replace -f replicaset-app.yaml
replicaset.apps/my-replicaset replaced

Check the status of the ReplicaSet:

$kubectl get replicaset

NAME            DESIRED   CURRENT   READY     AGE
my-replicaset     1         1         1       4m9s

Check the status of the Pod:

$Kubectl get pods

NAME                  	READY    STATUS     RESTARTS     AGE
my-replicaset-89dkw     1/1      Running       0         4m15s

You can see that the number of Replicas and the running instance of a Pod are the same as the number specified in the manifest file Replicas field.

An application can also be scaled up or down using the command line which is the second method.

$kubectl scale - -replicas=5 -f replicaset-app.yaml   ## Scale up
$kubectl scale - -replicas=1 -f replicaset-app.yaml  ## Scale down

Or

$kubectl scale - -replicas= 5 replicaset <replicaset name>   ## Scale up
$kubectl scale - -replicas= 1 replicaset <replicaset name>   ## Scale down

Deployment

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.

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:

Creating a Deployment

We will create an example Deployment that will roll out a ReplicaSet to bring up three instances of an nginx Pod.

You must have a running Kubernetes cluster with kubectl command-line tool configured and connected to it to follow this exercise. Check part 2 of this series for a guide on getting a running Kubernetes cluster using KubeOne.

Creating a Deployment is the same as creating a ReplicaSet, but Deployment is the kind property’s value, you will also add a strategy property and values to the manifest file.

Step 1:

Create a YAML manifest file named my-deployment.yaml using vim on the command line:

$vim my-deployment.yaml

Step 2:

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.

Step 3:

Run this command to create a Deployment:

$kubectl create -f my-deployment.yaml

Step 4:

Check the Deployment status to see if it has been created.

$kubectl get deployments

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 deployments once again. Once it is ready, the output will look like this.

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: 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: Shows the up-to-date number of replicas out of the desired number declared in the YAML file.
Available: Shows the number of replicas that are available for use
Age: Shows the duration the application has been running

Step 5:

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

The functionality of a ReplicaSet in a Deployment, to keep the desired number of Pods running, can be confirmed by deleting a Pod.

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, a new Pod is running while the old one is already terminated. The ReplicaSet ensures that three instances of the Pod, in this case, are continually running on the cluster. The number of running instances depends on the ReplicaSet value declared in the configuration 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

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 Deployment

You can edit a Deployment by changing the container image from one version to the other. For example, the container image nginx we have been using in our exercises has many versions. When the version is not specified in the manifest YAML file, the latest version will be pulled from the image repository. 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

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.

$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: 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 by changing the current image version from nginx:1.18.0 to nginx:1.19.1 by running the below command then saving and exiting the terminal:

$kubectl edit deployment my-deployment

Check the status of the Deployment to see that we still have 3 deployments ready.

$kubectl get deployments

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 deployments 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 replicasets

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

ReplicaSets and Deployments

This guide has introduced you to how ReplicaSets and Deployments can automate application lifecycle management. The exercises and concepts we walked through demonstrate how using 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. It also allows the rolling back to the previous version in case the upgraded version is not stable, has errors or bugs.
Next in our series, we will look at Deployment strategies, types, and its functionalities. We encourage you to contact us with any questions you have.

https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-update-deployment

Seyi Ewegbemi

Seyi Ewegbemi

Student Worker