- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Performance Tuning: Vom Bottleneck zur optimalen Auslastung
TL;DR
- 90% der Performance-Probleme in Kubernetes lassen sich auf falsch gesetzte Resource Requests und Limits zurueckfuehren
- CPU-Limits sind in den meisten Faellen kontraproduktiv -- CPU-Requests reichen aus, um faire Verteilung zu garantieren
- Der Cluster Autoscaler skaliert Nodes, nicht Pods. Der HPA skaliert Pods. Beide muessen zusammenspielen
- Messen vor Optimieren: Ohne Prometheus-Baseline ist jede Aenderung Blindflug
- VPA im Recommendation-Mode liefert bessere Insights als manuelles Raten bei Requests
Das Resource-Modell verstehen
Kubernetes verwaltet Compute-Ressourcen ueber zwei Mechanismen: Requests und Limits. Dieses Modell ist einfach zu beschreiben, aber die Auswirkungen sind subtil und oft missverstanden.
Requests sind Garantien. Der Scheduler platziert einen Pod nur auf einem Node, der die angeforderten Ressourcen frei hat. Sind 250m CPU requested, muessen 250m auf dem Node verfuegbar sein. Requests bestimmen also, wo ein Pod landet.
Limits sind Obergrenzen. Bei CPU fuehren Limits zu Throttling (der Kernel drosselt den Prozess via CFS Bandwidth Control). Bei Memory fuehren Limits zu OOMKill, wenn der Container mehr als das Limit allokiert.
Der entscheidende Punkt: Zu hohe Requests verschwenden Kapazitaet (Nodes sind "voll" laut Scheduler, aber real unterausgelastet). Zu niedrige Requests fuehren zu Overcommitment und Instabilitaet unter Last.
CPU Limits: Warum man sie oft weglassen sollte
Ein kontroverses Thema, aber durch Daten gut belegt: CPU-Limits verursachen in vielen Faellen mehr Probleme als sie loesen.
Das Problem liegt im Linux CFS (Completely Fair Scheduler). CPU-Limits werden ueber CFS Quota implementiert. Wenn ein Container sein CPU-Budget in einer Periode verbraucht hat, wird er fuer den Rest der Periode gedrosselt -- auch wenn die CPU idle ist.
Das Ergebnis: Latency-Spikes, die schwer zu diagnostizieren sind. Die CPU-Auslastung sieht niedrig aus (weil der Container ja gedrosselt wird), aber die Anwendung ist langsam.
Die Empfehlung: CPU-Requests setzen (fuer faire Scheduling-Verteilung), CPU-Limits in den meisten Faellen weglassen. Ausnahmen sind Multi-Tenant-Cluster, in denen Isolation kritisch ist.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api-service
template:
metadata:
labels:
app: api-service
spec:
containers:
- name: api
image: registry.example.com/api-service:3.1.0
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
# Kein CPU-Limit -- vermeidet CFS Throttling
memory: "1Gi"
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
failureThreshold: 3
Beachte: Memory-Limits sollten immer gesetzt werden. Ein Memory-Leak ohne Limit killt den gesamten Node via OOM-Killer auf Kernel-Ebene.
Bottlenecks finden: Die richtigen Metriken
Bevor man optimiert, muss man messen. Die folgenden PromQL-Queries decken die haeufigsten Performance-Probleme auf.
CPU Throttling erkennen:
# Container mit CPU-Throttling in den letzten 5 Minuten
# Werte ueber 25% sind problematisch
kubectl exec -n monitoring prometheus-0 -- \
promtool query instant http://localhost:9090 \
'sum by (namespace, pod, container) (
rate(container_cpu_cfs_throttled_periods_total[5m])
/
rate(container_cpu_cfs_periods_total[5m])
) > 0.25'
Memory-Ueberallokation finden:
# Verhaeltnis von tatsaechlicher Nutzung zu Requests
# Werte unter 0.5 bedeuten: Requests sind zu hoch
kubectl exec -n monitoring prometheus-0 -- \
promtool query instant http://localhost:9090 \
'sum by (namespace, pod) (
container_memory_working_set_bytes
)
/
sum by (namespace, pod) (
kube_pod_container_resource_requests{resource="memory"}
) < 0.5'
Diese Queries sind der Ausgangspunkt. Fuer ein vollstaendiges Monitoring-Setup verweisen wir auf Kubernetes Monitoring mit Open Source.
Horizontal Pod Autoscaler richtig konfigurieren
Der HPA ist das primaere Werkzeug fuer Workload-Skalierung. Die Default-Konfiguration (Skalierung bei 80% CPU) ist fuer viele Anwendungen nicht optimal.
Wichtige Parameter, die oft uebersehen werden:
| Parameter | Default | Empfehlung | Warum |
|---|---|---|---|
behavior.scaleDown.stabilizationWindowSeconds | 300s | 300-600s | Verhindert Flapping bei schwankender Last |
behavior.scaleUp.stabilizationWindowSeconds | 0s | 0-60s | Scale-Up sollte schnell sein |
behavior.scaleDown.policies[].periodSeconds | 60s | 60-120s | Wie schnell runterskaliert wird |
metrics[].resource.target.averageUtilization | 80% | Abhaengig vom Workload | IO-bound Apps brauchen andere Werte als CPU-bound |
minReplicas | 1 | Mindestens 2 fuer HA | 1 Replica = kein Rolling Update moeglich |
Ein praxistaugliches HPA-Manifest fuer einen API-Service:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-service-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-service
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 120
Die behavior-Section ist entscheidend. Ohne sie skaliert der HPA mit Default-Werten, die fuer Burst-Traffic oft zu langsam reagieren (Scale-Up) oder bei normaler Varianz zu aggressiv runterskalieren (Scale-Down).
Cluster Autoscaler: Nodes nachziehen
Der HPA skaliert Pods, aber wenn keine Node-Kapazitaet vorhanden ist, bleiben Pods im Status Pending. Hier kommt der Cluster Autoscaler (CA) ins Spiel.
Haeufige Fehler bei der CA-Konfiguration:
Zu kleine Node-Pools. Wenn der CA nur zwischen 2 und 4 Nodes skalieren darf, ist der Spielraum zu gering. Besser: min: 3, max: 15 und ueber Budget-Alerts absichern.
Nur einen Node-Pool verwenden. Unterschiedliche Workloads haben unterschiedliche Anforderungen. Ein Node-Pool mit 4 vCPU/8 GB fuer allgemeine Workloads und ein separater Pool mit 8 vCPU/32 GB fuer speicherintensive Anwendungen ist effizienter als ein Einheits-Pool.
Scale-Down nicht testen. Der CA entfernt Nodes nur, wenn alle Pods auf dem Node woanders Platz finden. DaemonSets, Pods mit lokalen Persistent Volumes oder Pods ohne Controller (bare Pods) blockieren das Scale-Down. Wer Kosten sparen will, muss das Scale-Down-Verhalten regelmaessig validieren.
Eine tiefergehende Analyse zum Kapazitaetsmanagement bietet Kubernetes Capacity Planning.
VPA: Automatische Empfehlungen fuer Requests
Der Vertical Pod Autoscaler (VPA) kann Requests automatisch anpassen. In der Praxis empfiehlt sich der "Recommendation"-Modus: Der VPA analysiert die tatsaechliche Nutzung und gibt Empfehlungen, ohne automatisch Aenderungen vorzunehmen.
So nutzt man den VPA als Analyse-Tool:
- VPA im Mode
Offdeployen (nur Empfehlungen, keine Aenderungen) - Nach 7 Tagen die Empfehlungen auswerten
- Empfehlungen manuell in die Deployment-Manifeste uebernehmen
- Nach der Anpassung erneut validieren
Die VPA-Empfehlungen sind besonders wertvoll fuer Workloads, die schon lange laufen und deren Requests nie angepasst wurden. Oft findet man 3-5x ueberallokierte Deployments, die erhebliche Cluster-Kapazitaet blockieren.
Netzwerk-Performance: CNI-Wahl und Service Mesh Overhead
Die CNI-Wahl hat direkten Einfluss auf die Netzwerk-Latenz. Ein Vergleich der gaengigsten Optionen:
| CNI | Throughput | Latency | eBPF Support | NetworkPolicy | Komplexitaet |
|---|---|---|---|---|---|
| Cilium | Hoch | Niedrig | Ja (nativ) | Ja (erweitert) | Mittel |
| Calico | Hoch | Niedrig | Ja (optional) | Ja | Mittel |
| Flannel | Mittel | Mittel | Nein | Nein (nativ) | Niedrig |
| Weave | Mittel | Mittel | Nein | Ja | Niedrig |
Cilium mit eBPF-basiertem Datapath umgeht iptables komplett, was bei Clustern mit vielen Services (500+) einen messbaren Latenz-Vorteil bringt. Fuer kleinere Setups ist der Unterschied marginal.
Service Meshes (Istio, Linkerd) fuegen Sidecar-Proxies hinzu, die pro Hop 1-3ms Latenz addieren. Das klingt wenig, kann aber bei tief verschachtelten Microservice-Calls (10+ Hops) relevant werden. Linkerd ist hier schlanker als Istio.
Storage-Performance: Die vergessene Dimension
Storage ist oft der groesste Bottleneck, wird aber zuletzt untersucht. Typische Probleme:
Falsche StorageClass. Standard-StorageClasses bei Cloud-Providern liefern oft nur 3.000 IOPS. Fuer Datenbank-Workloads (PostgreSQL, MySQL) braucht man 10.000+ IOPS. Pruefe die StorageClass-Parameter und waehle SSD-basierte Optionen.
ReadWriteOnce-Limitierung. PVCs mit ReadWriteOnce koennen nur von einem Node gemountet werden. Wenn der Pod auf einen anderen Node verschoben wird (z.B. durch Node-Drain), muss der PV erst detached und reattached werden. Das kann Minuten dauern. Fuer Details zur Storage-Konfiguration siehe Kubernetes Storage: DSGVO-konforme Loesungen.
CSI-Driver-Konfiguration. Viele CSI-Treiber unterstuetzen Volume-Expansion, Snapshots und Topology-Awareness. Diese Features muessen oft explizit aktiviert werden.
Container-Image-Optimierung
Grosse Container-Images sind ein versteckter Performance-Killer. Jedes Deployment, jedes Scale-Up-Event erfordert einen Image-Pull. Bei einem 2 GB Image und 10 neuen Pods sind das 20 GB Download-Traffic.
Praktische Massnahmen:
- Multi-Stage Builds verwenden: Build-Dependencies gehoeren nicht ins finale Image
- Alpine oder Distroless als Base-Image statt ubuntu/debian
- Layer-Caching optimieren: Selten aendernde Layers (OS-Pakete) oben, haeufig aendernde (App-Code) unten
- Image-Registry im selben Netzwerk/Region betreiben
Ein gut optimiertes Go-Service-Image ist 15-30 MB gross. Ein typisches Python-Service-Image mit pip-Installations liegt bei 200-500 MB. Der Unterschied ist bei Scale-Up-Events direkt spuerbar.
Probes: Fein konfigurieren statt Defaults
Falsch konfigurierte Probes sind eine haeufige Ursache fuer unnoetige Pod-Restarts und Traffic-Verlust.
Liveness Probes: Prueft, ob der Prozess noch lebt. Wichtig: Die Liveness-Probe sollte NICHT gegen externe Dependencies pruefen (Datenbank, Cache). Wenn die Datenbank kurz nicht erreichbar ist, soll der Pod nicht neugestartet werden, denn der Neustart loest das Problem nicht.
Readiness Probes: Prueft, ob der Pod Traffic empfangen kann. Hier duerfen externe Dependencies geprueft werden, da ein unready Pod einfach keinen Traffic bekommt, aber weiterlaeuft.
Startup Probes: Fuer Anwendungen mit langer Startzeit. Verhindert, dass Liveness-Probes die App toeten, bevor sie gestartet ist. Besonders wichtig fuer JVM-basierte Anwendungen.
Ein haeufiger Fehler: initialDelaySeconds auf 5 Sekunden bei einer Java-App, die 30 Sekunden zum Starten braucht. Resultat: Die Liveness-Probe killt den Pod in einer Endlosschleife.
Deployment-Strategien fuer Performance
Rolling Updates sind der Standard, aber die Default-Konfiguration ist konservativ. maxSurge: 25% und maxUnavailable: 25% bedeuten bei 4 Replicas, dass maximal 1 Pod gleichzeitig ersetzt wird.
Fuer schnellere Rollouts bei nicht-kritischen Services kann man maxSurge erhoehen. Fuer Zero-Downtime bei kritischen Services sollte maxUnavailable: 0 gesetzt werden, was bedeutet, dass immer die volle Kapazitaet verfuegbar ist.
Canary Deployments eignen sich, wenn man Performance-Regressions frueh erkennen will. 5% des Traffics auf die neue Version routen, Response-Zeiten vergleichen, dann stufenweise erhoehen. Unser Guide zu Kubernetes Canary Deployments beschreibt den Prozess im Detail.
Checkliste: Die 10 wichtigsten Quick Wins
- Alle Deployments auf korrekte Requests und Memory-Limits pruefen
- CPU-Limits bei latenz-sensitiven Services entfernen
- VPA im Recommendation-Mode fuer die Top-20-Deployments aktivieren
- HPA mit benutzerdefinierten Scaling-Behaviors fuer kritische Services
- Container-Images auf unnoetige Layers pruefen (dive-Tool)
- Liveness-Probes auf externe Dependencies pruefen (und entfernen)
- Node-Pool-Strategie: Workload-spezifische Node-Typen statt Einheits-Nodes
- Storage-IOPS der verwendeten StorageClasses validieren
- Pod Topology Spread Constraints fuer HA-kritische Services
- Prometheus-Dashboards fuer CPU-Throttling und OOMKill-Events einrichten
Fazit
Kubernetes-Performance-Optimierung ist kein einmaliges Projekt, sondern ein kontinuierlicher Prozess. Der wichtigste Schritt ist, Sichtbarkeit zu schaffen: Wer seine Cluster-Auslastung nicht kennt, kann nicht optimieren.
Die gute Nachricht: Die meisten Performance-Probleme haben einfache Ursachen. Falsche Requests, fehlende Autoscaler-Konfiguration, uebergrosse Images. Die hier beschriebenen Massnahmen lassen sich innerhalb weniger Wochen umsetzen und liefern messbare Ergebnisse.
Wer Unterstuetzung bei der Analyse oder Implementierung braucht, kann sich gerne an uns wenden. Ein initiales Cluster-Audit ist oft der effizienteste Einstiegspunkt: Kontakt aufnehmen.
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
Kubernetes Performance verdoppeln: Tuning-Anleitung
Kubernetes Performance systematisch verdoppeln: Requests und Limits tunen, HPA konfigurieren, CNI und Storage-IOPS optimieren mit YAML-Beispielen.
Kubernetes Requests und Limits richtig setzen
CPU und Memory Requests und Limits korrekt konfigurieren: QoS-Klassen verstehen, typische Fehler vermeiden und die richtigen Werte finden.
Vertical Pod Autoscaler (VPA) einrichten und konfigurieren
Kubernetes VPA einrichten und konfigurieren: Automatische CPU- und Memory-Empfehlungen, Update-Modi und Integration mit HPA praxisnah erklärt.
Kubernetes Requests, Limits und QoS richtig setzen
Kubernetes Requests und Limits optimal konfigurieren, QoS-Klassen verstehen und durch Right-Sizing bis zu 25 Prozent Cloud-Kosten sparen.
Prometheus PCA Zertifizierung für Kubernetes Monitoring
Die Prometheus Certified Associate (PCA) Zertifizierung bietet eine fundierte Validierung von Kubernetes Monitoring-Kenntnissen mit Prometheus. Erfahren Sie, wie diese offizielle CNCF-Zertifizierung deutschen Unternehmen hilft, ihre Observability-Strategien zu professionalisieren und die Betriebsstabilität ihrer Cloud-nativen Infrastrukturen zu gewährleisten – essenziell für ein zuverlässiges Kubernetes Monitoring in Deutschland.