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
kubectlverbonden met een Kubernetes 1.28+ cluster- metrics-server geinstalleerd en werkend (
kubectl top podstoont waarden, geenerror: 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
InPlacePodVerticalScalingfeature 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=2van de Updater betekent dat een Deployment metreplicas: 1nooit ge-evict wordt inRecreate-modus. GebruikInPlaceOrRecreateop 1.33+ clusters, zet--min-replicas=1op 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
maxAllowedin 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
resourcesstanzas 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>outputkubectl logs -n kube-system deploy/vpa-recommender --tail=50kubectl logs -n kube-system deploy/vpa-admission-controller --tail=50kubectl get mutatingwebhookconfiguration | grep vpaoutput- Kubernetes-versie (
kubectl version --short) - VPA-versie (
kubectl get deploy vpa-recommender -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}')