天天看點

K8s無法删除狀态為terminating的pod解決方法

作者:藍中科技

1. pod删除

K8s無法删除狀态為terminating的pod解決方法

每當删除namespace或pod 等一些Kubernetes資源時,有時資源狀态會卡在terminating,很長時間無法删除,甚至有時增加--force flag(強制删除)之後還是無法正常删除。這時就需要edit該資源,将字段finalizers設定為null,之後Kubernetes資源就正常删除了。

當删除pod時有時會卡住,pod狀态變為terminating,無法删除pod

(1)強制删除

kubectl delete pod xxx -n xxx --force --grace-period=0           

(2)如果強制删除還不行,設定finalizers為空

(如果一個容器已經在運作,這時需要對一些容器屬性進行修改,又不想删除容器,或不友善通過replace的方式進行更新。kubernetes還提供了一種在容器運作時,直接對容器進行修改的方式,就是patch指令。)

kubectl patch pod xxx -n xxx -p '{"metadata":{"finalizers":null}}'           

這樣pod就可以删除了。

推薦内容

2. k8s删除流程

基本的delete指令狀态圖:

K8s無法删除狀态為terminating的pod解決方法

盡管此操作很簡單,但其他因素可能會幹擾删除,包括finalizers和owner references。

K8s 中對象删除基本流程如下:

(1)用戶端送出删除請求到 API Server(可選傳遞 GracePeriodSeconds 參數)

(2)API Server 做 Graceful Deletion 檢查(若對象實作了 RESTGracefulDeleteStrategy 接口,會調用對應的實作并傳回是否需要進行 Graceful 删除)

(3)API Server 檢查 Finalizers 并結合是否需要進行 graceful 删除,來決定是否立即删除對象(若對象需要進行 graceful 删除,更新 metadata.DeletionGracePeriodSecond 和metadata.DeletionTimestamp 字段,不從存儲中删除對象;若對象不需要進行 Graceful 删除時

:metadata.Finalizers 為空,直接删除。metadata.Finalizers 不為空,不删除,隻更新 metadata.DeletionTimestamp。

2.1 finalizers介紹

Finalizers 字段屬于 Kubernetes GC 垃圾收集器,是一種删除攔截機制,能夠讓控制器實作異步的删除前(Pre-delete)回調。其存在于任何一個資源對象的 Meta中,在 k8s 源碼中聲明為 []string,該 Slice 的内容為需要執行的攔截器名稱。

常見用途:

(1)控制器在對象剛建立時,在 metadata.finalizers 寫入一個自定義字元串

(2)APIServer 在 metadata.finalizers 數組不為空時,不會删除對象。此邏輯是硬性,對所有對象生效。

(3)當有用戶端删除對象時,控制器可以發現對象出于删除狀态,然後執行相應的 pre-delete 邏輯。執行完成後,将之前寫入的自定義字元串移除。

(4)當所有控制器都将各自寫入到 metadata.finalizers 的字元串移除後。API Server 就自動将對象删除。

注:若對象同時實作了 graceful 删除政策,删除請求需要滿足 GracefulPeriodSeconds = 0 條件

2.2 Graceful Deletion

K8s無法删除狀态為terminating的pod解決方法

APIServer 在處理 Pod 删除請求時,會根據 pod 的 pod.Spec.TerminationGracePeriodSeconds 和 deleteOptions.GracefulPeriodSeconds 綜合判斷,是否進行 Graceful 删除。若是,并判斷最終的 GracefulPeriodSeconds 該設定為多少。

(1)當删除請求選項中有設定 GracefulPeriodSeconds,以選項中為準。若沒有,使用 pod.Spec.TerminationGracePeriodSeconds 。若 pod.Spec.TerminationGracePeriodSeconds 也沒有設定,使用預設值 0 。

(2)當 Pod 沒有排程,或者已經結束(無論成功還是失敗)。GracePeriodSeconds 都重置為 0.

GracePeriodSeconds 為 0 表示不進行優雅删除。非 0 表示進行優雅删除。Pod 的預設優雅删除時間為 30 s ,在對象建立時配置在 pod.Spec.TerminationGracePeriodSeconds 字段。

優雅删除的目的是給予 Kubelet 一定時間對 Pod 實行優雅退出。在使用者對 Pod 執行 Delete 操作時,Pod 對象不會立即從 API Server 删除,而隻是進入 Termination 階段。Kubelet 會對運作中的 Pod 的容器發送 TERM 信号,通知其退出。并執行使用者配置的 preStop hooks 邏輯。當優雅時間過了之後,再開始使用 KILL 信号嘗試強制殺容器。

當 kubelet 将 Pod 清理幹淨後,就會使用 GracefulPeriodSeconds==0 的參數執行删除操作。

因為 Pod 實作優雅删除目的是為了給予 Kubelet 時間做資源清理操作,是以這也是為什麼在設定 GracePeriodSeconds 階段,若 Pod 沒有被排程或者已經退出,也就可以直接允許立即删除 (GracePeriodSeconds = 0)。

注:

  • 了解該流程可以結合 Kubernetes 官網的 Pod Termination 說明:https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods
  • 對象第一次執行優雅删除操作時,會将當時 GracefulPeriodSeconds 配置在 metadata.DeletionGracefulPeriodSeconds 字段。
  • Deletion 操作在 API Server 是不可回退的操作。metadata.DeletionTimestamp 設定後不可更改,metadata.DeletionGracefulPeriodSeconds 隻能減小,不能增加。

2.3對象無法删除的原因

在了解以上機制後,對象無法删除無外乎以下兩個原因:

  • 對象存在 finalizers,關聯的控制器故障未能執行或執行 finalizer 函數卡住比如namespace控制器無法删除完空間内所有的對象,特别是在使用 aggregated apiserver 時,第三方 apiserver 服務故障導緻無法删除其對象。此時,需要會恢複第三方 apiserver 服務或移除該 apiserver 的聚合,具體選擇哪種方案需根據實際情況而定。叢集内安裝的控制器給一些對象增加了自定義 finalizers ,未删除完 fianlizers 就下線了該控制器,導緻這些 fianlizers 沒有控制器來移除他們。此時,需要恢複該控制器會手動移除 finalizers,具體選擇哪種方案根據實際情況而定。
  • 對象需要優雅删除,但執行者不能完成删除。比如 Pod 因為 kubelet 無法下線節點上 node 容器、存儲卷而無法删除。比較常見有以下原因:kubelet 無法通過 container runtime 殺死程序。比如程序進入 D (Uninterruptible) 狀态,container runtime 或操作核心遇到 bug 等。對于程序進入 D 狀态,若能恢複照成 D 的故障,比如恢複關聯的外設通路等,能解決問題。若不能,或者是因為後者核心 bug,一般并不能走正常流程讓 kubelet 殺死程序。一般需要重新開機作業系統才能解決。kubelet 程序停止或者 node 失去聯系。 該情況下,并沒有 kubelet 運作或者運作中的 kubelet 與 apiserver 已經斷開,無法收到 pod 需要删除下線的消息。是以,沒有執行者來進行優雅删除。該情況下,需要恢複節點以及 kubelet 的運作即可。

兩種機制都有強制跳過的方案:

  • 删除 finalizers ,讓關聯的邏輯不需要執行
  • kubelet delete --force --grace-period 0 直接删除

但應僅當關聯清理工作已經不重要或已手動執行時,才可選擇。不然容易照成資料、狀态不一緻等。

繼續閱讀