天天看點

Kubernetes 系列(十八)如何删除卡住的命名空間

作者:回首不堪的流年

大家看一下下圖:

Kubernetes 系列(十八)如何删除卡住的命名空間

有兩個命名空間處于 Terminating 狀态,隻要您願意等待,這個讨厭的命名空間就一直在那裡。是的,我嘗試過等待

當然,我嘗試了所有我知道的CLI技巧:

k delete ns cdi --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
namespace "cdi" force deleted           

再一次,并沒有讓它消失!

那麼這些現象背後的原因是什麼呢?為什麼有時候命名空間會卡住?

Finalizers(終結器)

什麼是 Finalizers?

Finalizers 是受命名空間控制的 keys,它告訴 Kubernetes 在”完全删除”被标記删除的資源之前等待,直到滿足特定的條件。終結器提醒控制器清理被删除對象擁有的資源。

當你試圖删除命名空間資源時,處理删除請求的API服務會注意到finalizers 中字段中的值,并做如下操作:

  • • 修改對象以添加一個 metadata.deletionTimestamp 字段,其中包含開始删除的時間。
  • • 阻止對象被删除直至 metadata.finalizers 字段為空
  • • 傳回 202 狀态碼(HTTP “Accepted”)

我的下一個自然反應是通過手動将 finalizers 字段設定為空清單來修複問題:

kubectl patch ns/cdi -p '{"metadata":{"finalizers":[]}}' --type=merge
namespace/cdi patched           

Welp !這也無濟于事。命名空間仍然停留在 terminating 狀态。

Kubernetes 系列(十八)如何删除卡住的命名空間

然後我想到了我在 CKA 課程中學到的東西!我的意思是,我們都花了很多錢!應該有一個解決問題的方法? 想了想,通過建立一個本地代理伺服器,可以直接與Kubernetes API伺服器通信。

使用 finalize 端點服務

步驟非常簡單,首先使用以下指令擷取資源的JSON定義:

k get ns cdi -o json > cid.json           

打開JSON檔案,從 finalizer 數組中删除kubernetes項,并儲存檔案。

Kubernetes 系列(十八)如何删除卡住的命名空間

現在,我們在機器和Kubernetes API伺服器之間啟動一個代理伺服器或應用程式級網關。該代理将在http://127.0.0.1:8001 上提供服務

在新視窗中鍵入此指令:

k proxy
Starting to serve on 127.0.0.1:8001           

現在我們可以調用Kubernetes API : http://127.0.0.1:8001/api/v1/namespaces/{NAME_OF_STUCKED_NAMESPACE}/finalize 傳入修改的 json檔案,其中的 {NAME_OF_STUCKED_NAMESPACE} 變量替換為實際的命名空間:

curl -k -H "Content-Type: application/json" -X PUT --data-binary @cid.json http://127.0.0.1:8001/api/v1/namespaces/cdi/finalize


{
  "kind": "Namespace",
  "apiVersion": "v1",
  "metadata": {
    "name": "cdi",
    "uid": "6c957c91-1f1a-463f-99fe-04a121c48ec6",
    "resourceVersion": "37800934",
    "creationTimestamp": "2022-07-26T13:04:08Z",
    "deletionTimestamp": "2022-08-11T11:32:26Z",
    "labels": {
      "cdi.kubevirt.io": ""
    },
    "managedFields": [
      {
        "manager": "kubectl-create",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2022-07-26T13:04:08Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {"f:metadata":{"f:labels":{".":{},"f:cdi.kubevirt.io":{}}},"f:status":{"f:phase":{}}}
      },
      {
        "manager": "kube-controller-manager",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2022-08-11T11:32:32Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {"f:status":{"f:conditions":{".":{},"k:{\"type\":\"NamespaceContentRemaining\"}":{".":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"NamespaceDeletionContentFailure\"}":{".":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"NamespaceDeletionDiscoveryFailure\"}":{".":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"NamespaceDeletionGroupVersionParsingFailure\"}":{".":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"NamespaceFinalizersRemaining\"}":{".":{},"f:lastTransitionTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}}}}
      }
    ]
  },
  "spec": {


  },
  "status": {
    "phase": "Terminating",
    "conditions": [
      {
{
        "type": "NamespaceDeletionDiscoveryFailure",
        "status": "True",
        "lastTransitionTime": "2022-08-11T11:32:31Z",
        "reason": "DiscoveryFailed",
        "message": "Discovery failed for some groups, 2 failing: unable to retrieve the complete list of server APIs: subresources.kubevirt.io/v1: the server is currently unable to handle the request, subresources.kubevirt.io/v1alpha3: the server is currently unable to handle the request"
      },
      {
        "type": "NamespaceDeletionGroupVersionParsingFailure",
        "status": "False",
        "lastTransitionTime": "2022-08-11T11:32:32Z",
        "reason": "ParsedGroupVersions",
        "message": "All legacy kube types successfully parsed"
      },
      {
        "type": "NamespaceDeletionContentFailure",
        "status": "False",
        "lastTransitionTime": "2022-08-11T11:32:32Z",
        "reason": "ContentDeleted",
        "message": "All content successfully deleted, may be waiting on finalization"
      },
      {
        "type": "NamespaceContentRemaining",
        "status": "False",
        "lastTransitionTime": "2022-08-11T11:32:32Z",
        "reason": "ContentRemoved",
        "message": "All content successfully removed"
      },
      {
        "type": "NamespaceFinalizersRemaining",
        "status": "False",
        "lastTransitionTime": "2022-08-11T11:32:32Z",
        "reason": "ContentHasNoFinalizers",
        "message": "All content-preserving finalizers finished"
      }
    ]
  }
}           

然後,Boom !!! 命名空間消失了!

Kubernetes 系列(十八)如何删除卡住的命名空間

雖然花了些時間,但是我感覺是這樣的:

Kubernetes 系列(十八)如何删除卡住的命名空間