- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Performance verdoppeln: Ein systematischer Ansatz
TL;DR
- Die meisten Performance-Probleme entstehen durch falsch gesetzte CPU/Memory Requests und Limits -- beginnen Sie dort.
- CPU Throttling ist der haeufigste unsichtbare Performance-Killer. Pruefen Sie
container_cpu_cfs_throttled_periods_totalin Prometheus. - Der Horizontal Pod Autoscaler (HPA) bringt nur dann etwas, wenn die einzelnen Pods bereits korrekt dimensioniert sind.
- Storage-IOPS und Netzwerk-Latenz werden oft uebersehen, sind aber bei datenintensiven Workloads die eigentlichen Bottlenecks.
- Messen Sie vor und nach jeder Aenderung. Ohne Baseline koennen Sie nicht wissen, ob eine Optimierung tatsaechlich hilft.
Wo faengt man an?
Performance-Tuning in Kubernetes ist kein einmaliges Projekt, sondern ein iterativer Prozess. Bevor Sie irgendetwas aendern, brauchen Sie zwei Dinge: ein funktionierendes Monitoring und eine Baseline-Messung.
Ohne Monitoring fliegen Sie blind. Ohne Baseline wissen Sie nicht, ob Ihre Aenderungen etwas gebracht haben. Investieren Sie also die erste Zeit in ein solides Setup aus Prometheus, Grafana und kube-state-metrics. Unser Artikel zu Kubernetes Monitoring zeigt, wie Sie das kosteneffizient aufsetzen.
Wenn das Monitoring steht, messen Sie fuer Ihre kritischen Services: End-to-End-Latenz (P50, P95, P99), Durchsatz (Requests/Sekunde), CPU- und Memory-Auslastung pro Pod, und Fehlerrate. Das ist Ihre Baseline. Alles weitere baut darauf auf.
Bereich 1: CPU und Memory Requests/Limits
Das ist mit Abstand der wirkungsvollste Hebel. Falsch gesetzte Requests und Limits verursachen zwei Probleme:
Zu niedrige Requests: Der Scheduler platziert zu viele Pods auf einem Node, weil er denkt, die Pods brauchen wenig Ressourcen. Ergebnis: CPU Throttling und Memory Pressure.
Zu hohe Requests: Nodes sind auf dem Papier voll, aber die tatsaechliche Auslastung liegt bei 20%. Sie zahlen fuer Kapazitaet, die niemand nutzt.
CPU Throttling erkennen
CPU Throttling ist trickisch, weil es in kubectl top pods nicht direkt sichtbar ist. Ihr Pod zeigt vielleicht nur 200m CPU-Nutzung bei einem Limit von 500m -- und ist trotzdem gedrosselt. Das passiert, wenn der Pod in kurzen Bursts mehr CPU braucht, als das Limit erlaubt.
Pruefen Sie in Prometheus:
# Rate der gedrosselten CPU-Perioden
rate(container_cpu_cfs_throttled_periods_total{container!=""}[5m])
/
rate(container_cpu_cfs_periods_total{container!=""}[5m])
Wenn dieser Wert ueber 20% liegt, wird Ihr Pod spuerbar ausgebremst. Erhoehen Sie das CPU-Limit oder entfernen Sie es (dazu gleich mehr).
Die Debate: CPU Limits ja oder nein?
Es gibt eine aktive Diskussion in der Community, ob CPU Limits ueberhaupt sinnvoll sind. Das Argument dagegen: CPU ist eine komprimierbare Ressource. Wenn ein Node freie CPU hat, sollte jeder Pod sie nutzen duerfen. Ein Limit verhindert das kuenstlich.
| Ansatz | Vorteile | Nachteile |
|---|---|---|
| CPU Requests + Limits setzen | Vorhersehbares Verhalten, kein Noisy-Neighbor-Problem | CPU Throttling moeglich, auch wenn Node nicht ausgelastet |
| Nur CPU Requests, keine Limits | Pods koennen freie CPU nutzen, kein Throttling | Weniger vorhersehbar, ein Pod kann andere verdraengen |
| Memory: Immer Limits setzen | Pflicht. Ohne Memory Limit wird der Pod bei Memory Pressure vom OOM-Killer getoetet | -- |
Unsere Empfehlung fuer den Einstieg: Setzen Sie CPU Requests realistisch (basierend auf Messwerten), setzen Sie CPU Limits grosszuegig (2-3x der typischen Nutzung), und setzen Sie Memory Limits immer. Passen Sie iterativ an.
Praxisbeispiel: Gut dimensioniertes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: registry.example.com/order-service:3.2.1
ports:
- containerPort: 8080
resources:
requests:
cpu: "200m" # Basiert auf gemessenem P95-Verbrauch
memory: "384Mi" # Basiert auf stabilem RSS nach Warmup
limits:
cpu: "800m" # 4x Request, um Bursts abzufangen
memory: "512Mi" # 33% Puffer ueber Request
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 15
Die Kommentare im YAML sind wichtig: Dokumentieren Sie, warum ein bestimmter Wert gewaehlt wurde. In drei Monaten wissen Sie sonst nicht mehr, ob die 200m ein Messwert oder eine Schaetzung waren.
Bereich 2: Horizontal Pod Autoscaler (HPA)
Der HPA skaliert die Anzahl der Pods basierend auf Metriken. Aber er ist nur so gut wie seine Konfiguration.
Haeufige HPA-Fehler
- CPU-Target zu niedrig (z.B. 50%): Der HPA skaliert staendig hoch und runter (Flapping). Das verursacht unnoetige Pod-Starts und -Stops.
- CPU-Target zu hoch (z.B. 90%): Der HPA reagiert zu spaet. Bis neue Pods bereit sind, ist der Lastpeak vorbei und die Latenz war schon hoch.
- Keine
stabilizationWindowSeconds: Ohne Stabilisierungsfenster reagiert der HPA auf kurzfristige Spikes und skaliert ueberschnell.
HPA mit Custom Metrics
Standard-CPU-basiertes Autoscaling reicht oft nicht. Besser: Skalieren Sie nach anwendungsspezifischen Metriken wie Request-Rate oder Queue-Laenge.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 3
maxReplicas: 15
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 5 Min warten vor Scale-Down
policies:
- type: Percent
value: 25 # Max 25% der Pods auf einmal entfernen
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Pods
value: 4 # Max 4 Pods auf einmal hinzufuegen
periodSeconds: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100" # Skaliere hoch wenn > 100 req/s pro Pod
Das behavior-Feld ist ab Kubernetes 1.23 stabil und gibt Ihnen feine Kontrolle ueber das Skalierungsverhalten. Ohne es flattert der HPA bei vielen Workloads. Mehr Details zum HPA-Tuning finden Sie in unserem HPA-Guide.
Bereich 3: Netzwerk-Performance
CNI-Wahl
Das Container Network Interface (CNI) Plugin hat erheblichen Einfluss auf die Netzwerk-Latenz und den Durchsatz. Hier ein Ueberblick:
| CNI Plugin | Kernel Datapath | eBPF Support | NetworkPolicy | Performance-Profil |
|---|---|---|---|---|
| Flannel | VXLAN/iptables | Nein | Nein (nativ) | Einfach, ausreichend fuer kleine Cluster |
| Calico | iptables oder eBPF | Ja (ab v3.13) | Ja | Gute Balance aus Features und Performance |
| Cilium | eBPF nativ | Ja | Ja (+ L7) | Beste Netzwerk-Performance, besonders bei vielen Pods und Policies |
Cilium mit eBPF umgeht den klassischen iptables-Stack komplett. Bei Clustern mit vielen Network Policies oder tausenden Pods macht das einen messbaren Unterschied in der Latenz (oft 10-30% weniger Overhead gegenueber iptables-basiertem Networking).
DNS als versteckter Bottleneck
Jeder Service-Call innerhalb des Clusters loest eine DNS-Anfrage aus. CoreDNS ist der Standard-DNS-Server in Kubernetes, und bei hoher Last kann er zum Bottleneck werden.
Anzeichen: Sporadisch hohe Latenzen, die nicht mit CPU oder Memory korrelieren. Pruefen Sie die CoreDNS-Metriken in Prometheus:
# CoreDNS Request-Latenz pruefen
kubectl -n kube-system top pods -l k8s-app=kube-dns
# CoreDNS Logs auf Fehler pruefen
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=100
Loesungen:
- CoreDNS horizontal skalieren (mehr Replikas)
- NodeLocal DNSCache aktivieren (DaemonSet, das DNS-Anfragen lokal cached)
- In Ihrer Anwendung: Connection Pooling nutzen, damit nicht jeder HTTP-Request eine neue DNS-Aufloesung ausloest
Bereich 4: Storage-Performance
Storage wird beim Performance-Tuning oft vergessen, ist aber bei datenintensiven Anwendungen (Datenbanken, ML-Workloads, Logging) der entscheidende Faktor.
IOPS und Throughput messen
# Einfacher I/O-Benchmark in einem Pod
kubectl run iobench --image=alpine --rm -it --restart=Never -- sh -c '
apk add fio &&
fio --name=test --ioengine=libaio --direct=1 --rw=randread \
--bs=4k --size=256M --numjobs=4 --runtime=30 \
--filename=/tmp/testfile --group_reporting
'
StorageClass-Wahl
| Storage-Typ | Typische IOPS | Latenz | Einsatz |
|---|---|---|---|
| Standard HDD (pd-standard, gp2) | 100-300 | 5-10ms | Logs, Backups, unkritische Daten |
| SSD (pd-ssd, gp3) | 3.000-16.000 | 0.5-2ms | Datenbanken, Caches, APIs mit persistentem State |
| Local SSD / NVMe | 100.000+ | 0.1ms | Hochperformante Datenbanken, ML-Training |
Der Unterschied zwischen Standard-HDD und SSD-Storage kann einen Faktor 10-50x bei den IOPS ausmachen. Wenn Ihre Datenbank auf Standard-Storage laeuft und Sie sich ueber langsame Queries wundern, ist die StorageClass der erste Verdaechtige.
Mehr zur Storage-Konfiguration in Kubernetes finden Sie in unserem Storage-Guide.
Bereich 5: Anwendungsebene
Kubernetes-Tuning hilft nichts, wenn die Anwendung selbst ineffizient ist. Hier die wichtigsten Hebel:
Container-Image-Groesse: Ein 2 GB Image braucht bei jedem Pod-Start 30-60 Sekunden zum Pullen. Ein optimiertes 100 MB Image ist in 2-3 Sekunden da. Nutzen Sie Multi-Stage Builds und Alpine-Basisimages.
Startup- und Readiness-Probes: Zu aggressive Liveness Probes (z.B. alle 2 Sekunden mit Timeout 1 Sekunde) koennen einen Pod unter Last unnoetig neu starten. Setzen Sie initialDelaySeconds hoch genug und failureThreshold auf mindestens 3.
Connection Pooling: Jede neue TCP-Verbindung zu einer Datenbank kostet Zeit (DNS, TCP Handshake, TLS Handshake, Authentication). Ein Connection Pool haelt Verbindungen offen und recycelt sie. Das kann die Latenz fuer Datenbank-Calls um 50-80% reduzieren.
Caching: Ein Redis-Cache vor Ihrer Datenbank kann die Lesezugriffe um Groessenordnungen beschleunigen. Aber: Cache Invalidation ist schwierig. Beginnen Sie mit einfachem TTL-basiertem Caching fuer Daten, die sich selten aendern.
Mess- und Validierungsstrategie
Jede Optimierung muss gemessen werden. Hier ein pragmatischer Ablauf:
Baseline messen: P50, P95, P99 Latenz und Durchsatz unter realistischer Last (nicht synthetisch, sondern echte Traffic-Muster oder ein realistischer Load Test).
Eine Aenderung vornehmen: Immer nur eine Variable gleichzeitig aendern. Wenn Sie gleichzeitig die CPU Limits erhoehen und den HPA umkonfigurieren, wissen Sie nicht, was den Effekt gebracht hat.
Ergebnis messen: Gleiche Metriken, gleiche Lastbedingungen. Vergleichen Sie mit der Baseline.
Dokumentieren: Was wurde geaendert, warum, und was war das Ergebnis? Diese Dokumentation ist wertvoll fuer spaetere Optimierungsrunden.
Tools fuer Load Testing:
# k6 -- modernes Load Testing Tool
k6 run --vus 50 --duration 5m load-test.js
# hey -- einfacher HTTP Load Generator
hey -n 10000 -c 100 https://api.example.com/orders
# Ergebnisse mit Prometheus/Grafana korrelieren
# -> Dashboard mit Latenz, Throughput, Error Rate und Resource Usage
Checkliste: Die 10 wirkungsvollsten Massnahmen
| Prioritaet | Massnahme | Erwarteter Impact | Aufwand |
|---|---|---|---|
| 1 | CPU/Memory Requests/Limits auf Messwerte setzen | Hoch | Niedrig |
| 2 | CPU Throttling identifizieren und beheben | Hoch | Niedrig |
| 3 | HPA mit stabilizationWindow konfigurieren | Mittel-Hoch | Niedrig |
| 4 | Storage-Klasse auf SSD upgraden | Hoch (bei I/O-lastigen Workloads) | Niedrig |
| 5 | Container-Images verkleinern (Multi-Stage Build) | Mittel | Mittel |
| 6 | Connection Pooling aktivieren | Mittel-Hoch | Mittel |
| 7 | CoreDNS skalieren / NodeLocal DNS Cache | Mittel | Niedrig |
| 8 | CNI auf eBPF-basierte Loesung migrieren | Mittel | Hoch |
| 9 | Caching-Layer (Redis/Memcached) einfuehren | Hoch | Mittel-Hoch |
| 10 | Readiness/Liveness Probes tunen | Niedrig-Mittel | Niedrig |
Arbeiten Sie die Liste von oben nach unten ab. Die Massnahmen mit dem besten Verhaeltnis von Impact zu Aufwand stehen oben.
Weitergehende Ressourcen
- Fuer die korrekte Dimensionierung Ihres Clusters empfehlen wir den Artikel zu Kubernetes Capacity Planning.
- Die Grundlagen fuer einen performanten Production-Cluster finden Sie im Guide zur Kubernetes Production-Einrichtung.
- Wer die Kosten der optimierten Infrastruktur im Blick behalten will, findet Orientierung im Kubernetes Hosting Kostenvergleich.
- Fuer GPU-intensive Workloads (ML, AI) lohnt sich ein Blick auf die GPU-Auslastungsoptimierung.
Wenn Sie bei der Performance-Analyse oder beim Tuning Ihrer Cluster Unterstuetzung brauchen, nehmen Sie Kontakt mit uns auf unter /kontakt.
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 Tuning: Bottlenecks finden
Kubernetes Performance optimieren: Resource Requests richtig setzen, HPA und Cluster Autoscaler konfigurieren und Bottlenecks systematisch finden.
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.
Capacity Planning: Kubernetes-Autoscaling richtig nutzen
HPA, VPA, Cluster Autoscaler und KEDA kombinieren für Capacity Planning in Kubernetes. Mit Praxisbeispielen und Entscheidungshilfe.