具代表性的面試主題

系統設計面試:Kubernetes 原生 sidecar 遷移如何控制故障邊界?

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

題幹

如何把普通容器遷移為 Kubernetes 原生 sidecar,同時保證應用啟動順序、readiness、終止 flush、資源配額、版本相容與安全回滾?

題幹與適用場景

你負責把已經執行在 Kubernetes 上的日誌代理、服務網格代理或本地快取守護程式,從「普通容器」遷移為 Kubernetes 原生 sidecar。應用容器必須先等待代理準備完成,代理異常時要有明確的可用性邊界;系統還要支援 Job、滾動發布、資源配額與回滾。請提出遷移方案,並說明如何處理版本差異、探針、終止順序與故障。

這是一道 system-design 題。面試重點是邊界與取捨,而不是背誦 YAML。回答應涵蓋生命週期、相容性、資源、可觀測性與回滾。

面試官在考察什麼

  • 能否把業務 SLO 轉成啟動、就緒、終止與失敗策略。
  • 能否解釋原生 sidecar 與普通容器、獨立 Deployment 或 DaemonSet 的邊界。
  • 能否識別 API server、節點、webhook 與客戶端之間的版本風險。
  • 能否用資源預算、發布分批、指標與回滾降低遷移風險。
  • 能否處理 Job 完成、代理卡死、探針失敗與節點升級等反例。

Amazon 的 SDE II 面試準備資料把系統設計評估歸納為實用性、準確性、效率、可靠性、最佳化與擴展性;本題還要把這些目標落到 Pod 生命週期與發布控制上。

回答前需要澄清的問題

  1. 代理是每個 Pod 一份,還是每個節點一份?它是否必須與應用共享網路命名空間或磁碟區?
  2. 應用在代理未就緒時能否接收流量?啟動失敗時是阻斷發布、降級,還是允許旁路運行?
  3. 這是長駐服務、一次性 Job,還是兩者都有?終止時需要先 flush 日誌或上傳資料嗎?
  4. 叢集的 Kubernetes 版本、API server 與節點版本是否一致?Admission webhook、模板渲染器與客戶端會不會丟棄未知欄位?
  5. 代理的 CPU、記憶體、暫存儲存與網路預算是多少?它的故障是否算入應用 SLO 的錯誤預算?
  6. 能否先在一個 namespace 或一小組 workload 灰度,並保留普通容器格式作為回滾開關?

30 秒回答框架

先定義目標:代理與應用同一 Pod、按順序啟動、可觀測、可回滾,且不能讓代理無限期阻塞發布。接著說明實作:使用 initContainersrestartPolicy: Always 的原生 sidecar,配置就緒探針與資源預算;用 admission 與叢集版本檢查守住相容性。最後說發布:雙模板灰度、比較啟動延遲與錯誤率,異常時切回普通容器或舊版本,並單獨處理 Job 完成與終止 flush。

分步深入解答

1. 先畫出生命週期邊界

Kubernetes 原生 sidecar 是一種特殊的 init container:容器層級 restartPolicy: Always 讓它在 init 階段啟動後持續執行。它仍遵循 init 容器的啟動排序,因此後續 init 容器與應用容器要等它進入可用狀態才繼續。這能把「代理先準備」寫成 Pod 的結構約束,而不是由應用腳本輪詢。

應用與 sidecar 共享 Pod 的網路與儲存命名空間。需要共享 Unix socket、日誌磁碟區或本地代理連接埠時,這個邊界很清楚;若代理只需要節點級能力,應評估 DaemonSet,避免每個 Pod 重複消耗資源。

2. 定義 readiness 與故障策略

為代理設定能代表真實服務能力的 readinessProbe,例如檢查控制面設定已載入、監聽連接埠可用、關鍵憑證未過期。sidecar 的 readiness 會影響 Pod ready 狀態,因此探針失敗可能把流量從整個 Pod 摘除。探針只能表達狀態,不能取代重試、限流與降級策略。

需要明確三種失敗:啟動失敗、運行中崩潰、依賴暫時不可用。啟動失敗通常阻止 Pod 進入可服務狀態;運行中崩潰由 Always 重啟,但要透過重啟次數、恢復延遲與錯誤率監控是否已超出 SLO。若代理只是增強能力,可設計應用旁路或舊路徑;若代理負責安全鑑權,應 fail closed,並在發布控制器中快速停止擴散。

3. 處理終止、Job 與 flush

原生 sidecar 會在應用容器之後終止,多個 sidecar 按反向順序關閉。日誌代理因此可以在應用退出後繼續讀取緩衝並 flush,但必須設定可接受的 termination grace period;flush 超時應記錄遺失量並結束,不能無限等待。

對 Job,要驗證控制器把主容器結束視為完成,而不會因 sidecar 永久運行而卡住。sidecar 可能在 Job 完成前繼續重啟,所以應把「主任務結果」「sidecar flush 結果」與「最終資料完整性」分成不同指標與告警。

4. 做版本與變更鏈路檢查

原生 sidecar 在 Kubernetes v1.33 已穩定並預設啟用;相關能力在 v1.29 起作為 beta 預設開啟。遷移前仍要逐節點確認 kubelet、API server 與 admission 元件的實際版本與 feature gate。

舊的 mutating webhook、模板工具或客戶端可能不認識容器層級 restartPolicy,並在修改物件時把欄位丟掉。應在 CI 對最終提交物件做 schema 檢查,在 admission 日誌中記錄 sidecar 形態,並用一個探針 Pod 驗證實際運行時行為。無法保證鏈路一致時,保留普通容器模板作為 fallback,或暫停遷移。

5. 計算資源與調度影響

sidecar 不是免費附加項。它的 CPU、記憶體與暫存儲存請求會參與 Pod 的有效資源計算,影響 QoS、配額與調度。遷移前應以應用峰值、代理啟動峰值與緩衝上限計算 request/limit,觀察節點碎片、驅逐、OOM 與啟動排隊時間。

如果 sidecar 需要獨立擴縮容、不同發布節奏或更寬的故障域,獨立 Deployment 可能比同 Pod 更合適。原生 sidecar 的收益是本地共享與生命週期順序,代價是兩者共享調度、資源與發布單元。

6. 設計灰度、觀測與回滾

準備兩種 Pod 模板:原生 sidecar 與舊普通容器。按 namespace、標籤或工作負載分批放量,每批設定自動停止條件。核心指標至少包括 Pod 從建立到 Ready 的延遲、sidecar readiness 失敗率、重啟次數、應用請求錯誤率、代理緩衝深度、flush 遺失量、CPU/記憶體峰值與 Job 完成延遲。

遷移期間要記錄「期望形態」與「實際形態」,避免只看 Deployment 成功。若 webhook 丟欄位、Ready 延遲回歸或代理重啟超過門檻,停止擴散並切換舊模板。回滾不只是改映像,也要確認舊模板不會殘留新設定、磁碟區格式或連接埠假設。

7. 把安全與可觀測性放進邊界

sidecar 與應用共享網路與磁碟區,代表它擁有同一 Pod 的存取面。為代理設定最小權限、唯讀根檔案系統、明確的服務帳號與網路策略;不要因為「只是輔助容器」而跳過審計。日誌、指標與 trace 要帶 Pod、容器與發布版本標籤,才能區分應用故障與代理故障。

高品質示範回答

我會先把代理定位為每個 Pod 的本地依賴,並確認它確實需要共享網路或磁碟區;若是節點級能力,我會選 DaemonSet。遷移模板使用 Kubernetes 原生 sidecar:把代理放到 init containers,並設定容器層級 restartPolicy: Always。它先按 init 順序啟動,readinessProbe 表達設定與連接埠已準備,應用容器再進入服務。

我會把失敗拆成啟動失敗、運行崩潰與依賴暫時不可用。安全代理採用 fail closed;可選增強能力保留旁路。終止時利用 sidecar 在應用之後關閉的順序完成 flush,並給 grace period 上限。Job 單獨驗證主容器完成與 sidecar flush,不讓長期運行的 sidecar 阻塞 Job 狀態。

上線前檢查 API server、每個節點、feature gate、webhook 與模板客戶端,因為舊工具可能丟棄 restartPolicy。CI 校驗最終物件,灰度環境驗證實際 Pod 順序與 readiness。資源預算把代理峰值計入 Pod 的 QoS、配額與調度,監控 Ready 延遲、重啟、錯誤率、緩衝與遺失量。發布採用新舊雙模板分批放量,任何門檻越界就停止並回滾舊模板。這樣既利用原生生命週期保證,也把版本、資源與故障邊界變成可觀測的發布門檻。

常見錯誤

  • 只貼一段 YAML,不解釋為什麼需要原生 sidecar,以及普通容器或獨立工作負載何時更合適。
  • restartPolicy: Always 寫成 Pod 層級欄位,忽略它必須位於 sidecar 容器定義中。
  • 只設定 livenessProbe,沒說明 readiness 失敗如何影響流量與發布。
  • 假定 Kubernetes 版本滿足要求,卻沒有檢查節點、webhook 與客戶端的版本偏差。
  • 認為 sidecar 不影響資源配額,漏算啟動峰值、緩衝與 QoS。
  • 只驗證長駐服務,忘記 Job 完成、flush 超時與反向終止順序。
  • 回滾時只改映像,不驗證舊模板、連接埠、磁碟區與 admission 變更是否一致。

追問及應對

如果舊節點不支援原生 sidecar,怎麼辦?

先停止放量並按節點池隔離。若不能保證物件在舊鏈路中保留容器層級策略,就使用普通容器模板或升級節點;不要把未知欄位丟失當作成功相容。

sidecar readiness 一直失敗會怎樣?

Pod 不應進入 Ready,發布控制器應停止擴散。接著區分設定錯誤、依賴不可用與探針誤報,修復或回滾;不能用無限放寬探針來掩蓋真實不可用。

Job 的主容器結束後,sidecar 還在運行嗎?

原生 sidecar 可以繼續運行並重啟,但 Job 控制器可以識別主容器完成。應設定 flush 上限並分別記錄任務結果與資料完整性,避免把 sidecar 的長期運行誤判為任務失敗。

為什麼不把代理拆成獨立 Deployment?

如果代理需要獨立擴縮容、獨立發布或更大的故障域,拆分更合理;如果必須共享本地 socket、網路與嚴格啟動順序,原生 sidecar 更直接。選擇取決於耦合度與 SLO。

遷移後資源壓力變大,如何定位?

比較遷移前後 Pod 有效 request、啟動峰值、節點碎片、驅逐與 OOM,檢查代理緩衝與並發。若 sidecar 只是共享節點能力,評估 DaemonSet;若必須同 Pod,調整預算或降低灰度規模。

如何證明回滾真的安全?

保留舊模板雜湊,回滾時驗證物件中的容器形態、連接埠、磁碟區、服務帳號與 webhook 輸出,並觀察一批 Pod 的 Ready 延遲、錯誤率與 flush 遺失量。指標恢復後再繼續擴散。

公開來源

同類題目

相關面試工具

用 Solve 整理系統設計回答

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

查看工具