- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Vertical Pod Autoscaler (VPA): Ressourcen automatisch optimieren
TL;DR
- Der Vertical Pod Autoscaler analysiert die tatsaechliche CPU- und Memory-Nutzung und empfiehlt passende Resource Requests.
- Drei Update-Modi: Off (nur Empfehlungen), Initial (setzt Requests beim Pod-Start), Auto (evicted und recreated Pods mit neuen Werten).
- VPA und HPA duerfen nicht gleichzeitig auf CPU oder Memory skalieren -- das fuehrt zu Konflikten. HPA auf Custom Metrics + VPA auf CPU/Memory ist dagegen problemlos.
- Starten Sie immer im Modus
Off, um die Empfehlungen zu pruefen, bevor SieAutoaktivieren. - Goldilocks visualisiert VPA-Empfehlungen fuer alle Workloads im Cluster und zeigt Einsparpotenziale.
Das Problem: Falsche Resource Requests
In den meisten Kubernetes-Clustern sind Resource Requests falsch konfiguriert. Entwickler setzen konservative Werte ("lieber zu viel als zu wenig"), und danach fasst niemand die Werte mehr an.
Das Ergebnis:
# Typischer Cluster: Requests vs. tatsaechliche Nutzung
kubectl top pods -n production
NAME CPU(cores) MEMORY(bytes)
order-service-abc123 45m 180Mi
order-service-def456 52m 175Mi
payment-service-ghi789 12m 95Mi
# Die Requests sind aber:
kubectl get pods -n production -o custom-columns=\
NAME:.metadata.name,\
CPU_REQ:.spec.containers[0].resources.requests.cpu,\
MEM_REQ:.spec.containers[0].resources.requests.memory
NAME CPU_REQ MEM_REQ
order-service-abc123 500m 1Gi
order-service-def456 500m 1Gi
payment-service-ghi789 500m 512Mi
Der order-service nutzt 10% der angeforderten CPU und 18% des angeforderten Memory. Diese Ueberprovisionierung kostet Geld -- Nodes laufen halbvoll, aber der Scheduler denkt, sie waeren ausgelastet.
Der Vertical Pod Autoscaler loest genau dieses Problem.
VPA Architektur: Drei Komponenten
Der VPA besteht aus drei Komponenten, die zusammenarbeiten:
1. Recommender
Beobachtet die historische und aktuelle Ressourcennutzung ueber den Metrics Server. Berechnet daraus Empfehlungen fuer Resource Requests mit Sicherheitspuffer.
2. Updater
Ueberwacht laufende Pods. Wenn die aktuellen Requests stark von den Empfehlungen abweichen und der Update-Modus Auto ist, evicted der Updater den Pod. Der neue Pod wird dann mit den empfohlenen Werten erstellt.
3. Admission Controller
Fuer die Modi Initial und Auto: Wenn ein neuer Pod erstellt wird, modifiziert der Admission Controller die Resource Requests basierend auf der VPA-Empfehlung, bevor der Pod auf einem Node gescheduled wird.
Metrics Server */} Recommender */} Empfehlungen
|
v
Updater */} evicted Pods (bei Auto)
|
v
Admission Controller */} setzt neue Requests beim Pod-Start
Installation per Helm
Der VPA ist nicht standardmaessig in Kubernetes enthalten. Die Installation erfolgt per Helm:
# Voraussetzung: Metrics Server muss laufen
kubectl top nodes
# Wenn das funktioniert, ist der Metrics Server aktiv
# VPA ueber das offizielle Helm Chart installieren
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm install vpa fairwinds-stable/vpa \
--namespace vpa-system \
--create-namespace \
--set recommender.enabled=true \
--set updater.enabled=true \
--set admissionController.enabled=true
# Installation pruefen
kubectl get pods -n vpa-system
# Erwartete Ausgabe:
# vpa-admission-controller-xxx 1/1 Running
# vpa-recommender-xxx 1/1 Running
# vpa-updater-xxx 1/1 Running
Alternative Installation aus dem offiziellen Kubernetes Repository:
# Clone des autoscaler-Repos
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
# Installation mit dem mitgelieferten Skript
./hack/vpa-up.sh
# Deinstallation
# ./hack/vpa-down.sh
Die drei Update-Modi
Modus Off: Nur Empfehlungen (Einstieg)
Der sicherste Modus. VPA beobachtet und empfiehlt, aendert aber nichts. Ideal zum Kennenlernen und zur Analyse.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: order-service-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
updatePolicy:
updateMode: "Off"
resourcePolicy:
containerPolicies:
- containerName: order-service
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: 2000m
memory: 4Gi
controlledResources:
- cpu
- memory
# VPA anlegen
kubectl apply -f order-service-vpa.yaml
# Nach 5-10 Minuten: Empfehlungen abrufen
kubectl get vpa order-service-vpa -n production -o yaml
Die Empfehlungen finden Sie im Status-Feld:
status:
recommendation:
containerRecommendations:
- containerName: order-service
lowerBound:
cpu: 25m
memory: 131072k
target:
cpu: 60m
memory: 200Mi
uncappedTarget:
cpu: 60m
memory: 200Mi
upperBound:
cpu: 180m
memory: 400Mi
| Feld | Bedeutung |
|---|---|
lowerBound | Minimale Empfehlung (unter diesem Wert ist OOM/Throttling wahrscheinlich) |
target | Optimaler Wert (das sollten Ihre Requests sein) |
uncappedTarget | Target ohne min/max Constraints |
upperBound | Maximale Empfehlung (fuer Lastspitzen) |
Modus Initial: Requests beim Pod-Start setzen
Im Initial-Modus setzt der VPA Admission Controller die Resource Requests, wenn ein neuer Pod erstellt wird. Laufende Pods werden nicht angefasst.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: order-service-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
updatePolicy:
updateMode: "Initial"
resourcePolicy:
containerPolicies:
- containerName: order-service
minAllowed:
cpu: 50m
memory: 128Mi
maxAllowed:
cpu: 2000m
memory: 4Gi
Das ist nuetzlich fuer Workloads, die nicht einfach neu gestartet werden koennen. Beim naechsten Rollout oder Restart bekommen die Pods automatisch optimierte Requests.
# Pruefen ob die Requests beim naechsten Pod-Start gesetzt werden
kubectl rollout restart deployment/order-service -n production
# Danach: Requests des neuen Pods pruefen
kubectl get pod -n production -l app=order-service -o jsonpath=\
'{.items[0].spec.containers[0].resources.requests}'
Modus Auto: Vollautomatisch (mit Pod-Neustarts)
Im Auto-Modus evicted der VPA Updater laufende Pods, deren Requests stark von den Empfehlungen abweichen. Die Pods werden mit neuen Requests neu erstellt.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: order-service-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
updatePolicy:
updateMode: "Auto"
minReplicas: 2
resourcePolicy:
containerPolicies:
- containerName: order-service
minAllowed:
cpu: 50m
memory: 128Mi
maxAllowed:
cpu: 2000m
memory: 4Gi
controlledResources:
- cpu
- memory
Wichtig: minReplicas: 2 stellt sicher, dass der Updater nicht den letzten Pod evicted. Setzen Sie diesen Wert auf die minimale Anzahl an Pods, die fuer Ihre Verfuegbarkeit noetig ist.
# VPA-Events ueberwachen: Wann werden Pods evicted?
kubectl get events -n production --field-selector reason=EvictedByVPA
# Aktuelle VPA-Recommendations vs. tatsaechliche Requests vergleichen
kubectl get vpa -n production -o custom-columns=\
NAME:.metadata.name,\
TARGET_CPU:.status.recommendation.containerRecommendations[0].target.cpu,\
TARGET_MEM:.status.recommendation.containerRecommendations[0].target.memory
VPA fuer mehrere Container im Pod
Pods mit Sidecars (Envoy, Filebeat, etc.) koennen pro Container unterschiedliche Policies haben:
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: "Auto"
resourcePolicy:
containerPolicies:
# Hauptcontainer: VPA steuert CPU und Memory
- containerName: web-app
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 4000m
memory: 8Gi
# Sidecar: Nur Memory wird gesteuert, CPU bleibt fix
- containerName: envoy-sidecar
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: 200m
memory: 512Mi
controlledResources:
- memory
# Init-Container: VPA ignorieren
- containerName: init-migration
mode: "Off"
VPA und HPA: Die Abgrenzung
VPA und HPA gleichzeitig auf CPU oder Memory zu verwenden, fuehrt zu Konflikten. Der HPA skaliert horizontal (mehr Pods), weil die CPU-Auslastung steigt. Gleichzeitig senkt der VPA die CPU-Requests, was die prozentuale Auslastung weiter erhoeht -- eine Endlosschleife.
# FALSCH: VPA und HPA auf CPU
# VPA
spec:
resourcePolicy:
containerPolicies:
- controlledResources: ["cpu", "memory"]
# HPA
spec:
metrics:
- type: Resource
resource:
name: cpu # Konflikt!
target:
type: Utilization
averageUtilization: 70
# RICHTIG: VPA auf CPU/Memory, HPA auf Custom Metrics
# VPA steuert die Groesse der Pods
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-api-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: web-api
controlledResources:
- cpu
- memory
---
# HPA steuert die Anzahl der Pods (ueber Custom Metric)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-api
minReplicas: 2
maxReplicas: 20
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second # Custom Metric, kein CPU
target:
type: AverageValue
averageValue: "100"
Fuer eine ausfuehrliche Erklaerung der HPA-Konfiguration empfehlen wir unseren Kubernetes Autoscaling Guide.
Praxisbeispiel: Java-Anwendung mit variablem Heap
Java-Anwendungen sind ein klassischer VPA-Use-Case. Der Heap waechst dynamisch, und die initialen Requests sind fast immer falsch geschaetzt.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-boot-api
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: spring-boot-api
template:
metadata:
labels:
app: spring-boot-api
spec:
containers:
- name: spring-boot-api
image: registry.example.com/spring-api:v2.3.0
env:
- name: JAVA_OPTS
value: "-XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0"
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 1Gi
---
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: spring-boot-api-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: spring-boot-api
updatePolicy:
updateMode: "Auto"
minReplicas: 2
resourcePolicy:
containerPolicies:
- containerName: spring-boot-api
minAllowed:
cpu: 100m
memory: 256Mi
maxAllowed:
cpu: 4000m
memory: 4Gi
Tipp: Verwenden Sie MaxRAMPercentage statt fester -Xmx-Werte. So passt sich der Heap automatisch an die vom VPA gesetzten Memory-Requests an.
Praxisbeispiel: Batch-Jobs optimieren
Batch-Jobs haben oft stark schwankenden Ressourcenbedarf. Mit VPA im Modus Initial bekommen neue Jobs automatisch passende Requests:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: data-import-vpa
namespace: batch
spec:
targetRef:
apiVersion: batch/v1
kind: CronJob
name: daily-data-import
updatePolicy:
updateMode: "Initial"
resourcePolicy:
containerPolicies:
- containerName: data-import
minAllowed:
cpu: 100m
memory: 256Mi
maxAllowed:
cpu: 8000m
memory: 16Gi
Goldilocks: VPA-Empfehlungen visualisieren
Goldilocks von Fairwinds erstellt automatisch VPA-Objekte im Modus Off fuer alle Deployments in einem Namespace und zeigt die Empfehlungen in einem Dashboard an.
# Goldilocks installieren
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm install goldilocks fairwinds-stable/goldilocks \
--namespace goldilocks \
--create-namespace \
--set dashboard.enabled=true
# Namespace fuer Goldilocks aktivieren
kubectl label namespace production goldilocks.fairwinds.com/enabled=true
# Dashboard aufrufen
kubectl port-forward -n goldilocks svc/goldilocks-dashboard 8080:80
# Oeffnen Sie http://localhost:8080 im Browser
Das Dashboard zeigt fuer jedes Deployment:
- Guaranteed QoS: Requests und Limits auf den empfohlenen Wert setzen
- Burstable QoS: Requests auf den empfohlenen Wert, Limits hoeher
- Aktuell vs. Empfohlen: Wie weit die aktuellen Werte von der Empfehlung abweichen
# Aktuelle Requests vs. VPA-Empfehlungen fuer alle Deployments anzeigen
kubectl get vpa -n production -o custom-columns=\
DEPLOYMENT:.spec.targetRef.name,\
CPU_TARGET:.status.recommendation.containerRecommendations[0].target.cpu,\
MEM_TARGET:.status.recommendation.containerRecommendations[0].target.memory,\
CPU_LOWER:.status.recommendation.containerRecommendations[0].lowerBound.cpu,\
CPU_UPPER:.status.recommendation.containerRecommendations[0].upperBound.cpu
VPA Troubleshooting
Empfehlungen bleiben leer
# Pruefen ob der Metrics Server funktioniert
kubectl top pods -n production
# Pruefen ob der VPA Recommender laeuft
kubectl logs -n vpa-system -l app=vpa-recommender --tail=50
# Haeufige Ursache: Metrics API nicht verfuegbar
kubectl get apiservice v1beta1.metrics.k8s.io -o yaml
Pods werden nicht evicted (Auto-Modus)
# Updater-Logs pruefen
kubectl logs -n vpa-system -l app=vpa-updater --tail=50
# Pruefen ob das PodDisruptionBudget den Evict blockiert
kubectl get pdb -n production
# Pruefen ob minReplicas das Evict verhindert
kubectl get vpa order-service-vpa -n production -o yaml | \
grep -A2 updatePolicy
Admission Controller setzt keine Requests
# Webhook-Konfiguration pruefen
kubectl get mutatingwebhookconfigurations | grep vpa
# Admission Controller Logs
kubectl logs -n vpa-system -l app=vpa-admission-controller --tail=50
# Test: Pod loeschen und pruefen ob der neue Pod angepasste Requests hat
kubectl delete pod -n production -l app=order-service --wait=false
kubectl get pods -n production -l app=order-service -o yaml | \
grep -A4 "resources:"
Best Practices
1. Immer minAllowed und maxAllowed setzen
Ohne Grenzen koennte der VPA extrem kleine oder grosse Werte empfehlen:
resourcePolicy:
containerPolicies:
- containerName: app
minAllowed:
cpu: 50m # Unter 50m wird es fuer die meisten Apps eng
memory: 64Mi # Unter 64Mi sind OOM-Kills wahrscheinlich
maxAllowed:
cpu: 4000m # Obergrenze basierend auf Node-Groesse
memory: 8Gi # Obergrenze basierend auf Budget
2. VPA-Empfehlungen in CI/CD einbauen
Statt den Auto-Modus zu nutzen, koennen Sie die Empfehlungen in Ihre Pipeline integrieren:
# Skript fuer die CI/CD-Pipeline
# VPA-Empfehlungen auslesen und als PR vorschlagen
NAMESPACE="production"
for vpa in $(kubectl get vpa -n "$NAMESPACE" -o jsonpath='{.items[*].metadata.name}'); do
deployment=$(kubectl get vpa "$vpa" -n "$NAMESPACE" \
-o jsonpath='{.spec.targetRef.name}')
target_cpu=$(kubectl get vpa "$vpa" -n "$NAMESPACE" \
-o jsonpath='{.status.recommendation.containerRecommendations[0].target.cpu}')
target_mem=$(kubectl get vpa "$vpa" -n "$NAMESPACE" \
-o jsonpath='{.status.recommendation.containerRecommendations[0].target.memory}')
echo "Deployment: $deployment -> CPU: $target_cpu, Memory: $target_mem"
done
3. PodDisruptionBudgets verwenden
Im Auto-Modus evicted der VPA Pods. Ohne PDB koennte er alle Pods gleichzeitig evicten:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: order-service-pdb
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app: order-service
Mehr zum Thema PodDisruptionBudgets finden Sie in unserem PDB Guide.
4. Schrittweise einfuehren
# Phase 1: VPA im Off-Modus fuer alle Namespaces (2 Wochen)
# -> Empfehlungen analysieren, Einsparpotenzial berechnen
# Phase 2: VPA im Initial-Modus fuer Staging (2 Wochen)
# -> Pruefen ob die empfohlenen Werte in der Praxis funktionieren
# Phase 3: VPA im Auto-Modus fuer Staging (2 Wochen)
# -> Eviction-Verhalten beobachten, PDBs pruefen
# Phase 4: VPA im Auto-Modus fuer Production
# -> Mit konservativen minAllowed-Werten starten
Kosten-Impact: Was bringt der VPA?
Ein typisches Beispiel aus der Praxis:
Vorher (manuelle Requests):
20 Pods x 500m CPU x 1Gi Memory = 10 CPU Cores, 20Gi Memory reserviert
Tatsaechliche Nutzung: 2 CPU Cores, 5Gi Memory
Auslastung: 20% CPU, 25% Memory
Nachher (VPA-optimiert):
20 Pods x 120m CPU x 300Mi Memory = 2.4 CPU Cores, 6Gi Memory reserviert
Tatsaechliche Nutzung: 2 CPU Cores, 5Gi Memory
Auslastung: 83% CPU, 83% Memory
Einsparung: 3-4 Nodes weniger noetig
In Kombination mit dem Cluster Autoscaler fuehrt das direkt zu geringeren Cloud-Kosten. Fuer eine umfassende Kosten-Strategie lesen Sie unseren Kubernetes Kosten-Optimierung Guide.
Fazit
Der Vertical Pod Autoscaler loest ein Problem, das in fast jedem Kubernetes-Cluster existiert: falsche Resource Requests. Die Installation ist einfach, der Modus Off ist risikolos, und die Empfehlungen sind in den meisten Faellen praezise.
Starten Sie mit dem Modus Off und Goldilocks fuer die Visualisierung. Analysieren Sie die Empfehlungen fuer zwei Wochen. Dann wechseln Sie schrittweise auf Initial oder Auto. Die typische Einsparung liegt bei 30-50% der reservierten Ressourcen -- das sind bei groesseren Clustern schnell mehrere tausend Euro im Monat.
Fuer das Zusammenspiel mit HPA und Cluster Autoscaler lesen Sie unseren Autoscaling-Gesamtueberblick.
Verwandte Artikel
- Kubernetes Autoscaling: HPA, VPA und Cluster Autoscaler
- Kubernetes Kosten-Optimierung Praxis-Guide
- Kubernetes Resource Management
- Kubernetes OOM Kills vermeiden
- Kubernetes Pod Disruption Budget
Moechten Sie die Ressourcen-Effizienz Ihres Kubernetes-Clusters analysieren lassen? Unsere Experten fuehren eine kostenfreie Erstanalyse durch und zeigen Ihnen das konkrete Einsparpotenzial mit VPA und Goldilocks -- jetzt Termin vereinbaren.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Capacity Planning: Kubernetes-Autoscaling richtig nutzen
HPA, VPA, Cluster Autoscaler und KEDA kombinieren für Capacity Planning in Kubernetes. Mit Praxisbeispielen und Entscheidungshilfe.
Kubernetes Skalierung: HPA, VPA und KEDA kombinieren
Kubernetes Skalierungs-Patterns im Überblick: HPA, VPA, Cluster Autoscaler und KEDA richtig kombinieren für Multi-Dimensional Autoscaling.
Kubernetes Autoscaling: Kosten sparen mit HPA, VPA und Karpenter
Mit Kubernetes Autoscaling 25-40% Cloud-Kosten sparen. HPA, VPA und Cluster Autoscaler richtig konfigurieren, Überprovisionierung erkennen und beseitigen.
Kubernetes Performance verdoppeln: Tuning-Anleitung
Kubernetes Performance systematisch verdoppeln: Requests und Limits tunen, HPA konfigurieren, CNI und Storage-IOPS optimieren mit YAML-Beispielen.
Kubernetes Performance Tuning: Bottlenecks finden
Kubernetes Performance optimieren: Resource Requests richtig setzen, HPA und Cluster Autoscaler konfigurieren und Bottlenecks systematisch finden.