題幹與適用場景
多租戶叢集有 GPU 記憶體、虛擬網卡頻寬等不能只按「整個裝置」分配的資源。平台希望多個 Pod 共享同一裝置,但每個請求必須有最小值、步長、上限與可追蹤的分配身分。請以 Kubernetes DRA consumable capacity 設計資源模型與端到端流程。
題目假設 Kubernetes 1.34 已啟用相關能力,裝置驅動能執行容量限制,排程器需要避免超賣。Kubernetes 1.34 讓 DRA 核心 API GA,同時把 consumable capacity 作為 alpha 能力提供更細緻的裝置共享;回答必須清楚標示穩定核心與 feature gate、驅動實作的邊界。
面試官考察點
強回答會講清楚 DeviceClass、ResourceSlice、ResourceClaim、DeviceRequest 與驅動分工,並寫出「已分配容量總和不能超過裝置容量」的不變量。還要區分預先切片與動態容量,說明 allowMultipleAllocations、RequestPolicy、ShareID 和 DistinctAttribute 如何影響排程與隔離。
面試官會檢查是否把排程成功誤當成應用限速成功。真正系統需要驅動執行頻寬或記憶體限制、狀態回報、跨命名空間授權、節點故障復原與可回滾的灰度策略。
需要澄清的問題
資源可切片還是可超賣
確認硬體或驅動能否強制隔離容量。不能強制隔離的資源只能使用軟配額或整裝置分配,不能把 DRA API 當作 QoS 保證。
共享邊界與授權
確認不同命名空間能否共享同一裝置、是否允許管理員模式,以及租戶能否讀取裝置屬性與容量。答案會改變 DeviceClass selector、Admission 與稽核範圍。
失敗時要保留什麼
確認排程失敗、驅動分配失敗、節點失聯與 Pod 重建時,要釋放容量、保留租約還是重新排隊。短暫重試與不可恢復的硬體故障需要不同狀態。
30 秒回答框架
「我先定義容量不變量與租戶隔離,再用 DeviceClass 描述可選裝置,用 ResourceSlice 發布容量與請求策略,用 ResourceClaim 表達 Pod 需求。排程器只負責選擇滿足容量和 selector 的裝置,驅動透過 ShareID 為每個分配執行實際限制並回報狀態。跨命名空間共享要由授權與稽核保護,所有釋放操作都要具備冪等性。上線前先在單一裝置類灰度,比較已分配容量、驅動實際上限、排程延遲、拒絕率和故障復原時間。」
分步深入解答
第一步:寫出資源模型
DeviceClass 表達裝置類型與 CEL selector;ResourceSlice 發布具體裝置、屬性、容量與是否允許多次分配;ResourceClaim 透過 DeviceRequest 宣告裝置類別與容量請求。把「裝置總容量」與「本次請求容量」分開,避免把裝置數量誤解成容量。
第二步:定義容量不變量
每個裝置維護已分配容量總和、單位與請求策略。若裝置容量是 40 GiB,策略最小 5 GiB、步長 5 GiB,每個請求必須符合邊界與步長,所有活躍 ShareID 總和不能超過 40 GiB。釋放與重試按分配版本做到冪等,不能因重複回呼扣減兩次。
第三步:描述排程與驅動資料流
排程器讀取 ResourceSlice,過濾 DeviceClass selector、容量範圍與 allowMultipleAllocations,預留候選後綁定 ResourceClaim。驅動收到結果,以 ShareID 建立獨立上限,對裝置施加記憶體或頻寬限制,再把動態資訊寫入 ResourceClaim status。排程成功但驅動拒絕時,控制器要把錯誤標為可重試或不可重試,而不是讓 Pod 假裝 Ready。
第四步:處理跨命名空間與重複裝置
ResourceClaim 的命名空間邊界不能被「共享裝置」繞過。Admission 應限制可用 DeviceClass、管理員存取與驅動設定;DistinctAttribute 用於同一 claim 內要求不同底層裝置,例如跨子網的兩張網卡。稽核記錄租戶、claim、ShareID、容量與策略版本,避免只記最終裝置名稱。
第五步:設計故障與回收
驅動重啟時先從持久化狀態恢復 ShareID 與實際限制;節點失聯時控制器標記分配未知,禁止立即把容量發給另一個 Pod,直到租約、裝置 fencing 或驅動確認完成。Pod 刪除、claim 失效和排程回滾都要能重複執行。容量策略變更時,已完成分配按舊快照解讀,新 claim 使用新策略。
第六步:灰度、SLO 與容量估算
假設叢集有 100 個裝置、每個裝置 40 GiB,目標平均利用率 70%,可供排程的邏輯容量約 2800 GiB;這不是業務吞吐承諾,還要扣除驅動保留、碎片與故障餘量。為排程 p99、驅動設定 p99、容量拒絕率和狀態收斂時間設定 SLO,按裝置類逐步開啟 feature gate。用整裝置分配作對照,測量吞吐、尾延遲、碎片與復原時間。
第七步:比較替代方案
若硬體只支援固定切片,MIG 或預先切分的 DeviceClass 更簡單,容量不變量也更容易證明;代價是碎片與彈性較差。若驅動不能執行細粒度限制,應退回整裝置或擴容,不能用 API 的 capacity 欄位偽造隔離。
高品質示範回答
我會先確認裝置是否能強制執行容量隔離。若不能,方案只提供宣告式選擇,不承諾 QoS。能隔離時,DeviceClass 描述可選裝置,ResourceSlice 發布容量與請求策略,ResourceClaim 表達租戶需求。排程器只在容量總和不超賣且 selector 符合時綁定;驅動再用 ShareID 建立獨立上限並回報 status。
我會把容量總和、版本與釋放冪等寫成不變量。跨命名空間共享需要 Admission、管理員授權和稽核;DistinctAttribute 解決同一 claim 不可重複選同一底層裝置。驅動或節點故障時先保留未知分配,完成 fencing 或確認後再回收。上線從單一裝置類灰度,比較排程 p99、驅動設定 p99、拒絕率、實際上限與復原時間;硬體只支援固定切片時選擇預切分方案。
常見錯誤
- 錯誤表現 → 只在 ResourceClaim 寫容量 → 失敗原因 → 驅動可能沒有實際上限能力 → 修正方法 → 證明驅動執行與狀態回報鏈路。
- 錯誤表現 → 用裝置數量代替容量總和 → 失敗原因 → 多個請求會超賣或浪費碎片 → 修正方法 → 維護按裝置與版本計算的已分配容量。
- 錯誤表現 → 共享裝置等於跨租戶無條件共享 → 失敗原因 → 命名空間與授權邊界被繞過 → 修正方法 → 加入 Admission、管理員存取控制與稽核。
- 錯誤表現 → 節點失聯後立即釋放容量 → 失敗原因 → 舊驅動可能仍在施加限制,造成雙重分配 → 修正方法 → 先完成 fencing、租約確認或明確未知狀態。
- 錯誤表現 → 把 alpha feature gate 當成穩定 SLO → 失敗原因 → API、驅動和升級行為仍有差異 → 修正方法 → 標出版本邊界並灰度驗證。
追問及應對
追問一:兩個命名空間同時請求最後 10 GiB,如何避免競態?
排程器需要用 ResourceSlice 版本或等價的樂觀並行檢查預留容量,綁定失敗後重新讀取最新狀態。驅動回呼不能自行突破排程器不變量,最終分配仍須由控制面確認。
追問二:驅動回報 ShareID 已分配,但 Pod 沒有啟動怎麼辦?
把分配狀態與 Pod 啟動狀態分開。控制器在逾時後執行冪等釋放或進入人工介入狀態,並保留 ShareID、claim 版本和錯誤原因。不能因 Pod 未 Running 就丟掉稽核和容量記錄。
追問三:容量策略從最小 5 GiB 改成最小 10 GiB,會影響已有 claim 嗎?
已完成分配按當時策略快照維持語義,新請求使用新策略。若業務要求重新平衡,應建立明確遷移流程,先評估驅動是否支援縮放,再按可回滾步驟釋放和重新分配。
追問四:如何證明共享頻寬真的被限制?
在固定流量、相同節點與相同驅動版本下,執行單租戶基線和多 ShareID 並行壓測,比較每個租戶的吞吐、p99、丟包和上限。只看 ResourceClaim status 不足以證明硬體 QoS 已生效。