具代表性的面試主題

Kubernetes 面試:如何讓 kube-scheduler 的 API 呼叫不阻塞?

系統設計困難
Offer.cc 編輯團隊發佈 更新

題幹

kube-scheduler 在排程週期中執行慢 API 呼叫時,如何改造成非阻塞處理,同時保證 Pod 順序、重試和可觀測性?

題幹與適用場景

一個叢集啟用了會呼叫 API Server 的排程外掛。API 延遲升高時,排程週期被同步呼叫占住,待排程 Pod 越積越多。請設計 KEP-5229 所描述的非同步處理方案,說明優先級佇列、請求去重、失敗重試、取消、資源公平和回滾條件。

面試官考察點

  • 能否區分排程週期串行語意與 API 副作用的非同步執行。
  • 是否用有界優先級佇列和請求去重避免執行緒飢餓與重複寫入。
  • 是否定義冪等鍵、逾時、取消、過期結果和不可重試錯誤。
  • 是否考慮高優先級 Pod、公平性、背壓、指標與 feature gate 灰度。

回答前需要澄清的問題

  1. API 呼叫是唯讀查詢、冪等寫入,還是建立外部資源?副作用決定重試邊界。
  2. 排程外掛能否接受最終一致的外部狀態,還是綁定前必須得到確認?
  3. 失敗時 Pod 回到 unschedulable 佇列,還是只重試 API 操作?兩者不可混為一談。
  4. 叢集的 API QPS、並發排程數和優先級佇列預算是多少?

30 秒回答框架

我會把慢 API 操作從排程執行緒移到有界的優先級佇列,排程執行緒提交帶冪等鍵的工作後繼續處理其他 Pod。佇列按 Pod 優先級和等待時間服務,並對相同鍵的請求去重。完成事件只觸發安全的重新評估,過期結果不能直接綁定。錯誤按可重試與永久失敗分類,設定逾時、取消、退避和並發上限。用待處理數量、佇列等待、成功率和排程延遲做灰度門檻,異常時關閉 feature gate 回退同步路徑。

分步驟深入解答

1. 劃分同步邊界

排程週期負責選擇節點和維護排程上下文;非同步工作負責可延遲的 API 操作。若操作結果是綁定決策的硬前置,就不能簡單「丟到背景」,應先把狀態建模為 pending,確認前阻止綁定。只有不影響當前週期安全性的工作才可非同步化。

2. 設計有界優先級佇列

每個工作攜帶 Pod UID、操作類型、冪等鍵、截止時間和取消上下文。佇列必須有容量上限;滿載時向排程器回傳明確的 backpressure 訊號,而不是無界堆積。高優先級工作先服務,同時用 aging 或配額避免低優先級工作永久飢餓。

text
submit(key, priority, deadline, operation)
if same key is pending: coalesce(operation)
else if queue is full: return Backpressure
else enqueue(operation)

3. 請求去重與冪等

去重只解決同一邏輯操作的並發合併,不等於 API Server 的冪等保證。寫入應使用穩定資源鍵、條件更新或伺服器冪等語意;重試前檢查上一次結果,避免重複建立外部資源。不同版本或不同目標的請求不能因字串相似而錯誤合併。

4. 完成、取消與過期結果

工作完成後發布事件,事件只負責讓相關 Pod 重新評估,不直接假設排程狀態仍然有效。Pod 被刪除、搶占或進入新排程上下文時取消舊工作。超過 deadline 的結果丟棄並記錄原因;API 呼叫成功但上下文已過期時也不能執行舊綁定。

5. 重試、背壓與公平

逾時、暫時網路錯誤和 429 可按指數退避重試;鑑權失敗、參數錯誤和衝突需要進入永久失敗或重新計算路徑。並發 worker 數、每個外掛配額和 API QPS 必須有上限。待排程 Pod 的重試要和 API 工作重試分開計數,否則一個慢操作會放大整個佇列。

6. 相容、灰度與回滾

保留外掛 API 和排程結果語意,用 feature gate 控制非同步路徑。先在低風險外掛、低並發叢集啟用,比較排程 P99、佇列等待、API 延遲、工作失敗、重複請求和 unschedulable 重試次數。若佇列積壓、綁定錯誤或 API 壓力超過基線,停止新工作並排空或取消佇列,再回退同步路徑。

高品質示範回答

我會先確認哪些 API 操作可以延遲,哪些是綁定前置條件;前者進入有界優先級佇列,後者保留明確的 pending 狀態。工作帶 Pod UID、操作類型、冪等鍵、deadline 和取消上下文,相同鍵的請求合併,佇列滿時施加背壓。worker 只執行冪等或可安全重試的操作,暫時錯誤退避,永久錯誤回到外掛的失敗處理。完成事件觸發重新評估,過期結果絕不直接綁定。發布使用 feature gate 和小範圍灰度,監測排程 P99、佇列深度、API QPS、重複率、失敗率和綁定正確性;異常時停止非同步提交、清理工作並回退同步路徑。

常見錯誤

  • 把所有 API 呼叫都放背景 → 綁定前置條件可能被繞過 → 先畫出排程上下文和安全狀態機。
  • 只有一個全域 FIFO → 高優先級 Pod 被低優先級工作阻塞 → 使用優先級、aging 和配額。
  • 以請求字串去重 → 不同資源版本或副作用被錯誤合併 → 使用資源鍵和明確冪等語意。
  • 無限重試 → API 故障變成佇列風暴 → 設 deadline、退避、最大嘗試次數和熔斷。
  • 只看吞吐 → 排程延遲和錯誤被掩蓋 → 同時觀察佇列、API、重試和綁定正確性。

追問及應對

如果相同 Pod 同時提交讀和寫,可以合併嗎?

不能只憑 Pod UID 合併。讀請求可按資源版本合併,寫請求需按操作類型、目標資源和冪等鍵判斷,並保持必要先後關係。

佇列滿時應該丟棄哪個工作?

先依 deadline、優先級和可重建性制定策略;不可丟棄的綁定前置工作應產生 backpressure。任何丟棄都要讓 Pod 進入可解釋的重試或失敗狀態,不可靜默刪除。

API 呼叫成功但 Pod 已被搶占怎麼辦?

用取消上下文和物件版本檢查阻止舊上下文繼續寫入。成功結果只記錄為稽核資訊,新的排程上下文重新評估,不重用過期綁定意圖。

公開來源

同類題目

相關面試工具

用 Solve 整理系統設計回答

從澄清需求開始,展開規模、架構、元件選擇和取捨。

查看工具