系統設計面試:如何安全推廣 Kubernetes Node Declared Features?
題幹與適用場景
叢集導入 Kubernetes 的 Node Declared Features:kubelet 在 Node 狀態回報受管理的節點能力,排程器據此過濾 Pod,准入控制器在 Pod 更新時再次驗證。請設計混合版本叢集的上線、觀測、失敗處理與回滾方案。假設這項能力只用於受控節點特性,不允許業務團隊任意寫入能力名稱。
面試官考察點
- 是否理解能力宣告是 Node 狀態事實,不是使用者可任意偽造的標籤。
- 是否能說清 kubelet、kube-apiserver、kube-scheduler 與 admission controller 的依賴順序。
- 是否涵蓋舊節點、狀態延遲、Pod 更新與 feature gate 回滾。
- 是否用排程拒絕率與節點回報完整度證明安全,而不只看元件啟動成功。
回答前需要釐清的問題
- 目標節點能力由哪個 kubelet 版本產生,舊節點是否繼續承載一般 Pod?
- 要保護的是排程放置,還是 Pod 綁定後的更新也必須受保護?
- 叢集是否有自訂 scheduler、多個 API server 或跨區控制面?
- 發生誤報時,先停止新 Pod,還是允許舊 Pod 繼續執行?
30 秒回答框架
我會把能力宣告視為跨元件的事實鏈:kubelet 回報 status.declaredFeatures,排程器插件在 PreFilter 與 Filter 判斷 Pod 需求,准入控制器保護後續更新。上線先在非關鍵節點與小比例工作負載啟用,確認 kube-apiserver、scheduler、kubelet 的 feature gate 一致後再擴大。監控能力回報完整度、排程失敗原因、更新拒絕率與版本分布;發現不一致就停止依賴新能力的工作負載並關閉 gate,保留一般 Pod 的排程路徑。
分步驟深入解答
- 定義事實來源。 節點能力由 kubelet 啟動時偵測並寫入 Node 的
status.declaredFeatures;應用團隊不能把任意標籤視為同等事實。能力名稱應來自受管理的 feature gate 或明確元件契約。 - 明確元件依賴。 Kubernetes 文件要求 NodeDeclaredFeatures gate 同時在 kube-apiserver、kube-scheduler 與 kubelet 啟用。先驗證控制面版本與設定,再升級 kubelet,避免只開一端造成「欄位存在但沒人使用」或「排程器要求欄位而節點不會回報」。
- 設計排程路徑。 scheduler 插件在 PreFilter 從 PodSpec 推導所需能力,在 Filter 對照節點宣告;未宣告所需能力的節點不可排程。自訂 scheduler 若使用此欄位,也必須複製相同的缺省與失敗語意。
- 保護更新路徑。
NodeDeclaredFeatureValidatoradmission controller 在 Pod 更新時驗證綁定節點能力,避免首次排程後節點能力變化或工作負載要求升級繞過過濾。把更新拒絕呈現為明確業務錯誤,避免靜默降級。 - 處理混合版本。 舊 kubelet 可能沒有此欄位或不認識新能力。把「未宣告」視為「不滿足要求」,讓依賴新能力的 Pod 留在佇列;一般 Pod 仍可排到相容節點。不要透過手動補 Node 狀態繞過版本差異。
- 分階段發布。 先在可回滾節點池啟用 gate,放置只要求新能力的探針工作負載,再逐步擴展。每階段設定停止條件:回報缺失率、排程拒絕率、Pod 更新拒絕率或 scheduler 延遲超過基線就暫停。
- 觀測與稽核。 收集 Node 宣告版本、能力集合摘要、排程過濾原因、准入拒絕原因與 gate 設定指紋,按節點池和 Kubernetes 版本切片。避免把完整 Node 物件寫入高基數日誌。
- 回滾與升級。 回滾先停止建立依賴能力的 Pod,再恢復一般排程;確認沒有 pending 工作負載後按元件順序關閉 gate。若能力已被業務依賴,先遷移工作負載或保留相容節點,不能直接讓宣告消失。
高品質示範回答
我會先確認這條鏈的事實來源與保護目標。kubelet 負責回報受管理的 status.declaredFeatures,scheduler 的 NodeDeclaredFeatures 插件負責排程前過濾,NodeDeclaredFeatureValidator 負責保護綁定後的更新。因為 Kubernetes 要求 kube-apiserver、scheduler 與 kubelet 同時啟用 gate,我會先統一控制面與節點版本,再在一個可回滾節點池啟用。探針 Pod 驗證能力回報與排程結果,接著以回報缺失率、過濾拒絕率、更新拒絕率與排程延遲作為擴容門檻。舊節點不宣告能力就視為不滿足要求,一般 Pod 仍走原路徑。回滾時停止新依賴、遷移現有工作負載、關閉 gate,並確認 pending 數量與一般 Pod 排程恢復。
常見錯誤
- 把 declaredFeatures 當一般標籤 → 使用者可偽造能力破壞排程安全 → 只接受 kubelet 管理的能力集合。
- 只在 scheduler 開 gate → 節點不會回報欄位 → 依 kube-apiserver、scheduler、kubelet 三端檢查設定。
- 把未宣告當成支援 → 混合版本節點可能接收不相容 Pod → 未宣告必須視為不滿足。
- 只驗證首次排程 → Pod 更新可能繞過能力約束 → 同時啟用並觀測准入驗證。
- 直接全量開啟 → 失敗時無法區分版本、節點池與工作負載影響 → 使用探針、分階段與停止條件。
- 直接關閉 gate → 已依賴能力的 Pod 進入不可恢復狀態 → 先停止建立並遷移依賴工作負載。
追問及應對
節點回報能力後狀態長時間沒有更新,排程器該怎麼辦?
把回報年齡納入可觀測性與運維門檻;要求該能力的 Pod 寧可等待或轉移到新鮮節點,也不要依過期宣告放行。超時後隔離節點池並人工確認。
自訂 scheduler 不使用官方插件,有什麼風險?
它必須實作相同的 PreFilter、Filter、缺省與版本語意,否則會出現預設 scheduler 拒絕、自訂 scheduler 放行的分裂。先用一致性測試驗證兩條路徑,再允許工作負載切換 scheduler。
feature gate 需要跨三個元件同時變更,如何避免窗口不一致?
把設定指紋納入發布檢查,先讓不依賴能力的工作負載保持可運作,再依控制面、scheduler、節點池順序滾動。任何指紋不一致都停止擴展,不把「元件已啟動」當完成訊號。
業務已依賴新能力,但回滾發現舊節點不支援,怎麼辦?
先保留一組宣告能力的新節點,遷移或縮小依賴該能力的工作負載,再關閉 gate;無法遷移就暫停回滾並提高相容節點容量,避免排程約束突然失效。