本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 1.26:非平滑節點關閉功能進入 Beta 階段

Kubernetes v1.24 引入了一個 Alpha 質量的改進實現,用於處理非平穩的節點關閉。在 Kubernetes v1.26 中,此功能進入 Beta 階段。該功能允許有狀態的工作負載在原始節點關閉或處於不可恢復狀態(例如硬體故障或作業系統損壞)後,故障轉移到另一個節點。

Kubernetes 中的節點關閉是什麼?

在 Kubernetes 叢集中,節點可能會關閉。這可能是有計劃地發生,也可能是意外發生。你可能計劃進行安全補丁或核心升級而需要重啟節點,或者它可能因為虛擬機器例項被搶佔而關閉。節點也可能由於硬體故障或軟體問題而關閉。

要觸發節點關閉,你可以在 shell 中執行 shutdownpoweroff 命令,或者物理上按下按鈕來關閉機器電源。

如果節點在關閉前沒有被排空(drain),節點關閉可能導致工作負載失敗。

下面,我們將描述什麼是平穩節點關閉和什麼是非平穩節點關閉。

什麼是平穩節點關閉?

kubelet 對平穩節點關閉的處理,允許 kubelet 檢測到節點關閉事件,正確地終止該節點上的 Pod,並在實際關閉前釋放資源。關鍵 Pod 在所有常規 Pod 終止後才會被終止,以確保應用程式的基本功能可以儘可能長時間地工作。

什麼是非平穩節點關閉?

只有當 kubelet 的節點關閉管理器能夠檢測到即將發生的節點關閉操作時,節點關閉才能是平穩的。然而,在某些情況下,kubelet 無法檢測到節點關閉操作。這可能是因為 shutdown 命令沒有觸發 kubelet 在 Linux 上使用的抑制鎖(Inhibitor Locks)機制,或者因為使用者錯誤。例如,如果該節點的 shutdownGracePeriodshutdownGracePeriodCriticalPods 詳細資訊配置不正確。

當一個節點關閉(或崩潰),並且該關閉沒有被 kubelet 節點關閉管理器檢測到時,它就成為了一次非平穩節點關閉。非平穩節點關閉對於有狀態應用來說是個問題。如果一個包含 StatefulSet 一部分 Pod 的節點以非平穩方式關閉,該 Pod 將無限期地卡在 Terminating 狀態,並且控制平面無法在健康的節點上為該 StatefulSet 建立一個替代 Pod。你可以手動刪除失敗的 Pod,但這對於一個自我修復的叢集來說並不理想。同樣,由 Deployment 建立的 ReplicaSet 的 Pod 也會卡在 Terminating 狀態,並且那些繫結到已關閉節點的 Pod 會無限期地保持 Terminating 狀態。如果你設定了水平擴充套件限制,即使是那些正在終止的 Pod 也會計入限制,因此如果你的工作負載已經達到最大規模,它可能會難以自我修復。(順便說一句:如果那個非平穩關閉的節點重新啟動,kubelet 會刪除舊的 Pod,控制平面可以建立一個替代的。)

Beta 版本有什麼新功能?

對於 Kubernetes v1.26,非平穩節點關閉功能是 Beta 版,並預設啟用。NodeOutOfServiceVolumeDetach 特性門控kube-controller-manager 上預設啟用,而不再是可選加入;如果需要,你仍然可以停用它(也請提交一個 issue 來說明問題)。

在監控方面,kube-controller-manager 報告了兩個新的度量指標。

force_delete_pods_total
被強制刪除的 pod 數量(Pod 垃圾回收控制器重啟時重置)
force_delete_pod_errors_total
嘗試強制刪除 Pod 時遇到的錯誤數量(Pod 垃圾回收控制器重啟時也重置)

它是如何工作的?

在節點關閉的情況下,如果平穩關閉不起作用或由於硬體故障或作業系統損壞,節點處於不可恢復狀態,你可以手動在節點上新增一個 out-of-service 汙點。例如,這可以是 node.kubernetes.io/out-of-service=nodeshutdown:NoExecutenode.kubernetes.io/out-of-service=nodeshutdown:NoSchedule。如果 pod 上沒有匹配的容忍度,這個汙點會觸發節點上的 pod 被強制刪除。附加到關閉節點的持久卷將被分離,新的 pod 將在另一個執行中的節點上成功建立。

kubectl taint nodes <node-name> node.kubernetes.io/out-of-service=nodeshutdown:NoExecute

注意:在應用 out-of-service 汙點之前,你必須確認節點已經處於關閉或斷電狀態(而不是正在重啟中),無論是使用者有意關閉它,還是由於硬體故障、作業系統問題等導致節點宕機。

一旦所有連結到 out-of-service 節點的工作負載 pod 都移動到了一個新的執行節點,並且關閉的節點已經恢復,你應該在節點恢復後移除該受影響節點上的汙點。

下一步是什麼?

根據反饋和採用情況,Kubernetes 團隊計劃在 1.27 或 1.28 版本中將非平穩節點關閉的實現推向 GA(正式釋出)。

此功能要求使用者手動向節點新增汙點以觸發工作負載的故障轉移,並在節點恢復後移除汙點。

叢集操作員可以透過自動應用 out-of-service 汙點來自動化這個過程,前提是有一種程式化的方式來確定節點確實已經關閉,並且節點與儲存之間沒有 IO。然後,叢集操作員可以在工作負載成功故障轉移到另一個執行節點並且關閉的節點已經恢復後,自動移除該汙點。

在未來,我們計劃尋找方法來自動檢測和隔離已關閉或處於不可恢復狀態的節點,並將其工作負載故障轉移到另一個節點。

我如何瞭解更多資訊?

要了解更多資訊,請閱讀 Kubernetes 文件中的非平穩節點關閉

如何參與?

我們非常感謝所有幫助設計、實現和審查此功能的貢獻者

在整個過程中,有很多人幫助審查了設計和實現。我們要感謝所有為這項工作做出貢獻的人,包括在過去幾年裡審查了KEP和實現的大約 30 人。

此功能是 SIG Storage 和 SIG Node 之間的合作。對於有興趣參與 Kubernetes 儲存系統任何部分的設計和開發的人,請加入 Kubernetes 儲存特別興趣小組(SIG)。對於有興趣參與支援 Pod 和主機資源之間受控互動的元件的設計和開發的人,請加入 Kubernetes Node SIG。