題幹與適用場景
一個多租戶機器學習平台使用 GPU、FPGA 和高速網卡。現有方案透過節點標籤、擴充資源與裝置外掛分配整塊裝置,難以表達裝置屬性、共享容量和租戶隔離。團隊計畫採用 Kubernetes 1.34 中已升級為穩定版的 Dynamic Resource Allocation(DRA)。
請設計從舊方案遷移到 DRA 的系統,並說明 ResourceClaim、DeviceClass、ResourceClaimTemplate、ResourceSlice、驅動和排程器之間的責任邊界。假設叢集需要漸進式遷移,不能一次重啟所有工作負載。
面試官考察點
面試官看重候選人是否把「宣告裝置需求」和「實際分配裝置」分開,能否解釋控制面 API、排程器、節點驅動與 kubelet 的資料流;是否知道 DRA 的 resource.k8s.io/v1 API 穩定不代表所有驅動能力都穩定。
強回答還會處理容量共享、跨命名空間引用、驅動不可用、Pod 重建、舊工作負載共存、最小權限和回滾指標,而不是只列出資源物件。
回答前需要釐清的問題
- 裝置需求是整卡、可切分容量,還是按屬性選取任意裝置?
- 裝置驅動是否支援 DRA,能否同時執行舊裝置外掛?
- ResourceClaim 的生命週期由工作負載建立,還是由平台範本產生?
- 租戶是否允許跨命名空間重用 Claim,哪些物件由平台控制器寫入?
- 遷移期間要保持 GPU 工作連續性、排程吞吐還是資源利用率?
30 秒回答框架
「我會先把裝置需求建模成 Claim,再讓驅動負責裝置發現、分配和節點設定,排程器只根據 ResourceSlice 和 Claim 的宣告做可行性判斷。先以獨立命名空間和少量裝置類別灰度,舊裝置外掛與 DRA 並存但不讓同一裝置被兩套控制面管理。每階段都驗證 Claim 狀態、Pod 綁定、節點可見性、驅動錯誤、分配延遲和租戶邊界;發現分配錯誤就停止新 Claim,保留執行中工作並讓新工作負載回到舊路徑。」
分步驟深入解答
先畫出 DRA 資料流
工作負載透過 Pod 的 resourceClaims 引用 Claim。Claim 可以由使用者直接建立,也可以由 ResourceClaimTemplate 為 Job 或其他控制器產生。DeviceClass 描述可選取的裝置類別,ResourceSlice 由驅動發布節點上的裝置和屬性。排程器結合 Pod、Claim、DeviceClass 和 ResourceSlice 選擇節點;節點側驅動隨後完成具體分配和設定。
這條鏈路把「選哪個裝置」從應用 YAML 抽離,避免平台把硬體拓撲編碼成標籤慣例。
設計 Claim 範本與租戶邊界
範本只暴露租戶需要的參數,例如顯存檔位、互連類型或網路頻寬,不讓租戶直接寫入驅動內部識別碼。平台控制器為每個命名空間設定准入策略、配額和生命週期清理;跨命名空間 Claim 必須有明確引用權限和稽核事件。刪除租戶時先停止新 Claim,再等待 Pod 釋放,最後回收裝置狀態。
處理整卡與可共享容量
整卡分配可以把一個 DeviceRequest 對應到一個裝置。若要共享顯存、頻寬或時間片,需要驅動發布容量並啟用對應的 DRA consumable capacity 能力;不能只在排程器標籤上模擬共享,否則排程成功後可能在節點超賣。容量模型應定義單位、並發上限、回收時機和碎片化策略。
與舊裝置外掛並存
遷移階段按裝置類別或節點池切分,不讓舊外掛和 DRA 同時宣告同一硬體。舊工作負載繼續使用擴充資源,新工作負載引用 DRA Claim;節點池標籤只做遷移邊界,不作為最終裝置屬性來源。每個池都要有清晰的所有權和停用開關,避免驅動重複初始化。
處理排程、搶佔與失敗
Claim 處於等待或分配失敗時,Pod 應保持可解釋的 Pending 原因。排程器選中節點不等於裝置已可用;驅動可能在節點設定階段失敗,因此控制器必須把失敗狀態傳給平台告警,並按可重試、不可重試和需要人工清理分類。搶佔策略要同時考慮 Pod 優先級、Claim 已占用容量和釋放延遲,不能只按 CPU 或記憶體排序。
觀測與容量規劃
記錄 Claim 建立到綁定、綁定到節點分配、分配到 Pod Ready 的分段延遲;分別統計裝置閒置、已分配、不可用、碎片化和驅動錯誤。把 ResourceSlice 發布的容量與節點實際可見性定期對帳,發現漂移時禁止繼續擴大灰度。訓練工作還要記錄重試、檢查點復原和裝置健康事件。
灰度、回滾與資料一致性
第一階段只選一個驅動和一個節點池,先執行可重試工作;第二階段擴大到多租戶並啟用範本;最後才遷移長時間、不可中斷的工作。回滾不是刪除已綁定 Claim:應先停止新 Claim 建立,等待或遷移執行中 Pod,凍結驅動變更,再讓新工作回到舊裝置外掛。保留 Claim、Pod 和驅動事件,避免回滾後失去事故證據。
驗證 API 與安全邊界
部署前用 resource.k8s.io/v1 API 做契約測試,驗證 Claim、Template、DeviceClass 和 ResourceSlice 的版本、狀態轉換和刪除順序。用故障注入測試驅動重啟、節點失聯、重複分配、Claim 洩漏和跨命名空間存取;同時檢查准入、RBAC、稽核和節點代理權限。只有功能、隔離和復原指標都通過,才擴大裝置池。
高品質示範回答
「我會把遷移拆成資源模型、驅動、排程和執行時四層。工作負載只宣告 Claim,Template 負責批量產生,DeviceClass 表達選擇語義,驅動發布 ResourceSlice 並在節點完成分配,排程器只做可行性和節點選擇。舊裝置外掛與 DRA 按節點池或裝置類別並存,禁止雙重管理同一裝置。對共享容量,我要求驅動提供容量模型和回收語義,不用標籤模擬超賣。上線先從可重試工作開始,觀測 Claim 到 Ready 的分段延遲、分配失敗、碎片化、驅動健康和租戶越權;回滾時停止新 Claim、保留執行中工作和事件,再把新工作切回舊路徑。」
常見錯誤
- 把 DRA 當成新的裝置標籤 → 排程成功但節點無法兌現 → 讓驅動發布結構化裝置與容量。
- 舊外掛和 DRA 管同一裝置 → 出現重複初始化或雙重分配 → 按池或裝置類別隔離所有權。
- 只設計 Claim,不設計回收 → 裝置和配額逐漸洩漏 → 定義釋放、逾時、刪除和對帳流程。
- 用標籤模擬可共享容量 → 排程器看不到真實剩餘容量 → 由驅動提供容量和並發約束。
- 把節點選中當成分配成功 → 驅動失敗導致長時間 Pending → 拆分排程、節點分配和 Ready 指標。
- 回滾時刪除所有 Claim → 執行中工作和事故證據遺失 → 先凍結新分配,保留狀態並遷移可復原工作。
追問及應對
追問一:為什麼不直接把 GPU 繼續註冊成擴充資源?
擴充資源適合簡單數量請求,但難以表達裝置屬性、可選方案、共享容量和複雜設定。若需求確實只有整卡計數且驅動成熟,舊方案可以繼續使用;引入 DRA 應由裝置選擇和生命週期複雜度驅動。
追問二:一個 Claim 被多個 Pod 引用時如何避免超賣?
Claim 的重用語義必須由驅動和平台策略明確,不能只依賴 YAML 慣例。對可共享容量,驅動需要記錄已分配容量、並發上限和回收狀態;准入層限制不符合租戶策略的引用。
追問三:驅動在節點設定階段失敗,排程器應該重試嗎?
先區分暫時性節點故障、裝置健康問題和 Claim 參數錯誤。暫時性故障可重試並退避;參數錯誤應標記不可重試並提示修正;裝置健康問題要隔離節點,避免排程器不斷把工作送回同一故障域。
追問四:如何驗證遷移沒有降低資源利用率?
用同一裝置池和相近工作負載比較分配成功率、等待延遲、碎片化、有效計算時間和工作重試率。把 DRA 與舊外掛按裝置類別分組,不能只看整個叢集平均 GPU 使用率。