Kubernetes:刪除 Resource Objects



前言

  • 管理 Kubernetes 的時候不時需要刪除一些資源;大部分的情況下可以輕鬆刪除,但偶而會 hang 住。
  • 都先假設已經有裝 kubectl
  • 文中的 resource object 包含 pod, service, statefulset 等



說明

一般刪除方式

1
2
3
4
kubectl delete <resource_object>

# namespaced
kubectl delete <resource_object> -n <namespace>

強迫刪除

  • 有些狀況下,刪除的處理時間會過久,主要是看 [finalizer](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/) 到底在做什麼
  • 如果真的卡住、想強迫刪除資源:
1
2
3
4
5
6
7
8
9
kubectl delete <resource_object> -n <namespace> --force --grace-periods=0


# example
kubectl delete pod --force --grace-periods=0
kubectl delete pod -n myapp --force --grace-periods=0

kubectl delete statefulset --force --grace-periods=0
kubectl delete statefulset -n myapp --force --grace-periods=0

kubectl 版本如果小於 1.4,就不需要 --force flag:

kubectl delete <resource_object> -n <namespace> --grace-periods=0

強迫刪除 namespace

  • 預設是無法強迫刪除 namespace 的,即使給了 --grace-periods=0 也是一樣。
  • 這時候要:

手動方法:

  1. 手動 get 並存成 json
  2. 清空 yaml 檔中的 finalizer
  3. kubectl replace 通知 apiserver
1
2
# output 成 json
kubectl get ns <namespace> -o json > tmp.json
1
2
# 編輯 json
vim tmp.json

像是這樣

1
2
3
4
5
6
{
  "spec": {
    "finalizers": [
    ]
  }
}

然後 replace 套用:

1
2
# replace 讓 api 知道並生效
kubectl replace --raw "/api/v1/namespaces/<namespace>/finalize" -f ./tmp.json

快速方法

快速方法 - jq

1
2
3
4
5
6
# 設定變數
NAMESPACE=<namespace>

kubectl get ns ${NAMESPACE} -o json | jq 'del(.spec.finalizers[])' > ./tmp.json
kubectl replace --raw "/api/v1/namespaces/${NAMESPACE}/finalize" -f ./tmp.json
rm -f ./tmp.json
  • jq 沒有支援直接更新原檔的參數 (類似 sed -i),所以要自行替換檔案

快速方法 - 如果沒有 jq

如果沒有 jq、或是不方便安裝的話,就只好用 sed 了:

假設你的 namespace 是 my_namespace

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
export TMP_NAMESPACE=my_namespace

echo '{
    "apiVersion": "v1",
    "kind": "Namespace",
    "metadata": {
        "name": "_target_replace_ns_"
    },
    "spec": {
        "finalizers": [
        ]
    }
}' | sed "s/_target_replace_ns_/${TMP_NAMESPACE}/g" \
   | kubectl replace --raw "/api/v1/namespaces/${TMP_NAMESPACE}/finalize" -f -

unset TMP_NAMESPACE
  • (像我) 懶得產生 JSON 檔的話,可以用這樣 echo 的方式;如果有檔案的話,就把最後的 -f - 換成檔案路徑 -f <file>.json 即可
  • export 是為了方便後續的 sed 取用變數。

包成函數,方便需要重複使用的情境:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
force_delete_namespace () {
    export TMP_NAMESPACE=$1

    echo '{
        "apiVersion": "v1",
        "kind": "Namespace",
        "metadata": {
            "name": "_target_replace_ns_"
        },
        "spec": {
            "finalizers": [
            ]
        }
    }' | sed "s/_target_replace_ns_/${TMP_NAMESPACE}/g" \
       | kubectl replace --raw "/api/v1/namespaces/${TMP_NAMESPACE}/finalize" -f -
    
    unset TMP_NAMESPACE
}

然後就可以用 for loop 批次處理,像是:

1
2
3
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
    force_delete_namespace ${ns}
done

Note

  1. 強迫刪除 namespace 之前,如果確定該 namespace 底下的資源都要刪除,可以先
1
kubectl delete all --all -n <namespace>



REF


主題 StackJimmy 設計