Skip to main content
RunBook Academy

KubernetesLXXXIII · Vertical Pod Autoscaling ConceptsVertical Pod Autoscaler

VPA limitations — the boundaries of vertical scaling

Advanced⏱ ~12 minkubectlvpa

What you'll learn

  • Identify the VPA limitations
  • Plan around the pod restart requirement
  • Configure the VPA for production
  • Recognize the VPA's boundary cases

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

The VPA has a set of limitations that production operators must plan around. The pod restart requirement, the interaction with HPA, the resource limits, and the storage of usage history are the boundary cases. This lesson walks the limitations and the production patterns that work around them.

The pod restart requirement

The VPA’s eviction-then-recreate pattern requires a pod restart:

flowchart LR
    A[Pod with old requests] --> B[VPA updater evicts]
    B --> C[New pod created]
    C --> D[Pod with new requests]

The pod restart is required because the resource requests of a running pod cannot be changed. The pod must be evicted and recreated.

The impact on stateful workloads

The pod restart is a problem for stateful workloads:

Postgres pod evicted by VPA
Postgres pod restarted
Database connection pool reset
Application reconnect

The restart is disruptive. The mitigation is to use VPA in Off mode or to use the Initial mode:

updatePolicy:
  updateMode: "Initial"

The Initial mode sets the requests on pod creation only; no eviction is required.

The HPA conflict

The VPA and HPA conflict on the same metric:

# VPA on CPU
controlledResources: ["cpu"]

# HPA on CPU
metrics:
- type: Resource
  resource:
    name: cpu

The two autoscalers fight each other. The VPA changes the request, which changes the CPU utilization, which triggers the HPA, which may trigger the VPA again.

The mitigation is to use different metrics or to use either VPA or HPA, not both.

The resource limits

The VPA’s recommendations are bounded by minAllowed and maxAllowed. The bounds are the container’s resource limits:

resourcePolicy:
  containerPolicies:
  - containerName: nginx
    minAllowed:
      cpu: 100m
      memory: 128Mi
    maxAllowed:
      cpu: 2
      memory: 4Gi

The VPA cannot recommend a request outside the bounds.

flowchart LR
    A[Recommendation] --> B{Bounds?}
    B -->|Inside| C[Recommended]
    B -->|Outside| D[Bound to min/max]

The history storage

The VPA’s recommendation is based on historical data. The recommender stores the historical data in memory:

The recommender stores:
  - 8 days of CPU usage samples
  - 8 days of memory usage samples
  - Per-pod, per-container

The memory storage is per-pod; the recommender needs sufficient memory to store the history.

The recommender uses the metrics server as the source:

spec:
  resourcePolicy:
    containerPolicies:
    - containerName: nginx
      historicalDataWindow: 8d

The history window is configurable.

The cold-start

The VPA’s recommendation is cold-start:

Pod 1 day old: insufficient data; recommendation is at minAllowed
Pod 8 days old: full data; recommendation is at the 90th percentile

The cold-start is the first 8 days. The recommendation is conservative; the VPA trusts the existing requests until the history is sufficient.

The non-CPU-bound workloads

The VPA is most effective for CPU-bound workloads. For memory-bound workloads, the VPA may not be as effective:

CPU-bound: VPA recommends higher CPU; the workload benefits
Memory-bound: VPA recommends higher memory; the workload benefits
I/O-bound: VPA's recommendations are less relevant; the bottleneck is not CPU/memory

The VPA is for CPU and memory; for I/O-bound workloads, the bottleneck is elsewhere.

The update mode boundaries

The three update modes have different boundaries:

  • Off: recommendations only; no pod updates.
  • Initial: sets on pod creation; running pods are not updated.
  • Auto: evicts and recreates pods.

The choice depends on the workload:

WorkloadRecommended mode
StatefulOff or Initial
StatelessAuto
CriticalOff or Initial

The storage of recommendations

The VPA’s recommendations are stored in the VPA object’s status:

kubectl describe vpa nginx-vpa
Status:
  Recommendation:
    Container Recommendations:
      Container Name:  nginx
      Target:
        Cpu:     100m
        Memory:  200Mi

The recommendations are readable via the VPA API.

The cross-course references

  • The HPA course (Part LXXXII) covers the horizontal alternative.
  • The Capacity Planning course (Part LXXXIV) covers the resource planning.
  • The Observability course covers VPA monitoring.

Quiz

Knowledge check · 4 questions

  1. Q1. What is the main VPA limitation for stateful workloads?

  2. Q2. The VPA's `Initial` mode sets the requests on pod creation only and does not update running pods.

  3. Q3. Walk the VPA configuration for a stateful workload that cannot tolerate pod restarts.

    Postgres StatefulSet with 3 replicas. The team is configuring the VPA but the workload cannot tolerate pod restarts. The VPA recommendations are needed for right-sizing.

  4. Q4. What is the VPA cold-start, and how is it handled?

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Choose the updateMode per workload. Off, Initial, or Auto.
  • Plan for pod restarts. Stateful workloads need careful planning.
  • Use different metrics for VPA and HPA. Avoid mixing on the same metric.
  • Set minAllowed and maxAllowed. Bound the recommendations.
  • Allow 8 days for history. The cold-start is the first 8 days.
  • Document the VPA configuration. The mode, the bounds, the rationale.

The VPA limitations are the boundary cases. Operating it well is choosing the right update mode, bounding the recommendations, and planning for the pod restarts.