Kubernetes Vertical Pod Autoscaler (VPA): resource requests goed dimensioneren

De Vertical Pod Autoscaler bekijkt het werkelijke CPU- en geheugengebruik per container en past resource requests daarop aan. In Off-modus krijg je right-sizing aanbevelingen zonder dat er iets aan draaiende pods verandert. In enforcement-modus past VPA die aanbevelingen automatisch toe, door pods te herstarten of (vanaf Kubernetes 1.33) in-place te resizen. Deze guide loopt door het installeren van VPA, het lezen van aanbevelingen, het begrenzen ervan met resource policies, het veilig opschalen naar auto-apply, en het vermijden van conflicten met HPA.

Wat je hebt aan het einde

Een VPA-object dat right-sizing aanbevelingen produceert voor de containers van een Deployment. Je weet hoe je die aanbevelingen leest, begrenst met minAllowed/maxAllowed, en veilig opschaalt van recommendation-only naar automatische enforcement. Je begrijpt ook de VPA + HPA spelregels zodat de twee autoscalers niet met elkaar in de clinch gaan.

Vereisten

  • kubectl verbonden met een Kubernetes 1.28+ cluster
  • metrics-server geinstalleerd en werkend (kubectl top pods toont waarden, geen error: Metrics API not available)
  • Een Deployment met resource requests gedefinieerd. VPA leest de huidige requests om het verschil te berekenen tussen wat er is gealloceerd en wat er daadwerkelijk wordt verbruikt
  • Voor in-place resize (stap 5): Kubernetes 1.33+ met de InPlacePodVerticalScaling feature gate ingeschakeld (standaard ingeschakeld sinds 1.33)

Stap 1: VPA installeren

VPA zit niet in core Kubernetes. Het wordt geleverd als CRD plus drie controllers in de kubernetes/autoscaler monorepo. Je hebt alle drie de componenten nodig:

  • Recommender: bevraagt metrics-server, bouwt per-container gebruikshistogrammen, schrijft aanbevelingen naar .status.recommendation
  • Updater: vergelijkt draaiende pods met de aanbeveling en evict of resize ze wanneer het verschil groot genoeg is
  • Admission controller: mutating webhook die aanbevolen resources injecteert in nieuw aangemaakte pods

Optie A: officieel installatiescript

git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
./hack/vpa-up.sh   # deployt CRD + alle drie controllers naar kube-system

Optie B: Helm (Fairwinds chart)

helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install vpa fairwinds-stable/vpa \
  --namespace vpa --create-namespace

Installatie verifieren

kubectl get pods -n kube-system -l app=vpa   # officieel script
kubectl get pods -n vpa                       # Helm

Verwachte output: drie draaiende pods (recommender, updater, admission-controller). Staat een pod in CrashLoopBackOff, controleer dan of metrics-server bereikbaar is.

Stap 2: VPA aanmaken in Off-modus

Begin in Off-modus. Dit is de standaard updateMode en het enige veilige startpunt. VPA genereert aanbevelingen maar raakt niets aan.

# vpa-off.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-app-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  updatePolicy:
    updateMode: "Off"
kubectl apply -f vpa-off.yaml

De recommender heeft echt verkeer nodig voordat de output bruikbaar is. Het algoritme gebruikt gewogen histogrammen met decay over een venster van 8 dagen. Na 24 uur zitten er nog veiligheidsmultiplicatoren van grofweg 2x in; na 7 dagen daalt dat naar zo'n 1.14x. Heb je workloads met wekelijkse pieken, wacht dan een volle week voordat je op de aanbevelingen afgaat.

Stap 3: aanbevelingen lezen en interpreteren

Na minimaal 24-48 uur dataverzameling:

kubectl describe vpa web-app-vpa -n production

De sectie status.recommendation.containerRecommendations toont drie niveaus per container:

containerRecommendations:
- containerName: web-app
  lowerBound:       # 50e percentiel, minimaal levensvatbaar
    cpu: 50m
    memory: 128Mi
  target:           # 90e percentiel, wat VPA toepast in enforcement-modus
    cpu: 200m
    memory: 300Mi
  upperBound:       # 95e percentiel, veiligheidsplafond
    cpu: 400m
    memory: 500Mi

target is de waarde die VPA toepast zodra je naar een enforcement-modus overschakelt. Vergelijk het met je huidige requests: staat er cpu: 1000m in je Deployment-spec en adviseert VPA cpu: 200m, dan ben je 5x over-provisioned. Adviseert VPA juist meer dan je alloceert, dan worden je pods waarschijnlijk CPU-gethrottled of OOMKilled.

Voor gestructureerde output kun je door jq pipen:

kubectl get vpa web-app-vpa -n production \
  -o jsonpath='{.status.recommendation.containerRecommendations}' | jq .

Stap 4: resource policy-grenzen instellen

Onbegrensde aanbevelingen kunnen de nodecapaciteit overschrijden en pods in Pending achterlaten. De resourcePolicy sectie beperkt wat VPA mag aanbevelen of toepassen.

# vpa-bounded.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: web-app-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  updatePolicy:
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
    - containerName: web-app
      minAllowed:
        cpu: 100m
        memory: 128Mi
      maxAllowed:
        cpu: "2"          # nooit meer dan 2 cores aanbevelen
        memory: 4Gi       # nooit meer dan 4 Gi aanbevelen
      controlledValues: RequestsAndLimits  # past beide aan, behoudt de ratio
    - containerName: istio-proxy
      mode: "Off"         # sluit sidecar uit van VPA-beheer

Twee opties voor controlledValues:

  • RequestsAndLimits (standaard): VPA past zowel requests als limits aan en behoudt de oorspronkelijke ratio. Heeft je Deployment een 1:2 request-to-limit ratio, dan houdt VPA die aan.
  • RequestsOnly: VPA past alleen requests aan; limits blijven wat je Deployment-spec zegt. Veiliger als je limits als een harde vangrail behandelt.

Stap 5: overschakelen naar een enforcement-modus

Zodra aanbevelingen stabiel zijn (7+ dagen data, target-waarden zien er redelijk uit, grenzen staan ingesteld), kies je een enforcement-modus.

Initial

VPA past aanbevelingen alleen toe bij het aanmaken van pods. Draaiende pods worden nooit ge-evict. Goed voor StatefulSets of workloads waar restarts midden in een operatie niet acceptabel zijn.

updatePolicy:
  updateMode: "Initial"

Recreate

De VPA Updater evict pods waarvan de requests flink afwijken van de aanbeveling. De workload controller maakt ze opnieuw aan en de admission webhook injecteert de bijgewerkte resources. Veroorzaakt een korte restart per pod. De Updater respecteert PodDisruptionBudgets en heeft een standaard --min-replicas=2: de laatste draaiende pod van een Deployment wordt niet ge-evict.

updatePolicy:
  updateMode: "Recreate"

InPlaceOrRecreate (Kubernetes 1.33+)

De Updater probeert eerst een in-place resize via de resize subresource van de pod. Geen restart, geen rescheduling. Als in-place resize mislukt (node heeft niet genoeg ruimte, memory limit decrease op een pre-1.35 cluster), valt het terug op eviction.

Op VPA 1.3.x moet je --feature-gates=InPlaceOrRecreate=true meegeven aan zowel de Updater als de admission controller. In VPA 1.4.0+ is die gate niet meer nodig.

updatePolicy:
  updateMode: "InPlaceOrRecreate"

In-place resize bereikte GA/stable in Kubernetes 1.35. Memory limit decreases worden wel ondersteund op 1.35+, maar de OOM-preventiecontrole van de Kubelet bij decreases is best-effort.

Gebruik geen Auto

Sinds VPA 1.4.0 is Auto deprecated. Het gedraagt zich momenteel identiek aan Recreate. Gebruik Recreate of InPlaceOrRecreate expliciet.

Controleer of enforcement werkt

Na het overschakelen naar een niet-Off modus, controleer of de admission webhook geregistreerd is:

kubectl get mutatingwebhookconfiguration | grep vpa

Ontbreekt de webhook, dan evict en herstelt VPA pods zonder de resources aan te passen. De pods starten opnieuw op, maar voor niets.

VPA + HPA: de feedback loop vermijden

VPA en HPA draaien op dezelfde resource metric leidt tot een destructieve feedback loop. VPA verlaagt de CPU-request van een pod op basis van per-container histogrammen. HPA's percentagegebaseerde utilization-berekening verschuift (zelfde absolute CPU / lagere request = hoger percentage). HPA schaalt meer replicas bij. VPA ziet lager per-pod gebruik en adviseert nóg lagere requests. De officiele VPA-documentatie waarschuwt hier expliciet voor.

Het veilige patroon scheidt de dimensies:

# VPA: alleen geheugen beheren
resourcePolicy:
  containerPolicies:
  - containerName: web-app
    controlledResources: ["memory"]
    controlledValues: RequestsOnly
    minAllowed:
      memory: 256Mi
    maxAllowed:
      memory: 8Gi

HPA blijft replicacount beheren op basis van CPU (of custom metrics zoals request rate). VPA regelt de geheugendimensionering. Geen overlap, geen oscillatie.

Goldilocks: een dashboard voor recommendation-only workflows

Fairwinds Goldilocks installeert alleen de VPA Recommender (geen Updater, geen admission controller) en voegt een webdashboard toe. Het maakt VPA-objecten aan in Off-modus voor elke Deployment in gelabelde namespaces en toont de aanbevelingen met kopieerbare resources: YAML.

helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install goldilocks fairwinds-stable/goldilocks \
  -n goldilocks --create-namespace
kubectl label namespace production goldilocks.fairwinds.com/enabled=true
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80

Goldilocks past goed als je clusterbreed inzicht wilt in right-sizing zonder enig enforcement-risico. Voor de volledige werkwijze om rightsizing-aanbevelingen om te zetten in clusterbesparingen — inclusief namespace-quota's, LimitRange-standaarden en spot-instance-integratie — zie de Kubernetes kostenoptimalisatiegids.

Bekende beperkingen

  • Single-replica Deployments: de standaard --min-replicas=2 van de Updater betekent dat een Deployment met replicas: 1 nooit ge-evict wordt in Recreate-modus. Gebruik InPlaceOrRecreate op 1.33+ clusters, zet --min-replicas=1 op de Updater (accepteert downtimerisico), of verhoog replicas naar 2.
  • Een VPA per workload: meerdere VPA-objecten die dezelfde pod targeten produceren ongedefinieerd gedrag. Gebruik een VPA per Deployment.
  • Aanbevelingen kunnen nodegrootte overschrijden: VPA adviseert op basis van geobserveerd gebruik, niet op basis van nodecapaciteit. Combineer met Cluster Autoscaler of Karpenter, of stel maxAllowed in zodat aanbevelingen onder de allocatable resources van je grootste node blijven.
  • Reactief, niet voorspellend: VPA heeft een vertraging van 60-90 seconden door de metrics-pipeline en geen seizoensbewustzijn. Het kan zich niet voorbereiden op een voorspelbare dagelijkse verkeersspiek.
  • Geen pod-level resources ondersteuning: VPA werkt niet met workloads die pod-level resources stanzas defieren (een nieuwere Kubernetes-feature).

Eindresultaat verifieren

Na het afronden van de setup, bevestig dat alles end-to-end werkt:

# 1. VPA-object bestaat en heeft een aanbeveling
kubectl get vpa web-app-vpa -n production -o wide

# 2. Aanbevelingen zijn gevuld (niet leeg)
kubectl describe vpa web-app-vpa -n production | grep -A 10 "Container Recommendations"

# 3. Bij enforcement-modus: controleer dat pods VPA-toegepaste resources hebben
kubectl get pods -n production -l app=web-app -o jsonpath='{.items[0].spec.containers[0].resources}'

Is Container Recommendations leeg, dan heeft de recommender nog niet genoeg data verzameld. Wacht 24-48 uur voordat je verder evalueert.

Wanneer escaleren

Als VPA geen aanbevelingen produceert, of pods worden ge-evict maar resources veranderen niet, verzamel dan het volgende voordat je om hulp vraagt:

  • kubectl describe vpa <naam> -n <namespace> output
  • kubectl logs -n kube-system deploy/vpa-recommender --tail=50
  • kubectl logs -n kube-system deploy/vpa-admission-controller --tail=50
  • kubectl get mutatingwebhookconfiguration | grep vpa output
  • Kubernetes-versie (kubectl version --short)
  • VPA-versie (kubectl get deploy vpa-recommender -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}')

Terugkerende server- of deploymentproblemen?

Ik help teams productie betrouwbaar maken met CI/CD, Kubernetes en cloud—zodat fixes blijven en deploys geen stress meer zijn.

Bekijk DevOps consultancy

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.