題幹與適用場景
平台團隊希望在不重建 Pod 的情況下調整 CPU 與記憶體。請設計 Kubernetes 原地 Pod 調整流程,說明何時容器必須重啟、如何處理資源不足,以及怎樣觀測與回復。
Kubernetes 1.33 將容器原地調整提升為 Beta;1.36 的 Pod 層級資源調整也處於 Beta。請求修改執行中 Pod 的 CPU 與記憶體資源時,kubelet 依 resizePolicy、節點容量與 cgroup 狀態執行或延遲處理,不能把「修改規格」誤解為「永不重啟」。
面試官考察點
重點包括:區分 Pod 層級上限與容器資源、resizePolicy 的 CPU/記憶體語意、Pending/InProgress 狀態、不可行與延遲重試、scheduler 與 kubelet 的職責、QoS 與優先級,以及灰度與回復邊界。
30 秒回答框架
「我會把原地調整設計成宣告式請求加狀態機。控制器更新資源規格,kubelet 檢查節點可行性並更新 PodResizePending 或 PodResizeInProgress;CPU 通常可以不重啟,記憶體是否重啟由容器的 resizePolicy 決定。不可行請求要保留原因並按優先級重試,不能假裝已生效。平台需要觀測 observedGeneration、實際 cgroup、重啟次數與 QoS 變化,並以小批量灰度和反向 patch 回復。」
分步驟深入解答
第一步:定義資源模型
容器資源決定單一容器的請求與限制;支援的版本中,Pod 層級資源提供聚合邊界。Pod 層級限制是所有容器使用量的上界,但單一容器限制不能超過 Pod 層級限制。API 必須明確修改 spec.containers[*].resources 還是 spec.resources。
第二步:建立宣告式調整流程
平台接收目標資源與原因,寫入 Pod 資源欄位,保存原值、操作者與變更代次。API 層不直接操作節點 cgroup;kubelet 觀察新的 generation,完成可行性檢查與執行,再把結果寫回狀態。
第三步:處理重啟策略
容器可按資源分別設定重啟策略:
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: RestartContainerNotRequired 嘗試在執行中套用;RestartContainer 允許透過重啟使新值生效。對 restartPolicy: Never 的 Pod,所有容器資源都必須使用 NotRequired,否則請求無效。
第四步:設計可行性與延遲狀態
節點無法提供目標資源時,kubelet 設定 PodResizePending,原因可以是 Infeasible 或 Deferred;成功處理時進入 PodResizeInProgress。控制器應讀取狀態而非只看 API spec,並透過 observedGeneration 確認狀態對應的請求代次。
第五步:處理 CPU 與記憶體差異
CPU 調整通常可更新 cgroup 配額而不重啟應用程式。記憶體縮容可能受目前工作集限制,部分執行時需要重啟才能安全套用;不能以 CPU 的無重啟行為推斷記憶體。控制器應按資源讀取策略並為每種結果提供明確事件。
第六步:協調排程與 QoS
原地調整不等於節點重新排程。擴大請求可能需要節點容量,延遲請求應按 PriorityClass、QoS 類別與等待時間重試。調整後要重新計算 QoS、資源配額與監控告警,避免突破 namespace 配額或低估 Guaranteed 工作負載。
第七步:觀測實際生效值
同時採集期望 spec、status 條件、observedGeneration、容器實際 cgroup 配額、重啟次數、OOM、CPU throttling 與記憶體工作集。若狀態顯示完成但 cgroup 未變化,應視為失敗並阻止下一次調整,而非繼續疊加 patch。
第八步:灰度、限速與回復
按工作負載與節點池分批執行,限制並發調整數,設定 Pending 超時與最大重試次數。異常時恢復保存的舊資源;若記憶體策略導致重啟,先摘除流量並驗證就緒,再擴大灰度。所有請求都要支援冪等鍵,避免控制器重複提交。
設計取捨與邊界
無重啟連續性還是資源確定性
原地調整減少服務中斷,但延遲與節點容量會讓結果非同步。對延遲敏感服務可保守使用小步調整;對批次工作可接受重啟以換取確定性。
Pod 層級邊界還是容器層級精度
Pod 層級資源適合表達共享上限,容器層級資源適合保護關鍵容器。兩者同時存在時,平台必須驗證容器限制不超過 Pod 上限,並在 UI 與稽核中顯示有效邊界。
自動重試還是人工批准
暫時不足適合有限重試;涉及記憶體重啟、QoS 變化或生產高峰時,應要求批准或維護窗口,不能無限自動重試。
失敗演練與演進計畫
節點資源不足
提交超過節點容量的擴容請求,確認狀態為 Infeasible 或 Deferred,驗證重試不會修改已生效的舊值。
記憶體調整觸發重啟
為記憶體設定 RestartContainer,觀察流量摘除、容器重啟、就緒恢復與事件順序,確認控制器不會把重啟誤報為業務故障。
代次競爭
快速提交兩個不同目標,確認舊 generation 的完成狀態不會覆蓋新目標,且最終狀態的 observedGeneration 與實際 cgroup 一致。
常見誤區與追問
誤區一:原地調整保證永不重啟
追問:什麼會觸發重啟?容器的 resizePolicy 可以要求重啟,尤其是記憶體變化;Pod 層級資源調整本身沒有獨立重啟策略,但容器策略仍生效。
誤區二:只更新 spec 就算完成
追問:如何確認成功?檢查狀態條件、observedGeneration、實際 cgroup、容器事件與重啟次數,不能只讀期望欄位。
誤區三:節點不足時持續 patch
追問:正確做法是什麼?保留 Pending 原因,按優先級與等待時間有限重試,並提供遷移、縮小目標或人工批准路徑。
延伸追問與參考答案
為什麼 CPU 與記憶體要分開設計?
CPU 配額通常能線上改變;記憶體縮容受工作集與執行時限制,可能需要重啟。統一介面仍應保留按資源的策略與狀態。
如何防止重複調整覆蓋新目標?
用資源版本或 generation 做條件更新,控制器只接受最新目標,狀態透過 observedGeneration 與實際 cgroup 對帳。
何時不應使用原地調整?
需要強隔離、節點無法穩定提供容量、應用程式不能承受重啟或資源變化會破壞執行時假設時,應採用新 Pod 滾動替換,並保留原地功能作為受控最佳化。