導航帶裝置的 Pod 中的故障
Kubernetes 是容器編排的事實標準,但在處理 GPU 和其他加速器等專用硬體時,事情會變得有點複雜。這篇博文深入探討了在 Kubernetes 中操作帶有裝置的 Pod 時管理故障模式的挑戰,基於 Sergey Kanzhelev 和 Mrunal Patel 在 KubeCon NA 2024 上的演講的見解。您可以點選以下連結檢視幻燈片和錄音。
AI/ML 繁榮及其對 Kubernetes 的影響
AI/ML 工作負載的興起給 Kubernetes 帶來了新的挑戰。這些工作負載通常嚴重依賴專用硬體,任何裝置故障都可能顯著影響效能並導致令人沮喪的中斷。正如 2024 年 Llama 論文所強調的那樣,硬體問題,特別是 GPU 故障,是 AI/ML 訓練中斷的主要原因。您還可以透過 Ryan Hallisey 和 Piotr Prokop 的 KubeCon 演講“您的所有 GPU 都屬於我們:NVIDIA 自愈 GeForce NOW 基礎設施的內部探秘”(錄音)瞭解 NVIDIA 在處理裝置故障和維護方面付出了多少努力,因為他們每天每 1000 個節點就會收到 19 個修復請求!我們還看到資料中心提供現貨消費模型和電力超額分配,這使得裝置故障變得司空見慣,成為商業模式的一部分。
然而,Kubernetes 對資源的看法仍然非常靜態。資源要麼存在,要麼不存在。如果存在,則假定它將保持完全正常執行——Kubernetes 缺乏對處理完全或部分硬體故障的良好支援。這些長期存在的假設加上設定的整體複雜性導致了各種故障模式,我們在此討論。
瞭解 AI/ML 工作負載
通常,所有 AI/ML 工作負載都需要專用硬體,具有挑戰性的排程要求,並且在空閒時成本高昂。AI/ML 工作負載通常分為兩類——訓練和推理。以下是對這些類別特徵的過度簡化檢視,它們與 Web 服務等傳統工作負載不同
- 培訓
- 這些工作負載是資源密集型的,通常會佔用整個機器並作為一組 Pod 執行。訓練作業通常是“執行完成”——但這可能需要數天、數週甚至數月。單個 Pod 中的任何故障都可能需要重新啟動所有 Pod 的整個步驟。
- 推理
- 這些工作負載通常是長期執行或無限期執行的,並且可以小到消耗節點裝置的一個子集,也可以大到跨多個節點。它們通常需要下載包含模型權重的巨大檔案。
這些工作負載型別特別打破了許多過去的假設
過去 | 現在 |
---|---|
可以獲得更好的 CPU,應用程式將執行得更快。 | 需要一個特定的裝置(或一類裝置)才能執行。 |
當出現問題時,只需重新建立它。 | 分配或重新分配成本高昂。 |
任何節點都可以工作。Pod 之間無需協調。 | 以特殊方式排程——裝置通常以跨節點拓撲連線。 |
每個 Pod 如果失敗都可以即插即用地替換。 | Pod 是更大任務的一部分。整個任務的生命週期取決於每個 Pod。 |
容器映象輕巧且易於獲取。 | 容器映象可能非常大,需要特殊處理。 |
漫長的初始化可以透過緩慢的推出抵消。 | 初始化可能很漫長,應該進行最佳化,有時是許多 Pod 同時進行。 |
計算節點商品化且相對便宜,因此一些空閒時間是可以接受的。 | 帶有專用硬體的節點可能比沒有專用硬體的節點貴一個數量級,因此空閒時間非常浪費。 |
現有的故障模型依賴於舊的假設。它可能仍然適用於新的工作負載型別,但它對裝置的瞭解有限,並且對它們來說非常昂貴。在某些情況下,甚至貴得令人望而卻步。您將在本文後面看到更多示例。
為什麼 Kubernetes 仍然至高無上
本文不深入探討以下問題:為什麼不為
AI/ML 工作負載從頭開始,因為它們與傳統的 Kubernetes 工作負載如此不同。儘管面臨諸多挑戰,Kubernetes 仍然是 AI/ML 工作負載的首選平臺。其成熟度、安全性和豐富的工具生態系統使其成為一個引人注目的選擇。雖然存在替代方案,但它們通常缺乏 Kubernetes 提供的多年開發和完善。Kubernetes 開發人員正在積極解決本文及其他地方發現的差距。
裝置故障處理的現狀
本節概述了不同的故障模式以及當今使用的最佳實踐和 DIY(自己動手)解決方案。下一節將描述改進這些故障模式的路線圖。
故障模式:K8s 基礎設施
為了瞭解與 Kubernetes 基礎設施相關的故障,您需要了解將 Pod 排程到節點上涉及多少個移動部件。當 Pod 排程到節點上時,事件序列如下
- 裝置外掛排程到節點上
- 裝置外掛透過本地 gRPC 註冊到 kubelet
- Kubelet 使用裝置外掛監視裝置並更新節點的容量
- 排程器根據更新後的容量將使用者 Pod 放置到節點上
- Kubelet 要求裝置外掛為使用者 Pod 分配裝置
- Kubelet 建立一個使用者 Pod,並將分配的裝置附加到它
此圖顯示了其中一些涉及的參與者
由於存在如此多的相互關聯的參與者,它們中的每一個以及每個連線都可能遇到中斷。這會導致許多通常被認為是故障的異常情況,並可能導致嚴重的工作負載中斷
- Pod 在其生命週期的各個階段拒絕准入
- Pod 無法在完全正常的硬體上執行
- 排程耗時出乎意料的長
Kubernetes 的目標是使這些元件之間的中斷儘可能可靠。Kubelet 已經實現了重試、寬限期和其他技術來改進它。路線圖部分詳細介紹了 Kubernetes 專案跟蹤的其他邊緣情況。然而,所有這些改進只有在遵循這些最佳實踐時才有效
- 儘早配置並重新啟動 kubelet 和容器執行時(如 containerd 或 CRI-O),以免中斷工作負載。
- 監控裝置外掛健康狀況並仔細規劃升級。
- 不要用不重要的工作負載使節點超載,以防止裝置外掛和其他元件中斷。
- 配置使用者 Pod 容忍度以處理節點就緒性閃爍。
- 仔細配置和編寫優雅終止邏輯,以免長時間阻塞裝置。
另一類與 Kubernetes 基礎設施相關的問題是驅動程式相關問題。對於 CPU 和記憶體等傳統資源,無需在應用程式和硬體之間進行相容性檢查。對於硬體加速器等特殊裝置,存在新的故障模式。節點上安裝的裝置驅動程式
- 必須與硬體匹配
- 與應用程式相容
- 必須與其他驅動程式(如 nccl 等)一起工作
處理驅動程式版本的最佳實踐
- 監控驅動程式安裝程式健康狀況
- 規劃基礎設施和 Pod 的升級以匹配版本
- 儘可能進行金絲雀部署
遵循本節中的最佳實踐並使用來自受信任和可靠來源的裝置外掛和裝置驅動程式安裝程式通常可以消除此類故障。Kubernetes 正在跟蹤工作以使這一領域變得更好。
故障模式:裝置故障
Kubernetes 目前對裝置故障的處理很少。裝置外掛僅透過更改可分配裝置的數量來報告裝置故障。Kubernetes 依靠活性探針或容器故障等標準機制,讓 Pod 將故障情況傳達給 kubelet。然而,Kubernetes 不會將裝置故障與容器崩潰相關聯,除了在連線到同一裝置時重新啟動容器外,不提供任何緩解措施。
這就是為什麼存在許多外掛和 DIY 解決方案來根據各種訊號處理裝置故障。
健康控制器
在許多情況下,裝置故障將導致無法恢復且非常昂貴的節點處於空閒狀態。一個簡單的 DIY 解決方案是節點健康控制器。該控制器可以比較裝置的分配計數和容量,如果容量更大,則啟動一個計時器。一旦計時器達到閾值,健康控制器將終止並重新建立節點。
健康控制器方法存在問題
- 通常不知道裝置故障的根本原因
- 控制器不瞭解工作負載
- 故障裝置可能未使用,您希望保持其他裝置執行
- 由於它非常通用,檢測可能太慢
- 節點可能是更大節點集的一部分,不能在沒有其他節點的情況下單獨刪除
存在解決上述部分問題的健康控制器變體。這裡的主題是,為了最好地處理故障裝置,您需要針對特定工作負載進行定製處理。Kubernetes 尚未提供足夠的抽象來表達裝置對節點、叢集以及它所分配的 Pod 的重要性。
Pod 故障策略
另一種處理裝置故障的 DIY 方法是針對故障裝置進行逐個 Pod 的反應。此方法適用於實現為作業的訓練工作負載。
Pod 可以為裝置故障定義特殊的錯誤程式碼。例如,每當遇到意外裝置行為時,Pod 會以特殊的退出程式碼退出。然後,Pod 故障策略可以以特殊方式處理裝置故障。閱讀更多關於 使用 Pod 故障策略處理可重試和不可重試的 Pod 故障
作業的Pod 故障策略方法存在一些問題
- 沒有眾所周知的裝置故障條件,因此此方法不適用於通用 Pod 情況
- 錯誤程式碼必須仔細編寫,在某些情況下很難保證。
- 由於 Pod 故障策略功能的限制,僅適用於帶有
restartPolicy: Never
的作業。
因此,此解決方案的適用性有限。
自定義 Pod 觀察器
一個更通用的方法是實現 Pod 觀察器作為 DIY 解決方案,或使用提供此功能的第三方工具。Pod 觀察器最常用於處理推理工作負載的裝置故障。
由於 Kubernetes 只是將 Pod 分配給裝置,即使裝置據報道不健康,其想法是使用 Pod 觀察器檢測這種情況並應用一些修復。它通常涉及獲取裝置健康狀態及其使用節點上的 Pod 資源 API 到 Pod 的對映。如果裝置故障,它可以刪除附加的 Pod 作為修復措施。副本集將處理健康裝置上的 Pod 重新建立。
實現此觀察器的其他原因
- 沒有它,Pod 將永遠保持分配給故障裝置。
- 對於帶有
restartPolicy=Always
的 Pod,沒有排程。 - 沒有內建控制器會刪除 CrashLoopBackoff 中的 Pod。
自定義 Pod 觀察器的問題
- 獲取 Pod 觀察器的訊號成本高昂,並且涉及一些特權操作。
- 它是一個自定義解決方案,它假設裝置對 Pod 的重要性。
- Pod 觀察器依賴外部控制器重新排程 Pod。
還有更多處理裝置故障或即將維護的 DIY 解決方案變體。總的來說,Kubernetes 有足夠的擴充套件點來實現這些解決方案。然而,一些擴充套件點需要比使用者可能習慣的更高許可權或破壞性太大。路線圖部分詳細介紹了處理裝置故障的具體改進。
故障模式:容器程式碼故障
當容器程式碼失敗或發生記憶體不足等問題時,Kubernetes 知道如何處理這些情況。要麼重新啟動容器,要麼如果 Pod 具有 restartPolicy: Never
,則 Pod 崩潰並將其排程到另一個節點上。Kubernetes 對什麼是故障(例如,非零退出程式碼或活性探針失敗)以及如何對這種故障做出反應(主要是始終重新啟動或立即使 Pod 失敗)的表達能力有限。
這種表達能力通常不足以應對複雜的 AI/ML 工作負載。AI/ML Pod 最好在本地甚至就地重新排程,因為這樣可以節省映象拉取時間和裝置分配。AI/ML Pod 通常相互連線,需要一起重新啟動。這增加了另一個複雜性級別,最佳化它通常可以為執行 AI/ML 工作負載帶來巨大的節省。
有各種 DIY 解決方案來處理 Pod 故障編排。最典型的方法是使用一些編排器將主可執行檔案包裝在容器中。當由於某個其他 Pod 失敗而需要重新啟動作業時,此編排器將能夠重新啟動主可執行檔案。
像這樣的解決方案非常脆弱且複雜。當用於大型訓練作業時,與常規 JobSet 刪除/重新建立週期相比,它們通常值得節省的資金。透過在 Kubernetes 中開發新的鉤子和擴充套件點,使這些解決方案不那麼脆弱且更簡化,將使其易於應用於較小的作業,從而使所有人受益。
故障模式:裝置降級
並非所有裝置故障都對整體工作負載或批處理作業是致命的。隨著硬體堆疊變得越來越複雜,硬體堆疊層之一的配置錯誤或驅動程式故障可能導致裝置功能正常,但效能滯後。一個滯後的裝置會減慢整個訓練作業。
我們看到此類案例的報告越來越多。Kubernetes 今天無法表達此類故障,並且由於它是最新型別的故障模式,硬體供應商沒有提供太多用於檢測的最佳實踐,也沒有第三方工具用於修復這些情況。
通常,這些故障是根據觀察到的工作負載特徵檢測的。例如,AI/ML 訓練步驟在特定硬體上的預期速度。這些問題的補救措施高度依賴於工作負載需求。
路線圖
如上文所述,Kubernetes 提供了許多擴充套件點,用於實現各種 DIY 解決方案。AI/ML 領域發展迅速,需求和使用模式不斷變化。SIG Node 正在採取一種有節制的方法,透過啟用更多擴充套件點來實現特定於工作負載的場景,而不是引入新的語義來支援特定場景。這意味著優先提供有關故障的資訊,而不是為那些可能只適用於部分工作負載的故障實施自動修復。
這種方法確保工作負載處理沒有劇烈變化,這可能會破壞現有、執行良好的 DIY 解決方案或現有更傳統工作負載的體驗。
當今使用的許多錯誤處理技術適用於 AI/ML,但成本高昂。SIG Node 將投資於擴充套件點,以降低這些成本,並認識到 AI/ML 的降價至關重要。
以下是我們為各種故障模式設想的一系列具體投資。
故障模式路線圖:K8s 基礎設施
Kubernetes 基礎設施領域最容易理解,並且對於即將到來的從裝置外掛到 DRA 的過渡非常重要。SIG Node 正在跟蹤該領域的許多工作項,其中最值得注意的是以下幾項
- 整合 kubelet 與 systemd 看門狗 · Issue #127460
- DRA:檢測過時的 DRA 外掛套接字 · Issue #128696
- 支援裝置管理器/裝置外掛的接管 · Issue #127803
- Kubelet 外掛註冊可靠性 · Issue #127457
- 如果失敗,重新建立裝置管理器 gRPC 伺服器 · Issue #128167
- 在裝置外掛 gRPC 失敗時重試 Pod 准入 · Issue #128043
基本上,Kubernetes 元件的每次互動都必須透過 kubelet 改進或外掛開發和部署中的最佳實踐來實現可靠性。
故障模式路線圖:裝置故障
對於裝置故障,在 Kubernetes 可以支援的常見場景中已經出現了一些模式。然而,第一步是更輕鬆地獲取有關故障裝置的資訊。這裡的第一步是 KEP 4680 中的工作(將資源健康狀態新增到裝置外掛和 DRA 的 Pod 狀態)。
更長期的想法包括待測試
- 將裝置故障整合到 Pod 故障策略中。
- 節點本地重試策略,為帶有 restartPolicy=OnFailure 的 Pod 啟用 Pod 故障策略,並可能超出此範圍。
- 能夠取消排程 Pod,包括帶有
restartPolicy: Always
的 Pod,以便它可以獲得新分配的裝置。 - 將裝置健康狀況新增到用於在 DRA 中表示裝置的 ResourceSlice,而不是簡單地從 ResourceSlice 中撤回不健康的裝置。
故障模式路線圖:容器程式碼故障
處理 AI/ML 工作負載容器程式碼故障的主要改進都旨在降低錯誤處理和恢復的成本。成本降低主要來自於儘可能多地重用預分配資源。從就地重新啟動容器以重用 Pod,到儘可能在節點本地重新啟動容器而不是重新排程,再到快照支援,以及重新排程時優先選擇同一節點以節省映象拉取時間。
考慮一下這個場景:一個大型訓練作業需要執行 512 個 Pod。其中一個 Pod 失敗了。這意味著所有 Pod 都需要中斷並同步以重新啟動失敗的步驟。實現這一點的最有效方法通常是就地重新啟動儘可能多的 Pod,同時替換失敗的 Pod 以清除其中的錯誤。如下圖所示
可以實現此場景,但由於 Kubernetes 缺乏某些擴充套件點,所有實現此場景的解決方案都很脆弱。在 Kubernetes 路線圖上,新增這些擴充套件點以實現此場景。
故障模式路線圖:裝置降級
這方面的工作很少——沒有明確的檢測訊號,故障排除工具非常有限,也沒有內建語義來表達 Kubernetes 上的“降級”裝置。曾討論過在 DRA 用於表示裝置的 ResourceSlice 中新增裝置效能或降級資料,但尚未明確定義。還有像 node-healthcheck-operator 這樣的專案可以用於某些場景。
我們期待硬體供應商和雲提供商在這一領域的發展,並且預計在不久的將來會看到主要是 DIY 解決方案。隨著越來越多的使用者接觸到 AI/ML 工作負載,這是一個需要反饋模式的領域。
加入對話
Kubernetes 社群鼓勵反饋和參與塑造裝置故障處理的未來。加入 SIG Node,為正在進行的討論做出貢獻!
這篇博文提供了 Kubernetes 中裝置故障管理面臨的挑戰和未來方向的概要。透過解決這些問題,Kubernetes 可以鞏固其作為 AI/ML 工作負載領先平臺的地位,確保依賴專用硬體的應用程式的彈性和可靠性。