K8s Resources Remove Procedure
說明 Kubernetes Finalizer 的作用、手動刪除資源造成殘留的情境,以及正確的資源與 namespace 移除流程。
前情提要:Finalizer 是什麼
- 是 Kubernetes 設置在資源上的一種「刪除前必須操作」機制。
- 有 Finalizer 的資源,Kubernetes 不會直接刪除,而是等待 Finalizer 執行完成,由 controller 清理相關資源,然後移除 Finalizer,最終刪除資源。
出錯情境
- 刪 kube-prometheus-stack 時,Prometheus 的 CR (如 Prometheus / Alertmanager / ThanosRuler) 上還有 Finalizer,但是相關的 StatefulSet / Deployment 資源已被我手動先行刪除。
- 後果:CR 的 Finalizer 未能正常完成,導致系統無法 finalize 資源,就會有残留的 Pod 存在,而其 owner (StatefulSet) 已絕緣,GC 無法自動刪 Pod。
原文情境
根據最之初提供的 Reddit 文:
- Kubernetes 刪 namespace 時,會執行全套資源檢查與削除流程,包括 Finalizer 處理。
- 如果遇到 stuck (Terminating 狀態不能解除),不應該直接 patch 刪掉 Finalizer,而應該看
describe ns說明原因,並解決根本問題(例如刪掉已失效的 APIService)。 - 直接 patch Finalizer 會造成剩餘的 orphaned resources,需找出所有已絕緣的資源,並手動刪除。
正確移除流程
-
先不要動手 patch Finalizer!
-
kubectl describe ns <namespace>查看 stuck 原因,確認是哪個資源止住了流程? -
處理根因(刪掉失效或異常資源):
kubectl delete apiservices.apiregistration.k8s.io <example.com> -
確認所有子資源正常被清除。
-
等 Kubernetes 自動 finalize namespace,如果已清理完,就會正常消失;否則才考慮手動消除。
若已發生錯誤 finalize,如何清理?
- 使用下列 script 檢索 cluster 裡所有 orphaned resources,並手動把這些資源刪除:
#!/bin/bash
current_namespaces=($(kubectl get ns --no-headers | awk '{print $1}'))
api_resources=($(kubectl api-resources --verbs=list --namespaced -o name))
for api_resource in ${api_resources[@]}; do
while IFS= read -r line; do
resource_namespace=$(echo $line | awk '{print $1}')
resource_name=$(echo $line | awk '{print $2}')
if [[ ! " ${current_namespaces[@]} " =~ " $resource_namespace " ]]; then
echo "api-resource: ${api_resource} - namespace: ${resource_namespace} - resource name: ${resource_name}"
fi
done < <(kubectl get $api_resource -A --ignore-not-found --no-headers -o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name")
done
結論
Kubernetes 資源移除時,應按正規流程註意 Finalizer,先處理問題,再等待系統清理完成,避免使系統歷史紀錄與資源綁緣錯亂,別輕易直接打斷 Finalizer 流程!