1. Overview

Container orchestration technologies such as Kubernetes have been widely adopted. One of the primary reasons for its popularity is it allows us to deploy and manage containerized applications at scale.

It’s very common to see that applications get overloaded during peak hours. One of the easiest ways to handle such scenarios is to deploy the additional instances of the applications. The good news is that we can do it very quickly and effortlessly in Kubernetes.

In this tutorial, we’ll discuss various techniques for scaling pods in Kubernetes. So, let’s get started.

2. Setting up an Example

It’s good practice to follow a resource isolation strategy while deploying the application. In Kubernetes, we can achieve it using the namespaces.

In this section, we’ll discuss how to create a new namespace and deploy a few pods to it.

2.1. Creating a New Kubernetes Namespace

First, let’s use the create command to create a new namespace:

$ kubectl create ns scaling-demo
namespace/scaling-demo created

Here, we can see that the command creates a new namespace with the name scaling-demo.

In the next sections, we’ll create a declarative YAML configuration to deploy NGINX and Redis pods in this namespace.

2.2. Creating Kubernetes Deployment Objects

To begin, let’s save the following declarative configuration as nginx.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: scaling-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine-slim
        name: nginx
        ports:
        - containerPort: 80
          name: nginx

Similarly, we can save the following configuration in a redis.yaml file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: scaling-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - image: redis:alpine
        name: redis
        ports:
        - containerPort: 6379
          name: redis

2.3. Creating Kubernetes Pods

Next, let’s use the apply command to create the NGINX and Redis pods in the scaling-demo namespace:

$ kubectl apply -f nginx.yaml
deployment.apps/nginx configured

$ kubectl apply -f redis.yaml
deployment.apps/redis configured

Finally, let’s check that all pods are in a healthy state:

$ kubectl get pods --show-labels -n scaling-demo
NAME                     READY   STATUS    RESTARTS   AGE   LABELS
nginx-59c556767c-ncl9k   1/1     Running   0          45s   app=nginx,pod-template-hash=59c556767c
redis-78497c75bd-9jxdw   1/1     Running   0          36s   app=redis,pod-template-hash=78497c75bd

In this example, we’ve used the –show-labels option with the get command to display the labels of the pod.

Now, the required setup is in place. So let’s use it to understand the scaling in Kubernetes.

3. Scaling Pods Using the Declarative Method

In this section, we’ll discuss the two declarative methods to scale up/down the Kubernetes pods. As the name suggests, this method needs a declarative configuration. In our case, we’ve defined it in the YAML files while setting up the example.

3.1. Using the apply Command

In the YAML file, we’ve set the value of spec.replicas to 1. This property controls the number of pods to be created. One of the easiest and most preferred methods for scaling is to update this value.

So, let’s edit the nginx.yaml file and set the value of the spec.replicas to 2. When we’ve saved it:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: scaling-demo
spec:
  replicas: 2            # We've updated this value
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine-slim
        name: nginx
        ports:
        - containerPort: 80
          name: nginx

Now, let’s use the apply command to deploy the updated configuration:

$ kubectl apply -f nginx.yaml 
deployment.apps/nginx configured

Here, we can observe that the command successfully applies the updated configuration.

Now, let’s confirm that there are two pods of the NGNIX:

$ kubectl get pods --selector=app=nginx -n scaling-demo
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59c556767c-ncl9k   1/1     Running   0          85s
nginx-59c556767c-nd6rb   1/1     Running   0          7s

In this example, we’ve used the app=nginx label with the get command to filter only NGINX pods.

It’s important to note that, ideally, one should use this method only because we can version control the latest configuration and avoid configuration drifts.

3.2. Using the scale Command

In addition to this, we can also use the scale command to scale pods. The sole purpose of this command is to set a new size for a deployment, replica set, replication controller, or stateful set.

We’ve to use the –replicas option with this command to specify the new size. This option is mandatory as we aren’t updating the value of the spec.replicas property from the YAML file*.*

In the previous example, we scaled up the NGINX pods. Now, let’s scale them down by specifying the –replicas=1 option to the command:

$ kubectl scale --replicas=1 -f nginx.yaml 
deployment.apps/nginx scaled

Here, the output shows that the scaling operation was completed successfully.

Now let’s check the status of NGINX pods:

$ kubectl get pods --selector=app=nginx -n scaling-demo
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59c556767c-ncl9k   1/1     Running   0          108s

In the output, we can see that the scale command has removed the additional Pod.

4. Scaling Pods Using the Imperative Method

In the previous section, we saw how to scale pods using the declarative method. However, sometimes we want to perform scaling operations without declarative configuration. In such cases, we can use the deployment name with the scale command. In our case, the deployment names are nginx and redis.

4.1. Scaling up the Pod

Let’s use the –replicas=2 option to set the replica count of the NGINX deployment to 2:

$ kubectl scale --replicas=2 deployment/nginx -n scaling-demo
deployment.apps/nginx scaled

Now, let’s verify that there are two NGINX pods:

$ kubectl get pods --selector=app=nginx -n scaling-demo
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59c556767c-5vznb   1/1     Running   0          10s
nginx-59c556767c-ncl9k   1/1     Running   0          2m11s

Here, we can see that scale operation creates the new NGINX pod.

4.2. Scaling Down the Pod

Similarly, we can use the scale command to scale down the pod. To achieve this, we need to use the smaller value with the –replicas option than the current replica count.

So, let’s use the –replicas=1 option to scale down the NGINX pod to one:

$ kubectl scale --replicas=1 deployment/nginx -n scaling-demo
deployment.apps/nginx scaled

Next, let’s verify that the additional NGINX pod is getting removed:

$ kubectl get pods --selector=app=nginx -n scaling-demo
NAME                     READY   STATUS       RESTARTS   AGE
nginx-59c556767c-5vznb   1/1     Terminating  0          10s
nginx-59c556767c-ncl9k   1/1     Running      0          2m11s

Here, we can see that the status of one of the Pods is Terminating.

4.3. Scaling Pod Based on the Condition

In addition to this, the scale command allows us to perform scaling based on the conditions. This helps us in avoiding the unintentional overwrites of previous scaling changes.

To understand this, let’s specify the scaling condition using the –current-replicas option:

$ kubectl scale --current-replicas=1 --replicas=2 deployment/nginx -n scaling-demo
deployment.apps/nginx scaled

The above condition sets the replica count of NGINX deployment to 2 only if the current replica count is 1.

Now, let’s check the status of the NGINX pods:

$ kubectl get pods --selector=app=nginx -n scaling-demo
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59c556767c-ncl9k   1/1     Running   0          3m6s
nginx-59c556767c-xx5bb   1/1     Running   0          9s

It’s important to note that the scaling operation succeeds only if the specified condition evaluates to the boolean true.

To understand this, let’s execute the same scale command once again:

$ kubectl scale --current-replicas=1 --replicas=2 deployment/nginx -n scaling-demo
error: Expected replicas to be 1, was 2

Here, we can see that the command fails while performing the scaling operation.

4.4. Scaling Multiple Pods

So far, we scaled only a single pod. However, the scale command allows us to scale multiple pods as well. To achieve this, we just need to specify the multiple deployment object on the command line.

So, let’s scale up the NGINX and Redis pods using the single command:

$ kubectl scale --replicas=3 deployment/nginx deployment/redis -n scaling-demo
deployment.apps/nginx scaled
deployment.apps/redis scaled

In the output, we can see that the two deployments have been scaled. To verify that, let’s list the pods from the scaling-demo namespace:

$ kubectl get pods -n scaling-demo
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59c556767c-ncl9k   1/1     Running   0          16m
nginx-59c556767c-vn96s   1/1     Running   0          11s
nginx-59c556767c-xx5bb   1/1     Running   0          13m
redis-78497c75bd-6gs96   1/1     Running   0          11s
redis-78497c75bd-9jxdw   1/1     Running   0          16m
redis-78497c75bd-l25mf   1/1     Running   0          11s

4.5. Scaling All Pods

In the previous example, we scaled up two deployments using their names. However, that isn’t the most efficient method if we want to perform the scale operation on a large number of objects.

In such cases, we can use the –all option to perform the scale operation on all objects:

$ kubectl scale --replicas=1 --all deployment -n scaling-demo
deployment.apps/nginx scaled
deployment.apps/redis scaled

It’s important to note that we’ve to specify the resource type after the –all option. The supported resource types are deployment, rs, rc, or statefulset.

Now, let’s verify that both NGINX and Redis pods have been scaled down:

$ kubectl get pods -n scaling-demo 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59c556767c-ncl9k   1/1     Running   0          17m
redis-78497c75bd-9jxdw   1/1     Running   0          17m

5. Cleaning Up

Kubernetes objects consume various system resources, such as CPU, memory, storage, network, etc. So it’s a good practice to remove them if they aren’t needed anymore. Removing the incorrect Kubernetes object can cause potential issues. Hence, we’ve to be extra careful before deleting them.

So, let’s use the delete command to remove the Deployment and Namespace objects:

$ kubectl delete deployment/nginx deployment/redis -n scaling-demo
deployment.apps "nginx" deleted
deployment.apps "redis" deleted

$ kubectl delete namespace scaling-demo
namespace "scaling-demo" deleted

6. Conclusion

In this article, we saw how to scale up/down the Kubernetes pods.

First, we discussed how to use the apply and scale commands with the declarative configuration.

Next, we saw the usage of the scale command using the imperative method. Then we discussed how to perform the scaling based on the condition.

Finally, we discussed scaling multiple pods at once using a single command.