# 在 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)