Kubernetes Autoscaling
Vertical Pod Autoscaler VPA
VPA CPU Memory in Action Demo
In this hands-on guide, you’ll learn how to configure Kubernetes’ Vertical Pod Autoscaler (VPA) for both CPU and memory. We’ll cover:
- Deploying a sample Flask application
- Applying a VPA manifest with updates disabled
- Generating load and inspecting VPA Updater logs (no evictions yet)
- Enabling automatic updates and observing pod evictions and resource adjustments
Prerequisites
Ensure you have a running Kubernetes cluster (v1.15+) with the VPA Admission Controller and Updater components installed.
1. Deploy the Sample Application
Apply the Deployment and Service for our Flask app:
kubectl apply -f /root/vpa-cpu-app.yml
# deployment.apps/flask-app created
# service/flask-app-service created
Verify the pods and service are running:
kubectl get pods,svc | grep flask-app
2. Review and Apply the VPA Configuration
Inspect the VPA manifest below. The updateMode is set to Off, so no live adjustments will occur:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: flask-app
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: flask-app
updatePolicy:
updateMode: "Off"
evictionRequirements:
- resources: ["cpu", "memory"]
changeRequirement: TargetHigherThanRequests
resourcePolicy:
containerPolicies:
- containerName: "*"
minAllowed:
cpu: 100m
memory: 100Mi
maxAllowed:
cpu: 800m
memory: 500Mi
controlledResources: ["cpu", "memory"]
Apply the VPA object:
kubectl apply -f /root/vpa-cpu-vpa.yml
# verticalpodautoscaler.autoscaling.k8s.io/flask-app created
Describe the Initial Recommendation
With no traffic and updateMode: Off, the VPA will only show its configured bounds:
kubectl describe vpa flask-app
# Recommendation:
# Container Name: flask-app
# Lower Bound: Cpu: 100m
# Target: Cpu: 100m
# Uncapped Target: Cpu: 25m
# Upper Bound: Cpu: 800m
3. Generate Load Without Evictions
Start a load test to drive up CPU usage:
sh load.sh
# Hello, World!Hello, World!Hello, World!...
Now tail the VPA Updater logs in the kube-system namespace. Since updates are disabled, you’ll see skip messages:
kubectl logs -f deployment/vpa-updater -n kube-system
# I0104 12:28:33.901166 updater.go:150] skipping VPA object default/flask-app because its mode is not "Recreate" or "Auto"
# W0104 12:28:33.901197 updater.go:166] no VPA objects to process
Understanding VPA Logs
The Updater only evicts pods when the VPA’s updateMode is set to Auto or Recreate.
4. Enable Automatic Updates
Switch the VPA into Auto mode so it can evict and restart pods with new resource requests:
kubectl edit vpa flask-app
# Change updatePolicy.updateMode from "Off" to "Auto"
Confirm the change:
kubectl get vpa flask-app -o=jsonpath='{.spec.updatePolicy.updateMode}'
# Auto
| updateMode | Description | Pod Behavior |
|---|---|---|
| Off | Live updates disabled | No pod evictions |
| Auto | Automatic updates | Pods evicted & restarted with new requests |
5. Observe Pod Evictions & Resource Adjustments
With load still running, watch the Updater logs:
kubectl logs -f deployment/vpa-updater -n kube-system
# I0104 12:39:33.906873 update_priority_calculator.go:146] pod accepted for update default/flask-app-67b666c5fc-k9rtg with priority 586 - processed recommendations: flask-app: target: 587m; uncappedTarget: 587m;
# I0104 12:39:33.906962 updater.go:228] evicting pod default/flask-app-67b666c5fc-k9rtg
# I0104 12:39:33.919716 event.go:298] Event(...): type: 'Normal' reason: 'EvictedByVPA' Pod was evicted by VPA Updater to apply resource recommendation.
Check the updated pods and their ages:
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# flask-app-67b666c5fc-41b5s 1/1 Running 0 43s
# flask-app-67b666c5fc-96jfj 1/1 Running 0 103s
You should now see new pods running with the VPA-recommended CPU and memory requests. This completes the VPA demo.
Links and References
Further Reading
Watch Video
Watch video content
Practice Lab
Practice lab