Skip to content

How to Fix a Kubernetes Namespace Stuck in Terminating State

DodaTech 2 min read

In this tutorial, you'll learn about How to Fix a Kubernetes Namespace Stuck in Terminating State. We cover key concepts, practical examples, and best practices.

The Problem

You run kubectl delete namespace my-namespace and it hangs forever with Terminating status. Running kubectl get namespaces shows the namespace stuck in Terminating for minutes or hours. This happens when resources inside the namespace have finalizers that block deletion, webhooks that are now unreachable, or the namespace controller itself can't clean up dependent resources.

Quick Fix

1. Check which resources are blocking

kubectl get all -n my-namespace
kubectl get validatingwebhookconfigurations -A
kubectl get mutatingwebhookconfigurations -A

If a webhook configuration references the stuck namespace or a service within it, that webhook prevents namespace deletion. Remove any webhook configurations that reference the stuck namespace:

kubectl delete validatingwebhookconfiguration my-webhook
kubectl delete mutatingwebhookconfiguration my-webhook

2. Remove finalizers from the namespace

Get the namespace JSON and remove the finalizers array:

kubectl get namespace my-namespace -o json > ns.json

Edit ns.json to remove the "finalizers": [...] line (or set it to "finalizers": []), then apply:

kubectl replace --raw "/api/v1/namespaces/my-namespace/finalize" -f ./ns.json

3. Force delete using the API directly (one-liner)

kubectl proxy &
curl -k -H "Content-Type: application/json" -X PUT \
  --data-binary '{"kind":"Namespace","apiVersion":"v1","metadata":{"name":"my-namespace"},"spec":{"finalizers":[]}}' \
  http://127.0.0.1:8001/api/v1/namespaces/my-namespace/finalize
kill %1

4. Quick one-liner for force deletion

kubectl get namespace my-namespace -o json | tr -d "\n" | sed "s/\"finalizers\": \[[^]]\+\]/\"finalizers\": []/" | kubectl replace --raw /api/v1/namespaces/my-namespace/finalize -f -

5. Verify the namespace was removed

kubectl get namespaces | grep my-namespace

If the namespace no longer appears, the fix was successful. If it's still visible, repeat the steps or check for leftover resources that may be recreating the finalizers.

6. Patch the namespace as an alternative

kubectl patch namespace my-namespace -p '{"metadata":{"finalizers":[]}}' --type=merge

Common Causes

Cause Why It Gets Stuck Fix
Finalizers on resources Namespace controller waits for finalizer removal Remove finalizers from the namespace
Webhooks that reference the namespace Webhook is unreachable, blocking deletion Delete the webhook configuration
CRDs with instances in the namespace Custom resources prevent cleanup Delete CRD instances first
Controller loop recreating resources A controller recreates deleted resources Scale the controller to 0

Use kubectl describe for Detailed Diagnostics

kubectl describe pod <pod-name>
# Events:
#   Type     Reason     Age   From     Message
#   ----     ------     ----  ----     -------
#   Warning  BackOff    5m    kubelet  Back-off restarting failed container

The Events section at the bottom of kubectl describe output is the most valuable diagnostic tool. It shows a chronological log of scheduling failures, image pull errors, and container crashes.

Prevention

  • Delete all resources in a namespace first before deleting the namespace itself
  • Use kubectl delete all --all -n my-namespace to clear resources first
  • Avoid custom finalizers unless absolutely necessary
  • Delete webhook configurations before their target namespaces

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro