Veröffentlicht am

Node NotReady debuggen: Ursachen finden und beheben

Teilen:
Authors

Kubernetes Node NotReady: Ursachen finden und beheben

TL;DR

  • Node NotReady bedeutet: Der Kubelet sendet keine Heartbeats mehr an den API-Server -- nach 40 Sekunden wird der Node als NotReady markiert.
  • Erster Befehl immer: kubectl describe node <node-name> -- die Conditions-Sektion zeigt die genaue Ursache.
  • Die haeufigsten Ursachen: Kubelet gestoppt, Disk Pressure, Memory Pressure, Container Runtime abgestuerzt, Netzwerk-Probleme.
  • Bei NotReady werden Pods nach 5 Minuten automatisch evicted und auf andere Nodes verschoben.
  • Monitoring mit Prometheus-Alerts verhindert ueberraschende NotReady-Zustaende.

Was Node NotReady bedeutet

Wenn kubectl get nodes diesen Status zeigt, hat Kubernetes den Kontakt zu einem Node verloren:

NAME          STATUS     ROLES    AGE    VERSION
worker-01     Ready      worker   120d   v1.30.2
worker-02     NotReady   worker   120d   v1.30.2
worker-03     Ready      worker   120d   v1.30.2

Der Kubelet sendet standardmaessig alle 10 Sekunden einen Heartbeat. Nach 40 Sekunden ohne Meldung markiert der Node Controller den Node als NotReady.

Der Diagnose-Workflow

Schritt 1: Node Conditions pruefen

# Node-Details mit allen Conditions
kubectl describe node worker-02

# Nur die Conditions extrahieren
kubectl get node worker-02 -o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\n"}{end}'

Die fuenf Node Conditions zeigen die Ursache:

ConditionBedeutung wenn True
Ready = FalseNode ist NotReady
MemoryPressureArbeitsspeicher knapp
DiskPressureFestplatte voll
PIDPressureZu viele Prozesse
NetworkUnavailableNetzwerk nicht funktionsfaehig

Schritt 2: Events und Node-Logs pruefen

# Events fuer den Node
kubectl get events --field-selector involvedObject.name=worker-02 --sort-by='.lastTimestamp'

# Auf dem Node selbst (SSH):
systemctl status kubelet
journalctl -u kubelet --since "10 minutes ago" --no-pager
systemctl status containerd

Die 6 haeufigsten Ursachen

1. Kubelet nicht laufend

Die haeufigste Ursache fuer kubernetes node notready. Der Kubelet-Prozess ist abgestuerzt oder gestoppt.

# SSH auf den Node
systemctl status kubelet
journalctl -u kubelet -n 50 --no-pager

Typische Fehler: falsche cgroup-Konfiguration, abgelaufene Zertifikate oder API-Server nicht erreichbar.

Loesung:

# Kubelet neu starten
sudo systemctl restart kubelet
sudo systemctl status kubelet

# Zertifikate pruefen
sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text -noout | grep "Not After"

# Kubelet beim Systemstart aktivieren
sudo systemctl enable kubelet

2. Disk Pressure

Weniger als 15% freier Speicherplatz auf der Root-Partition. Kubernetes stoppt das Scheduling neuer Pods.

# Von aussen pruefen
kubectl describe node worker-02 | grep -A2 "DiskPressure"

# Auf dem Node
df -h
du -sh /var/log/* /var/lib/containerd/*

Loesung:

# Alte Container-Images entfernen
sudo crictl rmi --prune

# Systemd Journal bereinigen
sudo journalctl --vacuum-size=500M

# Alte Logs loeschen
sudo find /var/log -name "*.log" -mtime +7 -delete

Log-Rotation praeventiv konfigurieren:

# /var/lib/kubelet/config.yaml
containerLogMaxSize: "50Mi"
containerLogMaxFiles: 3
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
evictionHard:
  nodefs.available: "10%"
  imagefs.available: "15%"

3. Memory Pressure

Weniger als 100Mi freier Speicher. Kubernetes beginnt mit der Eviction von Pods.

kubectl top node worker-02
kubectl top pods --all-namespaces --sort-by=memory | head -20

Loesung:

# Memory-intensiven Pod verschieben
kubectl delete pod memory-hungry-app -n production

Thresholds in der Kubelet-Konfiguration anpassen:

# /var/lib/kubelet/config.yaml
evictionHard:
  memory.available: "200Mi"
evictionSoft:
  memory.available: "500Mi"
evictionSoftGracePeriod:
  memory.available: "2m"

4. PID Pressure

Zu viele laufende Prozesse auf dem Node.

kubectl describe node worker-02 | grep -A2 "PIDPressure"
# Auf dem Node:
ps aux | wc -l

Loesung:

# /var/lib/kubelet/config.yaml
podPidsLimit: 4096
evictionHard:
  pid.available: "10%"

5. Container Runtime nicht erreichbar

Containerd oder CRI-O ist abgestuerzt. Typisches Symptom in den Kubelet-Logs: PLEG is not healthy.

systemctl status containerd
journalctl -u containerd -n 50 --no-pager
sudo crictl --runtime-endpoint unix:///run/containerd/containerd.sock info

Loesung:

sudo systemctl restart containerd
sudo systemctl status containerd

6. Netzwerk-Probleme

Der Node kann den API-Server nicht erreichen. Ursachen: Netzwerk-Partition, Firewall, defektes CNI-Plugin.

# Auf dem Node: API-Server erreichbar?
curl -k https://api-server:6443/healthz

# CNI-Plugin Status
ls /etc/cni/net.d/
kubectl -n kube-system logs -l k8s-app=calico-node --tail=30

Loesung:

# CNI-Plugin Pod auf dem betroffenen Node neu starten
kubectl -n kube-system delete pod -l k8s-app=calico-node --field-selector spec.nodeName=worker-02

# Firewall-Regeln pruefen
sudo iptables -L -n | head -30

Node sicher aus dem Cluster nehmen

# Keine neuen Pods auf den Node schedulen
kubectl cordon worker-02

# Pods kontrolliert verschieben
kubectl drain worker-02 \
  --ignore-daemonsets \
  --delete-emptydir-data \
  --grace-period=60 \
  --timeout=300s

# Node reparieren, dann wieder freigeben
kubectl uncordon worker-02

Monitoring: Node NotReady verhindern

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: node-health-alerts
  namespace: monitoring
spec:
  groups:
    - name: node-health
      rules:
        - alert: NodeNotReady
          expr: kube_node_status_condition{condition="Ready",status="true"} == 0
          for: 2m
          labels:
            severity: critical
          annotations:
            summary: "Node {{ $labels.node }} ist NotReady"

        - alert: NodeDiskPressure
          expr: kube_node_status_condition{condition="DiskPressure",status="true"} == 1
          for: 1m
          labels:
            severity: warning
          annotations:
            summary: "Festplatte auf {{ $labels.node }} wird knapp"

        - alert: NodeMemoryPressure
          expr: kube_node_status_condition{condition="MemoryPressure",status="true"} == 1
          for: 1m
          labels:
            severity: warning
          annotations:
            summary: "Arbeitsspeicher auf {{ $labels.node }} wird knapp"

Pod Disruption Budget: Verfuegbarkeit sichern

Stellen Sie sicher, dass Ihre Anwendungen bei Node-Ausfaellen verfuegbar bleiben:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: webapp-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: webapp

Zusammenfassung: Diagnose-Tabelle

UrsacheConditionDiagnoseLoesung
Kubelet gestopptReady=Falsesystemctl status kubeletsystemctl restart kubelet
Disk PressureDiskPressure=Truedf -hLogs/Images bereinigen
Memory PressureMemoryPressure=Truefree -hMemory-intensive Pods evicten
PID PressurePIDPressure=Trueps aux | wc -lProzesse beenden
Container RuntimeReady=False (PLEG)systemctl status containerdsystemctl restart containerd
NetzwerkNetworkUnavailable=Truecurl -k https://api:6443/healthzCNI/Firewall pruefen

Der wichtigste Tipp: Bei node notready troubleshooting immer zuerst kubectl describe node ausfuehren. Die Conditions-Sektion zeigt in 90% der Faelle die Ursache.

Verwandte Artikel


Wenn Sie wiederkehrende Node-Probleme haben oder Unterstuetzung beim Aufbau eines stabilen Kubernetes-Clusters brauchen, helfen wir gerne -- 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