Jitrak Blog

How to delete stuck terminating namespace in k8s

วิธีการลบ namespace ที่ติดสถานะ terminating ใน k8s

29 Aug 2025 11:15

Written by: Yosapol Jitrak

Stuck Terminating
Tags:

Kubernetes

Namespace

Terminating

เคยไหมครับ Kubernetes ลบ Namespace ไม่ออก

ลอง Get namespace ดูว่าสถานะจะติด Terminating

kubectl get ns
NAME                          STATUS        AGE
atlas-test-primary-failover   Active        22d
default                       Active        2y214d
grafana-k8s-monitoring        Terminating   66m
ingress-nginx                 Active        212d
kafbat-ui                     Active        14d
keda                          Active        198d
kube-node-lease               Active        2y214d
kube-public                   Active        2y214d
kube-state-metrics            Active        2y214d
kube-system                   Active        2y214d
production                    Active        2y214d
redis                         Active        363d

ทั้งที่ใช้ Option force รวมถึงใส่ Grace period เป็น 0 แล้วก็ยังลบไม่ออก โดยคำสั่งจะมีหน้าตาประมาณนี้

kubectl delete namespace <namespace-name> --grace-period=0 --force

แน่นอนปัญหานี้ไม่ได้มีเราเจอกันคนเดียวแน่นอน และผมก็เจอปัญหานี้มาตั้งแต่ปี 2019-2020 แล้ว ซึ่งสมัยนั้นผมเจอปัญหากับ Cert-manager บ่อยสุด แหล่งข้อมูลสมัยนั้นก็คือ deleting namespace stuck at “Terminating” state บอกว่าหลัก ๆ จะมาจากปัญหา Finalizers มีของอยู่

ตัวอย่างของ namespace ที่ Finalizers มีของอยู่คือ

kubectl get ns grafana-k8s-monitoring -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: '2025-08-15T18:44:06Z'
  deletionTimestamp: '2025-08-15T19:49:51Z'
  labels:
    kubernetes.io/metadata.name: grafana-k8s-monitoring
    name: grafana-k8s-monitoring
  name: grafana-k8s-monitoring
  resourceVersion: '587594176'
  uid: 38809b07-14ea-46ee-a4cb-9b0eb7a97633
spec:
  finalizers:
    - kubernetes
status:
  conditions: ...
  phase: Terminating

สมัยนั้นมีแต่คนบอกว่าวิธีการคือให้ลองลบ Finalizers ออก

วิธีแรกคือ Edit โดยตรง แล้วลบ kubernetes ออกจาก List ของ Finalizers ออกเอง ให้กลายเป็น Empty list หรือเปลี่ยนค่าเป็น null ซึ่งบางครั้งก็ยังลบไม่ออกอยู่ดี Edit to delete finallizer


วิธีถัดมาก็คือสารพัดยิง Curl เช่น Curl to delete finalizer ซึ่งวิธีนี้ต้องไปหา IP ของ Master Node ของคุณที่สามารถยิงได้ หรือต้องเปิด kube-proxy ไว้ก่อน ซึ่งวิธีนี้ผมไม่เคยใช้ครับ


วิธีถัดมาคือ Patch เช่น Patch to delete finallizer วิธีนี้คล้ายกับวิธีแรก แต่ไม่ต้องเข้าไป Edit โดยตรง ยิงคำสั่งเดียวจบ


อีกวิธีคือ Patch raw เช่น

Path raw to delete finallizer วิธีนี้ลบออกแน่นอน แต่…


⚠️ หยุดก่อน วิธีทั้งหมดนั้นไม่ใช่วิธีที่ถูกต้อง

Please do not remove the finalizer

Foundamental issue

ซึ่งคำตอบนี้ให้แก้ปัญหาที่ต้นเหตุ ซึ่งมาจาก Aggregated API group ที่ไม่พร้อมใช้งานแล้ว จึงทำให้ไม่สามารถลบ Resource นั้นออกได้ Namespace จึงรอให้ลบออกได้ก่อน จึงจะลบ Namespace ได้

หา API service ที่ไม่พร้อมใช้งานแล้ว

kubectl get apiservice --namespaced | grep False

หลังจากนั้นก็ลบ API service นั้นออก

kubectl delete apiservice <api-service-name>

เพียงเท่านี้ Namespace ก็จะลบออกได้ในทันทีครับ


ถ้าอยากลงลึกมากกว่านี้ลองดูวิดีโอนี้เลยครับ


ตอนนี้ทาง Google ก็มี Document สำหรับวิธีแก้ปัญหานี้แล้วเหมือนกัน แต่สมัยนั้นผมยังหาไม่เจอ Troubleshoot namespace stuck in the Terminating state


แต่ถ้ายังไม่ลบไม่ออกจริง ๆ แล้วต้องการลบ Namespace ก็ต้องยอมลบ Finalizers ผมจะใช้คำสั่งนี้

export NAMESPACE=<namespace>
kubectl get namespace $NAMESPACE-o json \
  | jq 'del(.spec.finalizers)' \
  | kubectl replace --raw "/api/v1/namespaces/$NAMESPACE/finalize" -f -

แต่ถ้าเครื่องไม่มี jq ก็ใช้อันนี้แทนครับ

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

ปล. Finalizers ไม่จำเป็นจะต้องเป็น Namespace เท่านั้นนะครับ Resource อื่นก็มีโอกาสติดได้เหมือนกัน แต่ส่วนใหญ่จะเจอปัญหากับ Namespace


จริง ๆ ยังมีคนใช้วิธีผิด ๆ เยอะกันอยู่ครับ หลายบทความ และหลายโพสก็ยังบอกว่าวิธีการคือให้ลองลบ Finalizers ออกเลย โดนไม่ได้แก้ปัญหาที่ต้นเหตุเลย อยากมาเขียนวิธีที่ถูกต้อง

อย่างของผมตัวอย่างที่ยกไว้ตอนต้นคือตอน Helm uninstall แล้วลบของให้ไม่หมด ซึ่งผมต้องการลบให้เกลี้ยง โดยการลบ Namespace ก่อน จากนั้นค่อยติดตั้งใหม่อีกครั้ง

จบแล้วครับ เจอกันใหม่บทความหน้าครับ

Credits: