Skip to content

Vertical Pod Autoscaler (VPA) Demo

Now that you have an understanding of how VPA works, let's see it in action.

Docker Images

Here is the Docker Image used in this tutorial: reyanshkharga/nodeapp:v1


reyanshkharga/nodeapp:v1 runs on port 5000 and has the following routes:

  • GET / Returns host info and app version
  • GET /health Returns health status of the app
  • GET /random Returns a randomly generated number between 1 and 10


We'll follow these steps to test the Vertical Pod Autoscaler (VPA):

  1. We'll create a Deployment and a Service object.
  2. We'll create a VerticalPodAutoscaler object for the deployment.
  3. We'll generate load on pods managed by the deployment.
  4. We'll observe VPA taking autoscaling actions to meet the increased demand.

Let's see this in action!

Step 1: Create a Deployment

First, let's create a deployment as follows:

apiVersion: apps/v1
kind: Deployment
  name: my-deployment
  replicas: 2
      app: demo
        app: demo
      - name: nodeapp
        image: reyanshkharga/nodeapp:v1
        imagePullPolicy: Always
          - containerPort: 5000
            cpu: "10m"
            memory: "10Mi"

Apply the manifest to create the deployment:

kubectl apply -f my-deployment.yml

Verify deployment and pods:

# List deployments
kubectl get deployments

# List pods
kubectl get pods

Note that each pod can requests a minimum of 10m CPU and 10Mi memory.

Step 2: Create a Service

Next, let's create a LoadBalancer service as follows:

apiVersion: v1
kind: Service
  name: my-service
  type: LoadBalancer
    app: demo
    - port: 80
      targetPort: 5000

Apply the manifest to create the service:

kubectl apply -f my-service.yml

Verify service:

kubectl get svc

Step 3: Create VPA for the Deployment

Now, let's create a VPA for the deployment as follows:

apiVersion: ""
kind: VerticalPodAutoscaler
  name: my-vpa
    apiVersion: "apps/v1"
    kind: Deployment
    name: my-deployment
    updateMode: "Auto"
    minReplicas: 2 # Minimal number of replicas which need to be alive for Updater to attempt Pod eviction
      - containerName: '*' # The name of the container that the policy applies to.
          cpu: 10m
          memory: 10Mi
          cpu: 500m
          memory: 500Mi
        controlledResources: ["cpu", "memory"]

The minAllowed field prevents the VPA from recommending or setting resource requests below the specified minimum threshold, ensuring requests won't drop below that limit.

The maxAllowed field prevents the VPA from recommending or setting resource requests above the specified maximum threshold, ensuring requests won't exceed that limit.

Apply the manifest to create the VPA:

kubectl apply -f my-vpa.yml

Verify VPA:

# List vpa
kubectl get vpa

# Describe vpa to view the events
kubectl descripe vpa my-vpa


The .spec.replicas value in deployment must be greater than or equal to .spec.updatePolicy.minReplicas value in VPA for the VPA to manage the pods for autoscaling.

Step 4: Generate Load

Let's generate load on the pods managed by the deployment. On your local machine run the following command to generate the load:

while sleep 1; do seq 1000 | xargs -P100 -I{} curl -s <load-balancer-dns> > /dev/null; done

The above command concurrently sends 1000 requests per second to the LoadBalancer service using 100 parallel processes.

Step 5: Monitor Pods and VPA Events

# List pods in watch mode
kubectl get pods -w

# List vpa in watch mode
kubectl get vpa -w

# View vpa events
kubectl describe vpa my-vpa

You'll notice that vpa recommender recommends a new value for resource requests and then vpa updater updates the resource requests of pods.


The updater may take some time to apply the recommendation and you might have to wait before you can see the updated resource requests in pods.

You can view the VPA logs as follows:

# view logs from admission controller
kubectl get pods -n kube-system | grep vpa-admission | kubectl logs -f `awk '{print $1}'` -n kube-system

# view logs from recommender
kubectl get pods -n kube-system | grep vpa-recommender | kubectl logs -f `awk '{print $1}'` -n kube-system

# view logs from updater
kubectl get pods -n kube-system | grep vpa-updater | kubectl logs -f `awk '{print $1}'` -n kube-system

Clean Up

Assuming your folder structure looks like the one below:

|-- manifests
│   |-- my-deployment.yml
│   |-- my-service.yml
│   |-- my-vpa.yml

Let's delete all the resources we created:

kubectl delete -f manifests/