Setting up a Vertical Pod Autoscaler (VPA)

The following example demonstrates the deployment of an application based on a publicly available image. This example illustrates how the VPA responds to changes in the application state.

1) Provisioning a Cluster

First, you should provision a Kubernetes cluster.

2) Installing the VPA

Unlike the HPA, the VPA needs to be installed separately. This can be done using the repository https://github.com/kubernetes/autoscaler.

Cloning the Repository

$ git clone https://github.com/kubernetes/autoscaler.git

Changing to the Right Directory

$ cd autoscaler/vertical-pod-autoscaler/

Installing the VPA

$ ./hack/vpa-up.sh

Verifying the Installation

$ kubectl get pods -n kube-system
NAME                                        READY   STATUS    RESTARTS   AGE
...
metrics-server-7b236j497-bnw9s              1/1     Running   0          67d
vpa-admission-controller-3ns8d8777d-pps3w   1/1     Running   0          12s
vpa-recommender-6fcsnm26j5-s7lw0            1/1     Running   0          23s
vpa-updater-7sm51h55c-a9smw                 1/1     Running   0          23s
...

3) Deploying the Application

Rolling out the Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vpa-demo-deployment
spec:
  selector:
    matchLabels:
      run: vpa-demo-deployment
  replicas: 1
  template:
    metadata:
      labels:
        run: vpa-demo-deployment
    spec:
      containers:
      - name: vpa-demo-deployment
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
$ kubectl apply -f deployment.yaml
deployment.apps/vpa-demo-deployment created

$ kubectl -n default get pods
NAME                                  READY   STATUS    RESTARTS   AGE
vpa-demo-deployment-85bff8877-9z9p9   1/1     Running   0          3s

$ kubectl -n default get deployment
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
vpa-demo-deployment   1/1     1            1           6s

Creating a Service

apiVersion: v1
kind: Service
metadata:
  name: vpa-demo-deployment
  labels:
    run: vpa-demo-deployment
spec:
  ports:
  - port: 80
  selector:
    run: vpa-demo-deployment
$ kubectl apply -f service.yaml
service/vpa-demo-deployment created
$ kubectl -n default get services # Can also be abbreviated as 'svc'
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
vpa-demo-deployment   ClusterIP   10.122.166.51   <none>        80/TCP    5s
kubernetes            ClusterIP   10.112.0.1      <none>        443/TCP   13d

Configuring the VPA

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-deployment-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: vpa-demo-deployment
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        controlledResources:
          - cpu
          - memory
        maxAllowed:
          cpu: 1
          memory: 500Mi
        minAllowed:
          cpu: 100m
          memory: 50Mi
  updatePolicy:
    updateMode: "Auto"
$ kubectl apply -f vpa.yaml
verticalpodautoscaler.autoscaling.k8s.io/my-deployment-vpa created

3) Testing

Status before testing:

$ kubectl -n default get pods
NAME                                  READY   STATUS    RESTARTS   AGE
vpa-demo-deployment-85bff8877-9z9p9   1/1     Running   0          20m
$ kubectl -n default get verticalpodautoscaler # Can also be abbreviated as 'hpa'
NAME                  REFERENCE                        TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
vpa-demo-deployment   Deployment/vpa-demo-deployment   0%/50%    1         10        1          20m

Generating Load

The following command simulates load:

kubectl run -i --tty load-simulation --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://vpa-demo-deployment; done"

Behavior during Load

The behavior during the load is specific to the application and may vary.

4) Removing Load

To remove the load simulator, use the following command:

$ kubectl delete pod load-simulation
pod "load-simulation" deleted

Subsequently, the replicas will be removed as there is no longer any load.

5) Cleanup

The following commands remove the service, deployment, and VPA:

$ kubectl delete -f vpa.yaml
horizontalpodautoscaler.autoscaling "vpa-demo-deployment" deleted
 
$ kubectl delete -f deployment.yaml
deployment.apps "vpa-demo-deployment" deleted
 
$ kubectl delete -f service.yaml
service "vpa-demo-deployment" deleted