Try   HackMD

在 Kubernetes 中刪除 namespace 的時候卡在 Terminating 無法刪除

tags: k8s

Context

在 Kubernetes 中刪除 Namespae 的操作通常在 5 分鐘內會完成 (如果 namespace 中沒有太多 resources 的話),但有時候會發生超過 1 小時 Namespace 的狀態還在 Terminating 的狀態(如下圖),查看 GitHub 中相關的 Issue [1],發現原因可能就是 Kubernetes 刪除 Namespace 的流程出了問題,導致沒有正確執行 finalizer。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

這時可以使用 kubectl get namespaces <NAMESPACE> -o yaml 查看該 namespace 中的 finalizers 是否有設定東西,通常都是這個引起 namespace 無法正常刪除。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Solution

遇到這件事,可以手動修改 finalizers,將 finalizers 刪除,但刪除 finalizers 沒辦法透過 kubectl edit 指令完成,也無法透過 kubectl apply apply 新的 resource configurations。

根據 issue 內的說明,可以透過 kubernetes 的 Update finalize of a Namespace API 修改 finalizers 的值。

要直接呼叫 kubernetes 的 API 可以透過 kubectl proxy 指令,在本機建立 Proxy 連線到 Kubernetes 的 API Server。

指令:kubectl proxy --port 8080

接著建立 resource configurations,將 finalizers 刪除,如果電腦有安裝 jq 指令的話,可以透過 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 是否已經正常被刪除了。


  1. Kubernetes namespaces stuck in terminating state ↩︎