Skip to content

Kubernetes Namespace Stuck in Terminating Fix

DodaTech Updated 2026-06-24 3 min read

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

The Problem

Deleting a namespace hangs and the namespace stays in Terminating state:

$ kubectl delete namespace my-namespace
namespace "my-namespace" deleted

$ kubectl get namespaces
NAME              STATUS        AGE
my-namespace      Terminating   5m

The namespace appears to be deleted but never disappears. All resources inside the namespace should have been deleted, but some resource is preventing the cleanup.

Quick Fix

Step 1: List remaining resources in the namespace

kubectl api-resources --verbs=list --namespaced -o name | xargs -n1 kubectl get -n my-namespace 2>/dev/null

This shows all namespaced resources still in the namespace. Look for custom resources, CRDs, or resources with finalizers.

Step 2: Check the namespace YAML for finalizers

kubectl get namespace my-namespace -o yaml
apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
spec:
  finalizers:
  - kubernetes

The spec.finalizers list must be empty for the namespace to terminate. Common finalizers that get stuck:

  • kubernetes (Kubernetes default -- safe to remove)
  • foregroundDeletion (waits for child resources)
  • Custom finalizers from operators or controllers

Step 3: Patch the namespace to remove all finalizers

WRONG -- trying to delete with finalizers in place:

kubectl delete namespace my-namespace --force --grace-period=0

This may still hang if finalizers are present.

RIGHT -- remove all finalizers with a JSON patch:

kubectl get namespace my-namespace -o json | jq '.spec.finalizers = []' | kubectl replace --raw "/api/v1/namespaces/my-namespace/finalize" -f -

Or use Python:

python3 -c "
import json, sys
ns = json.load(sys.stdin)
ns['spec']['finalizers'] = []
json.dump(ns, sys.stdout)
" < <(kubectl get namespace my-namespace -o json) | kubectl replace --raw "/api/v1/namespaces/my-namespace/finalize" -f -

Step 4: Delete stuck custom resources

If CRDs have instances in the namespace, delete them first:

kubectl delete crd --all
kubectl delete $(kubectl get crd -o name) 2>/dev/null

Then retry the namespace deletion.

Step 5: Check for APIService resources blocking deletion

kubectl get apiservice

Look for APIService resources with Available=False that reference the stuck namespace:

NAME                       SERVICE                    AVAILABLE   AGE
v1beta1.example.com        my-namespace/operator       False       5d

Delete the problematic APIService:

kubectl delete apiservice v1beta1.example.com

Step 6: Force delete using the API directly

As a last resort, force delete through the raw Kubernetes API:

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

Use DodaTech's Namespace Cleaner to identify stuck resources, remove finalizers, and force-terminate namespaces safely.

Prevention

  • Always delete all resources in a namespace before deleting the namespace itself.
  • Use helm uninstall to remove Helm releases before deleting the namespace.
  • Avoid installing CRDs with scope: Namespaced unless necessary.
  • Set --timeout on kubectl delete namespace to detect hangs early.
  • Audit custom operators that add finalizers to resources.

Common Mistakes with namespace terminating

  1. Misunderstanding that String is [Char] with poor performance for large text operations
  2. Using foldl instead of foldl' causing stack overflow on large lists
  3. Forgetting deriving (Show, Eq) on custom data types needed for debugging

These mistakes appear frequently in real-world K8S code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Is it safe to force-delete a namespace by removing finalizers?

Yes, but only after verifying that no critical resources remain in the namespace. Removing spec.finalizers tells Kubernetes to skip the normal cleanup process. Any resources still in the namespace become orphaned.

Why does a namespace stay Terminating after deleting all visible resources?

Custom resources (CRDs) or APIService objects can hold finalizers that are not visible with kubectl get all. Run the full api-resources list command from Step 1 to find hidden resources.

How long should I wait before force-deleting a namespace?

Wait at least 2-3 minutes. Some controllers need time to clean up gracefully. If the namespace is still Terminating after 5 minutes, start investigating with the steps above.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro