- Authors

- Name
- Phillip Pham
- @ddppham
Pod Terminating hängt: Finalizer, Grace-Period, Force-Delete
TL;DR
Terminating heißt: Löschen ist angefordert, ein Finalizer oder ein noch laufender Prozess hält den Pod. Zuerst sehen, wer blockiert:
kubectl get pod POD -o jsonpath='{.metadata.finalizers}{"\n"}{.metadata.deletionTimestamp}{"\n"}'
Ist der Node noch da und der Prozess braucht nur länger als 30 Sekunden, warten oder terminationGracePeriodSeconds anheben. Ist der Node weg und der Pod bleibt liegen, ist Force-Delete der richtige Schritt. Finalizer am Pod löschen Sie nur, wenn Sie wissen, welches Objekt sie schützen.
Warum der Pod nicht verschwindet
Zwei Mechanismen, oft zusammen.
Grace-Period. kubectl delete setzt deletionTimestamp und schickt SIGTERM an den Container. Das Kubelet wartet terminationGracePeriodSeconds (Default 30s), dann SIGKILL. In der Zeit steht der Pod auf Terminating. Das ist kein Hänger, sondern der definierte Stopp. Ein Prozess, der SIGTERM ignoriert, braucht die vollen 30 Sekunden. Einer, der Verbindungen zu Ende schreibt, auch.
Finalizer. Solange metadata.finalizers nicht leer ist, löscht die API den Pod nicht, auch nach dem Kill. Typisch: foregroundDeletion bei einem Delete mit --cascade=foreground, ein Operator-Finalizer, oder bei Volumes die Protection auf dem PVC, nicht am Pod. Der Pod wartet, bis der Controller den Finalizer abnimmt. Ist der Controller tot, wartet er für immer.
kubectl get pod POD -o yaml | sed -n '/finalizers:/,/^[^ ]/p'
kubectl get node
Fehlt der Node in kubectl get node, kann das Kubelet den Prozess nicht mehr beenden und den Status nicht mehr melden. Dann hilft Warten nicht.
Force-Delete, wenn der Node nicht mehr existiert
kubectl delete pod POD --force --grace-period=0
Das entfernt den Pod aus dem API-Server, ohne auf das Kubelet zu warten. Richtig, wenn der Node gelöscht, ausgefallen oder aus dem Cluster genommen ist. Falsch, solange der Prozess auf einem lebenden Node noch auf ein Volume schreibt. Das API-Objekt ist dann weg, der Schreibvorgang nicht. Ein neues Replica kann dasselbe Volume öffnen. Bei ReadWriteOnce endet das in einem Mount-Fehler oder, schlimmer, in zwei Schreibern, wenn das Volume es zulässt.
Reihenfolge auf einem lebenden Node: normales Delete, Grace abwarten, erst dann Force. Bei einem StatefulSet mit PVC vorher prüfen, ob der Pod der einzige Nutzer des Claims ist.
Finalizer entfernen
Nur wenn der Controller, der den Finalizer besitzen sollte, nicht mehr läuft und das Objekt sonst nie weggeht.
kubectl patch pod POD -p '{"metadata":{"finalizers":null}}' --type=merge
kubernetes.io/pvc-protection sitzt auf dem PVC, nicht auf dem Pod. Den dort zu löschen, während ein Pod das Volume noch mounted, hebt den Schutz auf. Erst Pod weg, dann PVC. Ein Operator-Finalizer (some-operator/cleanup) bedeutet: der Operator wollte noch Aufräumen, Datenbank-User löschen, Cloud-Ressource freigeben. Wer den Finalizer streicht, behält die verwaiste Ressource. Das ist ein bewusster Kompromiss, kein Standard-Fix.
Der Pod kommt sofort wieder
Ein Deployment oder StatefulSet ersetzt den gelöschten Pod. Terminating an einem Replica und gleichzeitig ein neuer Pod im CrashLoopBackOff oder Pending ist normal. Sie haben den alten Pod entfernt, nicht die Ursache im Spec. Solange das ReplicaSet dasselbe Template ausrollt, wiederholt sich der Zustand.
Wollen Sie den Nachschub stoppen, skalieren Sie auf null oder ändern das Template. Ein Force-Delete am Symptom skaliert den Fehler nur schneller nach.
Quellen
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Exit Code 1: die erste Zeile im Previous-Log
Exit Code 1 auf Kubernetes: die Anwendung beendet sich selbst. kubectl logs --previous zeigt die Zeile. Speicher, Image-Pull und SIGKILL sind andere Codes.
Pod startet nicht: Status lesen, dann der Fix
Pod startet nicht: ein kubectl get pod, dann der Status. Pending, ImagePull, CrashLoop, Evicted und die Befehle, die den jeweiligen Fehler wirklich zeigen.
CrashLoopBackOff beheben: Logs, Probes, Exit-Code
CrashLoopBackOff beheben: kubectl logs --previous, Exit-Codes 1, 137 und 139, Liveness-Probes. Der Unterschied zu ImagePullBackOff in wenigen Minuten.
kubectl connection refused 6443 beheben
kubectl connection refused auf Port 6443: der API-Server antwortet nicht. kubeconfig, Kontext, Firewall, API-Prozess. Der Pod-Status kommt erst danach.
Error from server Forbidden: RBAC-Recht
kubectl Forbidden: Error from server (Forbidden) nennt User, Verb und Ressource. kubectl auth can-i zeigt das Recht, bevor jemand cluster-admin vergibt.
CreateContainerConfigError: Secret und ConfigMap
CreateContainerConfigError: fehlendes Secret, falscher Key oder Namespace. Der Container startet nicht, logs --previous bleibt leer. Das Event nennt das Objekt.
Exit Code 143: SIGTERM und Graceful Shutdown
Exit Code 143 ist SIGTERM: 128 plus 15. Beim Rollout ist das normal. Im Loop fehlt ein Handler oder die Grace-Period ist kürzer als der Stopp der Anwendung.
ImagePullBackOff beheben: Auth, Name, Limit
ImagePullBackOff beheben: Image-Name, imagePullSecrets und Registry-Rate-Limits. Welches Event den Unterschied macht und wann es kein CrashLoopBackOff ist.