# 在 Kubernetes 中刪除 namespace 的時候卡在 `Terminating` 無法刪除 ###### tags: `k8s` ## Context 在 Kubernetes 中刪除 Namespae 的操作通常在 5 分鐘內會完成 (如果 namespace 中沒有太多 resources 的話),但有時候會發生超過 1 小時 Namespace 的狀態還在 `Terminating` 的狀態(如下圖),查看 GitHub 中相關的 Issue [^k8s-issue-1],發現原因可能就是 Kubernetes 刪除 Namespace 的流程出了問題,導致沒有正確執行 finalizer。 ![](https://i.imgur.com/vCYtTgV.png) 這時可以使用 `kubectl get namespaces <NAMESPACE> -o yaml` 查看該 namespace 中的 `finalizers` 是否有設定東西,通常都是這個引起 namespace 無法正常刪除。 ![](https://i.imgur.com/Nsr5OiR.png) ## Solution 遇到這件事,可以手動修改 finalizers,將 finalizers 刪除,但刪除 finalizers 沒辦法透過 `kubectl edit` 指令完成,也無法透過 `kubectl apply` apply 新的 resource configurations。 根據 issue 內的說明,可以透過 kubernetes 的 [`Update finalize of a Namespace`](https://docs.okd.io/latest/rest_api/api/v1.Namespace.html#Put-api-v1-namespaces-name-finalize) API 修改 finalizers 的值。 要直接呼叫 kubernetes 的 API 可以透過 `kubectl proxy` 指令,在本機建立 Proxy 連線到 Kubernetes 的 API Server。 指令:`kubectl proxy --port 8080` 接著建立 resource configurations,將 finalizers 刪除,如果電腦有安裝 [`jq`](https://stedolan.github.io/jq/manual/#Assignment) 指令的話,可以透過 `kubectl get namespaces <NAMESPACE> -o json | jq '.spec.finalizers = []' > temp.json` 將 finalizers 清空,並將結果的 json 匯出至 `temp.json` 檔案 例如: ``` raccoon:~$ kubectl get ns <NAMESPACE> -o json | jq '.spec.finalizers = []' > temp.json raccoon:~$ cat temp.json { "apiVersion": "v1", "kind": "Namespace", "metadata": { "annotations": { "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"<NAMESPACE>\"}}\n" }, "creationTimestamp": "2019-03-12T09:31:01Z", "deletionTimestamp": "2019-05-29T05:49:07Z", "name": "<NAMESPACE>", "resourceVersion": "95028789", "selfLink": "/api/v1/namespaces/<NAMESPACE>", "uid": "8d0e98b4-44a9-11e9-aa7a-42010a8c0083" }, "spec": { "finalizers": [] }, "status": { "phase": "Terminating" } } ``` 有了修改過的 resource configurations 後,就可以透過 Kubernetes 的 api 修改 finalize 的值,可以透過 `curl` 指令呼叫 kubernetes 的 api。 範例: ``` raccoon:~$ curl -H "Content-Type: application/json" \ -X PUT \ --data-binary @temp.json \ http://127.0.0.1:8080/api/v1/namespaces/<NAMESPACE>/finalize { "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "<NAMESPACE>", "selfLink": "/api/v1/namespaces/<NAMESPACE>/finalize", "uid": "8d0e98b4-44a9-11e9-aa7a-42010a8c0083", "resourceVersion": "97983943", "creationTimestamp": "2019-03-12T09:31:01Z", "deletionTimestamp": "2019-05-29T05:49:07Z", "annotations": { "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"<NAMESPACE>\"}}\n" } }, "spec": { }, "status": { "phase": "Terminating" } }% ``` 呼叫完 API 後,就可以透過 `kubectl get namespace` 查看該 namespace 是否已經正常被刪除了。 [^k8s-issue-1]: [Kubernetes namespaces stuck in terminating state]( https://github.com/kubernetes/kubernetes/issues/19317)