Namespace stuck in Terminating — finalizers blocking deletion
kubectl get namespace shows Terminating for minutes or hours
Focused incident mode — strips away everything but this runbook.
Symptoms
- kubectl get namespace shows Terminating for minutes or hours
- Namespace resources are deleted but the namespace itself persists
- kubectl delete namespace hangs or times out
Removing finalizers manually bypasses the controller's cleanup logic. Only do this if you are sure the controller is not going to run its reconciliation.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Namespace finalizers
kubectl get namespace <namespace> -o jsonpath='{.spec.finalizers}'Remaining resources
kubectl api-resources --namespaced=true -o name | xargs -I {} kubectl get {} -n <namespace>
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Finalizer like servicecatalog.k8s.io is present but the controller is not running
- Namespace has no resources but is still Terminating
Confirm before fixing
kubectl get namespace <namespace> -o json | jq '.spec.finalizers'Read the exact finalizers
Fix
kubectl patch namespace <namespace> -p '{"metadata":{"finalizers":[]}' --type=mergeRemove the stuck finalizer to allow deletion to complete
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
kubectl get namespace <namespace> -o jsonpath='{.spec.finalizers}'Read the finalizers
kubectl get all,pvc,secrets -n <namespace>Find lingering resources
kubectl patch namespace <namespace> -p '{"metadata":{"finalizers":[]}' --type=mergeForce-remove stuck finalizers
kubectl get namespace <namespace>Confirm deletion completed
Prevention
- Ensure all operators/controllers that add finalizers are healthy and monitored.
- Avoid installing CRDs with finalizers unless the controller is reliably running.
- Add a liveness probe to the controller and alert on crashes.
- Test namespace deletion in staging regularly to catch stuck finalizers.
Related runbooks
Same stack, same failure family — worth a skim.
kubectl get pv shows status Released for extended period
StatefulSet pods stuck in Pending or ContainerCreating sequentially
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.