題干與適用場景
一個外部排程元件會為 Pending Pod 推薦目標節點,希望減少搶佔後的重複過濾成本。請依 Kubernetes nominatedNodeName 設計協作協定,並說明為什麼它不能取代 nodeName、如何處理 scheduler 覆寫、資源變化和回滾。
Kubernetes v1.35 將 nominatedNodeName 標為 beta。它是 Pod status 中供外部元件提名節點的欄位,提名是 best effort,scheduler 仍可覆寫,即使欄位存在也可能判斷該節點不適合。題目考察候選人能否把提示狀態與最終 binding 分離。
面試官考察點
重點包括:status 寫入權限和所有權、提名與過濾迴圈的時序、搶佔受害者優雅退出、nodeName 與 nominatedNodeName 的語義差異、外部排程器的冪等與過期處理、指標設計,以及 feature gate 的灰度和回滾。
30 秒回答框架
「我把 nominatedNodeName 當作可撤銷提示,不把它當作承諾。外部元件只在明確授權下更新 status,並附帶版本和原因;scheduler 每輪先驗證提名節點,失敗就回退到全量候選。提名節點可能被更高優先級 Pod 搶走,欄位也可能被 scheduler 改寫或清空。最終以 nodeName 和 binding 事件為準,觀測提名命中率、回退率、排程延遲和搶佔受害者退出時間,異常時關閉 feature gate 或停用外部寫入。」
分步驟深入解答
第一步:劃分欄位語義
nodeName 是 Pod spec 中的硬綁定提示,scheduler 會被繞過,節點不存在或資源不足時可能直接失敗。nominatedNodeName 位於 status,用於表達某個 Pending Pod 的候選節點,外部提名和 scheduler 搶佔都可寫入,屬於軟狀態。
第二步:定義外部元件權限
外部元件應使用最小 RBAC,只能更新目標 Pod 的 status,並在註解或事件中記錄提名原因、演算法版本和時間。它不能修改 spec.nodeName,也不能假設 status 更新後 kubelet 會立即執行綁定。
apiVersion: v1
kind: Pod
metadata:
name: batch-worker
status:
nominatedNodeName: worker-07第三步:處理 scheduler 的優先級
scheduler 可能因搶佔找到提名節點,也可能在進入 WaitOnPermit 或 PreBind 時寫入。外部元件必須接受欄位被覆寫,不能持續搶寫造成控制器震盪。每次更新前比較 resourceVersion,衝突時重新讀取並重新計算。
第四步:設計過濾與回退
scheduler 先驗證 nominatedNodeName 是否仍通過資源、親和、污點和拓撲過濾;不通過時繼續標準候選節點流程。外部元件也應在提名前做相同級別的快速檢查,但不能把自己的檢查結果當成 scheduler 的最終結論。
第五步:處理搶佔時間窗
搶佔會給受害 Pod 留出優雅終止時間,提名節點在這段時間內可能仍不符合新 Pod。scheduler 可能先清空提名欄位,或因另一個更高優先級 Pod 到達而讓出節點。業務側應等待 binding 事件,不應在 status 提名後立即發流量。
第六步:保證冪等與過期安全
外部元件為每次提名產生可追蹤的決策 ID,並設定短 TTL。節點資源變化、Pod spec 更新、優先級變化或排程佇列重排後,舊提名應視為過期;重複 reconcile 只在決策仍有效時寫入相同值。
第七步:設計觀測指標
至少記錄提名寫入成功率、status 衝突、提名節點過濾失敗率、回退後排程延遲、Pod 從 Pending 到 binding 的時間、受害 Pod 終止耗時和 nominatedNodeName 被清空次數。按叢集、優先級、排程器和外部演算法版本切分,才能定位回退退化。
第八步:規劃灰度與回滾
先在少量 namespace 和低風險 PriorityClass 上啟用,比較啟用前後的排程延遲與搶佔結果。發現過濾耗時上升、錯誤綁定或狀態震盪時,停止外部 status 更新並關閉相關 scheduler feature gate;保留普通排程路徑,避免透過寫 nodeName 強制回退。
設計取捨與邊界
nominatedNodeName 還是 nodeName
nominatedNodeName 保留 scheduler 的過濾、搶佔和 binding 責任,適合外部元件提供建議。nodeName 繞過 scheduler,適用於明確知道節點且能承擔資源與故障責任的進階場景,不能作為通用加速手段。
先驗提名還是全量過濾
先驗提名可減少大型叢集中搶佔後的重複過濾,但提名節點可能已釋放資源或變得不合適。回退掃描是正確性底線,效能最佳化不能刪除它。
狀態可見性還是控制權
status 讓外部系統和維運看到排程意圖,卻不授予最終控制權。告警、控制器和業務自動化都應監聽 binding、FailedScheduling 和事件,而不是只看 nominatedNodeName。
失敗演練與演進計畫
提名節點資源被占用
在提名寫入後啟動更高優先級 Pod,驗證 scheduler 能覆寫或清空欄位,並讓原 Pod 回退到其他節點,而不是永久 Pending。
status 更新衝突
並發修改同一 Pod status,確認外部元件遇到 resourceVersion 衝突後重新讀取,不會使用舊物件覆蓋 scheduler 的決定。
優雅終止延遲
讓搶佔受害者設定較長 termination grace period,確認提名節點在等待期間不會被誤報為已可用,並監控 Pending 到 binding 的尾延遲。
常見誤區與追問
誤區一:把 nominatedNodeName 當成綁定結果
追問:欄位存在後 Pod 一定在該節點嗎?不一定,scheduler 仍會重新過濾,最終 nodeName 和 binding 事件才是結果。
誤區二:用 nodeName 取代提名
追問:為什麼不直接寫 nodeName?它會繞過 scheduler,失去資源、污點、親和與搶佔保護,節點不合適時可能直接失敗。
誤區三:外部控制器持續搶寫 status
追問:scheduler 改寫欄位怎麼辦?接受所有權競爭,使用 resourceVersion、決策 TTL 和冪等 reconcile,避免控制器來回覆蓋。
延伸追問與參考答案
提名節點為什麼仍可能不是最終節點?
搶佔受害者退出期間,其他節點可能釋放資源,或更高優先級 Pod 先占用提名節點;scheduler 會繼續嘗試,並可能清空或改寫提名。
如何判斷最佳化是否有效?
比較提名前後過濾耗時、Pending 到 binding 延遲、提名命中率、回退率和搶佔受害者退出時間;只看寫入次數不能證明排程變快。
外部元件最小安全邊界是什麼?
只更新獲授權 Pod 的 status,不寫 nodeName,不修改優先級或資源 spec,並以 binding 事件確認結果;所有決策都要能過期、稽核和回滾。