- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Pod Evicted: Ursachen verstehen und verhindern
TL;DR
Evicted Pods entstehen durch Resource Pressure auf dem Node -- zu wenig Memory, Disk oder Ephemeral Storage. Prüfen Sie kubectl describe node auf Conditions wie MemoryPressure oder DiskPressure. Verhindern Sie Evictions durch korrekte Resource Requests, LimitRanges und Pod Priority Classes.
127 Pods evicted über Nacht -- was ist passiert?
So oder ähnlich beginnt der Montag, wenn ein Node unter Resource Pressure gerät. Kubernetes schützt den Node, indem es Pods "evicted" -- zwangsweise beendet und vom Node entfernt. Das ist kein Bug, sondern ein Schutzmechanismus. Aber es hilft nicht, wenn Ihre Produktion betroffen ist.
# Evicted Pods finden
kubectl get pods -A --field-selector=status.phase=Failed | grep Evicted
# Details eines evicted Pods anzeigen
kubectl describe pod <evicted-pod-name> -n <namespace>
# Suchen Sie nach "Status: Failed" und "Reason: Evicted"
Die 3 Eviction-Trigger
Kubernetes überwacht drei Ressourcen auf jedem Node. Wird ein Schwellenwert unterschritten, beginnt die Eviction:
| Condition | Schwellenwert (Default) | Eviction-Signal |
|---|---|---|
| MemoryPressure | < 100Mi verfügbar | memory.available |
| DiskPressure | < 10% oder < 15% (imagefs) | nodefs.available |
| PIDPressure | Kernel PID-Limit nahe | pid.available |
# Node Conditions prüfen
kubectl describe node <node-name> | grep -A 5 Conditions
# Aktuelle Resource-Nutzung des Nodes
kubectl top node <node-name>
Wer wird zuerst evicted?
Kubernetes evicted Pods in dieser Reihenfolge:
- BestEffort Pods (keine Requests/Limits definiert) -- werden zuerst evicted
- Burstable Pods (Requests < Limits oder nur teilweise definiert)
- Guaranteed Pods (Requests = Limits für CPU und Memory) -- werden zuletzt evicted
Innerhalb derselben QoS-Klasse entscheidet die tatsächliche Nutzung relativ zu den Requests. Pods, die ihre Requests am stärksten überschreiten, fliegen zuerst.
# QoS-Klasse eines Pods prüfen
kubectl get pod <pod-name> -o jsonpath='{.status.qosClass}'
Ursache 1: Memory Pressure
Die häufigste Ursache. Ein oder mehrere Pods verbrauchen mehr Memory als angefordert, der Node läuft voll.
# Memory-Nutzung aller Pods auf einem Node
kubectl get pods --field-selector spec.nodeName=<node-name> -o wide -A
kubectl top pods -A --sort-by=memory | head -20
Fix: Resource Requests und Limits setzen
spec:
containers:
- name: app
resources:
requests:
memory: "256Mi" # Kubernetes reserviert diesen Wert
limits:
memory: "512Mi" # Container wird OOMKilled bei Überschreitung
Die Faustregel: requests auf den durchschnittlichen Verbrauch, limits auf das 1,5- bis 2-fache der Requests.
Ursache 2: Ephemeral Storage Eviction
Diese Ursache wird oft übersehen. Container-Logs, temporäre Dateien und beschreibbare Layer verbrauchen Ephemeral Storage. Ohne Limits kann ein einzelner Pod den Node-Speicher füllen.
# Ephemeral Storage Nutzung prüfen
kubectl describe node <node-name> | grep -A 3 "Allocated resources"
# Welche Pods verbrauchen Ephemeral Storage?
kubectl get pods -o json -A | jq '.items[] | select(.spec.containers[].resources.requests["ephemeral-storage"] != null) | .metadata.name'
Fix: Ephemeral Storage Limits setzen
spec:
containers:
- name: app
resources:
requests:
ephemeral-storage: "1Gi"
limits:
ephemeral-storage: "2Gi" # Pod wird evicted bei Überschreitung
Typische Ephemeral-Storage-Verbraucher:
- Container-Logs, die nicht rotiert werden
/tmp-Dateien in Containern- Writable Container Layers (z.B. bei
apt installim laufenden Container)
Ursache 3: Disk Pressure (nodefs)
Der Node selbst hat zu wenig Disk Space. Oft verursacht durch Container Images, die den Image-Cache füllen.
# Disk-Nutzung auf dem Node prüfen (per SSH oder Debug-Container)
kubectl debug node/<node-name> -it --image=busybox -- df -h
# Image-Cache-Größe prüfen
kubectl debug node/<node-name> -it --image=busybox -- du -sh /var/lib/containerd
Fix: Alte Images bereinigen, Log-Rotation konfigurieren oder Node-Disk vergrößern.
Evictions verhindern: Best Practices
1. LimitRange im Namespace setzen
Erzwingt, dass jeder Pod Requests und Limits hat:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: production
spec:
limits:
- default:
memory: "256Mi"
cpu: "250m"
defaultRequest:
memory: "128Mi"
cpu: "100m"
type: Container
2. PriorityClasses für kritische Pods
Pods mit höherer Priority werden bei Evictions bevorzugt behalten:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: critical-production
value: 1000000
globalDefault: false
description: "Für produktionskritische Pods"
3. Pod Disruption Budgets
PDBs schützen nicht direkt vor Node-Pressure-Evictions, aber vor freiwilligen Disruptions (Upgrades, Drain):
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-app
Aufräumen: Evicted Pods löschen
Evicted Pods bleiben als Failed-Pods im Cluster. Sie verbrauchen keine Ressourcen, aber sie stören die Übersicht:
# Alle evicted Pods in allen Namespaces löschen
kubectl get pods -A --field-selector=status.phase=Failed -o json | \
jq -r '.items[] | select(.status.reason=="Evicted") | "\(.metadata.namespace) \(.metadata.name)"' | \
xargs -n2 kubectl delete pod -n
FAQ
Werden evicted Pods automatisch neu gestartet?
Ja, wenn sie von einem Controller (Deployment, StatefulSet, DaemonSet) verwaltet werden. Einzelne Pods ohne Controller sind nach der Eviction weg. Der neue Pod wird auf einem Node mit genügend Ressourcen gescheduled.
Kann ich die Eviction-Schwellenwerte anpassen?
Ja, über die Kubelet-Konfiguration mit --eviction-hard und --eviction-soft. Zum Beispiel: --eviction-hard=memory.available\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\<200Mi erhöht den Memory-Schwellenwert auf 200Mi. In Managed-Kubernetes-Clustern (EKS, AKS, GKE) haben Sie darauf meist keinen Zugriff.
Was ist der Unterschied zwischen Eviction und OOMKilled?
OOMKilled wird vom Linux Kernel ausgelöst, wenn ein einzelner Container sein Memory-Limit überschreitet. Eviction wird vom Kubelet ausgelöst, wenn der gesamte Node unter Memory Pressure steht. Bei OOMKilled wird nur der Container neu gestartet, bei Eviction wird der gesamte Pod vom Node entfernt.
Warum werden meine Guaranteed-Pods trotzdem evicted?
Guaranteed-Pods werden nur evicted, wenn Node-System-Prozesse (kubelet, containerd, OS) nicht mehr genügend Ressourcen haben. Das ist selten, kann aber bei sehr knapp dimensionierten Nodes passieren. Prüfen Sie, ob system-reserved und kube-reserved in der Kubelet-Konfiguration korrekt gesetzt sind.
Wenn Ihre Pods nach der Eviction in CrashLoopBackOff landen, hilft unser CrashLoopBackOff Troubleshooting Guide bei der weiteren Diagnose.
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
CoreDNS Debugging: Kubernetes-DNS Probleme lösen
DNS-Probleme in Kubernetes systematisch debuggen: CoreDNS-Logs, ndots-Konfiguration, NXDOMAIN-Fehler und Corefile-Optimierung für schnellere Auflösung.
Ephemeral Containers: Live-Debugging in Kubernetes
Ephemeral Containers fuer Live-Debugging in Kubernetes nutzen. Mit kubectl debug laufende Pods analysieren, Distroless-Images debuggen und Netzwerkprobleme loesen.
Kubernetes Incident Management: Runbooks erstellen
Effektive Runbooks für Kubernetes-Incidents erstellen: Vorlagen für CrashLoopBackOff, OOMKilled und Node-Ausfälle mit konkreten Debugging-Befehlen.
Resource Requests und Limits: Kubernetes-Guide
Kubernetes Resource Requests und Limits richtig setzen. CPU-Throttling, OOMKill, QoS-Klassen und LimitRange mit praktischen YAML-Beispielen erklärt.
Kubernetes Troubleshooting: Systematisch debuggen
Kubernetes-Probleme systematisch debuggen mit kubectl describe, logs und debug. Lösungen für ImagePullBackOff, CrashLoopBackOff, Pending Pods und DNS-Fehler.