題目與適用場景
某團隊在 Pod 中使用 gitRepo volume,節點啟動時直接把儲存庫複製到掛載目錄。Kubernetes v1.36 已永久停用該 volume plugin,且無法透過 feature gate 恢復。請設計遷移:盤點工作負載和儲存庫依賴,選擇 init container、外部同步器或建置期打包,驗證提交完整性、憑據、網路、更新語義和回滾。
官方說明指出,gitRepo 長期 deprecated,舊實作可能讓攻擊者以 root 身份在節點執行程式碼。v1.36 關閉外掛後,舊 Pod 不會因重新排程而自動獲得相容行為;答案要把 API 變更、映像發布和執行時拉取分開討論。
背景與邊界
本題聚焦卷外掛生命週期、Pod 啟動順序、供應鏈信任和遷移驗證。Git 託管平台、映像倉庫、網路出口和密鑰管理是外部依賴;候選人應明確 commit pin、憑據最小權限、網路失敗策略和資料更新目標。
面試官考察點
- 能否識別
gitRepo是 volume plugin,而不是普通映像層或 ConfigMap。 - 能否比較建置期打包、init container 和持續同步器的可重現性、更新延遲和故障語義。
- 能否處理 private repository、known host、token、代理和提交完整性。
- 能否設計升級前掃描、Admission 阻斷、灰度節點和可回滾發布。
- 能否說明空目錄、掛載權限、read-only 共享和應用啟動依賴。
30 秒回答框架
「我先掃描所有 Pod、模板和產生器中的 gitRepo,記錄儲存庫、revision、掛載路徑、憑據和更新需求。預設優先在建置期把固定 commit 打進不可變映像;若必須執行時拉取,就用最小權限 init container 將儲存庫寫入 emptyDir,並讓主容器只讀掛載。需要持續更新時使用受控的外部同步器,但要定義原子切換、失敗保留舊版本和校驗規則。升級前透過策略拒絕新使用,灰度新映像,確認重啟、網路失敗和回滾後再刪除舊模板。」
分步驟深入解答
- 盤點真實依賴。 搜尋 Pod、Deployment、StatefulSet、Job、Helm chart、Kustomize、產生腳本和 admission mutation 中的
gitRepo。記錄 repository、revision、路徑、容器是否啟動即讀取、儲存庫大小、更新頻率、憑據來源和網路出口。
- 劃分更新語義。 固定設定或靜態模板優先建置期打包;啟動時必須拉取的內容使用 init container;執行中需要更新的內容才考慮同步器。不要把「每次啟動拉取」和「熱更新」混為一種需求。
- 建置期打包。 CI 在可信網路中按 commit digest 拉取儲存庫,執行內容掃描和建置,產生帶來源標籤的不可變映像。部署只引用映像 digest,應用啟動不依賴 Git 服務可用性;回滾就是恢復上一個映像 digest。
- init container 替代。 init container 使用專用 ServiceAccount 或 Secret,只讀掛載憑據,固定 commit 後將內容寫入
emptyDir。主容器以 read-only 方式掛載同一目錄;拉取失敗時 Pod 不進入 Ready,避免應用看到半成品。
volumes:
- name: repo-data
emptyDir: {}
initContainers:
- name: fetch-repo
image: platform/git-sync:approved
volumeMounts:
- name: repo-data
mountPath: /work
containers:
- name: app
volumeMounts:
- name: repo-data
mountPath: /app/config
readOnly: true這是結構示意;映像、憑據投影、網路策略、校驗腳本和命令必須由平台標準固定,不能直接把佔位映像用於生產。
- 持續同步器。 如果內容需要熱更新,使用受控 sidecar 或節點外部同步器。同步到臨時目錄後校驗 commit、檔案清單和權限,再原子替換版本目錄;失敗時保留目前有效版本。應用必須支援 reload 或明確重啟視窗,不能假設檔案變化自動生效。
- 安全與供應鏈。 禁止把長期 token 寫入 Pod spec 或日誌;限制儲存庫、分支和出口,校驗 TLS、known host、commit 簽名或可信 digest。同步器不應以 root 修改宿主機路徑,目錄權限應讓應用只讀。
- 灰度、阻斷與回滾。 升級前用 CI 掃描和 ValidatingAdmissionPolicy 阻止新 Pod 使用
gitRepo,同時保留遷移白名單。先在少量節點和工作負載重啟,驗證冷啟動、網路中斷、私有儲存庫憑據輪換、節點重排和擴縮容;舊模板只在新映像穩定後刪除。回滾恢復舊映像或舊同步器版本,不嘗試重新開啟 v1.36 已停用的外掛。
高品質示範回答
我會先用清單和渲染後的 Pod 模板盤點 gitRepo,把每個工作負載分成固定內容、啟動時內容和熱更新內容。固定內容放進 CI 建置的不可變映像並按 digest 部署;啟動時內容用最小權限 init container 按固定 commit 寫入 emptyDir,主容器只讀掛載;熱更新才引入同步器,並要求臨時目錄校驗後原子切換,失敗時保留舊版本。
所有路徑都要綁定儲存庫、commit、憑據、網路和權限邊界。token 不進入 spec 或日誌,拉取內容要驗證 TLS、known host、commit 或映像來源。升級前掃描模板、阻止新增 gitRepo,然後灰度重啟和重排,觀察 Pod 啟動時長、拉取失敗、內容 digest、Ready 狀態和回滾成功率。v1.36 已永久停用外掛,回滾只能回到替代方案或舊映像,不能依賴 feature gate 恢復舊行為。
常見錯誤
- 錯誤表現: 把儲存庫 URL 放進 ConfigMap,認為它會自動更新 → 失敗原因: ConfigMap 不執行 Git 拉取或版本校驗 → 修正方法: 明確建置期、init container 或同步器責任。
- 錯誤表現: init container 拉預設分支 → 失敗原因: 重啟結果不可重現,回滾無法證明 → 修正方法: 固定 commit,記錄 digest 和來源。
- 錯誤表現: 用 root 同步到宿主機共享目錄 → 失敗原因: 擴大節點攻擊面並繞過 Pod 隔離 → 修正方法: 使用 Pod 內卷、非 root、最小權限和只讀消費。
- 錯誤表現: 同步器直接覆蓋應用正在讀取的目錄 → 失敗原因: 應用可能讀到半套檔案 → 修正方法: 臨時目錄校驗後原子切換版本目錄。
- 錯誤表現: v1.36 升級後嘗試打開
GitRepoVolumeDriver→ 失敗原因: 外掛已永久停用,且安全風險未消失 → 修正方法: 回滾替代實作或舊叢集版本,並繼續遷移。
追問及應對
為什麼固定 commit 仍要做內容校驗?
commit pin 保證引用穩定,但不能證明儲存庫、依賴或建置環境可信。CI 仍應驗證簽名、來源、檔案清單、惡意內容掃描和映像 digest,並把證據關聯到發布版本。
私有儲存庫憑據應放在哪裡?
使用專用 Secret 或外部密鑰提供器,限制到目標命名空間和儲存庫範圍。透過環境變數或掛載檔案注入,避免寫入映像、Pod 註解和日誌,並安排輪換與撤銷。
init container 失敗時主容器會怎樣?
Pod 不會進入可用狀態,主容器不會正常啟動。應讓失敗原因可觀測,設定重試和退避,並用舊版本映像或預熱快取決定是否需要業務降級。
熱更新如何避免應用讀到半成品?
同步器寫入新版本目錄,完成 commit、清單和權限校驗後,再透過原子 rename 或符號連結切換。應用需要 reload 介面或重啟策略;切換失敗保留目前版本。
如何發現遺漏的 gitRepo?
同時掃描 API 物件、Helm/Kustomize 原始碼、渲染結果和准入變更器輸出。升級後監控棄用或未知欄位錯誤,並將掃描納入 CI,防止新模板重新引入。
參考資料
- Kubernetes v1.36 Sneak Peek(Kubernetes Blog)
- Volumes 文件(Kubernetes Documentation)
- Projected Volume 配置文件(Kubernetes Documentation)
- Kubernetes Deprecation Policy(Kubernetes Documentation)
面試作答要點
先區分固定、啟動拉取和熱更新三種語義,再分別設計映像、init container、同步器、權限、校驗、灰度和回滾。
一句話總結
gitRepo 移除遷移的核心是用可重現、最小權限、可校驗的內容交付鏈替代節點內隱式 Git 拉取。
繼續練習
如果儲存庫包含數 GB 模型和頻繁更新的設定,請比較映像分層、物件儲存、init container 和同步器的成本與一致性。