Veröffentlicht am

Pod Terminating hängt: Finalizer entfernen

Teilen:
Authors

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