題干與適用場景
Kubernetes v1.36 將宣告式驗證提升為 GA,並預設啟用 DeclarativeValidation feature gate。驗證規則以 +k8s: 標記寫在型別定義旁,由 validation-gen 產生驗證程式碼。題目考察你能否把 API 契約、產生器、相容性與發布流程連成閉環。
面試官考察點
- 能否說明手寫驗證的維護與一致性風險。
- 能否區分宣告式規則、產生程式碼、OpenAPI 暴露與執行期拒絕。
- 能否正確解釋 ambient ratcheting 對舊物件更新的影響。
- 能否設計測試、回滾與漸進遷移,避免驗證收緊破壞既有物件。
回答前需要釐清的問題
先確認 API 是 Kubernetes 原生型別還是 CRD、用戶端是否依賴 OpenAPI,以及約束改變屬於新增、放寬或收緊。還要確認舊物件是否可能包含歷史上已被接受的值,以及產生器、linter 與伺服器版本的相容範圍。
30 秒回答框架
宣告式驗證把約束放在型別定義附近,由產生器統一產出程式碼並可映射到 OpenAPI。方案要同時覆蓋規則設計、產生與靜態檢查、伺服器執行期驗證、舊物件相容與發布回滾。收緊規則時依靠 ambient ratcheting 保護未改變欄位,但對新值仍應先做相容性評估與灰度驗證。
分步驟深入解答
1. 定義規則來源
用 +k8s:required、+k8s:minimum=0 或列舉等標記表達可發現的約束,把語意與欄位放在同一型別檔案。複雜跨欄位規則要明確不變量、錯誤訊息與適用版本,避免把業務邏輯藏在產生器之外。
2. 產生並驗證
validation-gen 解析標記並產生 Go 驗證函式,再註冊到 API scheme。CI 中同時執行產生器、單元測試、kube-api-linter 與 OpenAPI 差異檢查,防止標記、產生程式碼與公開 schema 漂移。產生物應可重複建置,避免手工修改被覆蓋。
3. 處理版本演進
新增約束先評估舊物件與用戶端行為。ambient ratcheting 會比較新舊物件:欄位語意未改變時,新規則不會因舊值而阻斷更新;欄位被修改時仍要符合新規則。對收緊規則應提供遷移工具、稽核指標與明確失敗訊息。
4. 發布與回滾
先在相容性測試集與影子驗證中觀察拒絕率,再分階段啟用。監控 API 錯誤碼、資源版本與用戶端重試;若錯誤率異常,回退產生器或規則版本,並保留已接受物件的可讀性。GA feature gate 預設開啟不代表可以跳過遷移驗證。
高品質示範回答
我會把驗證視為版本化 API 契約。欄位附近用 +k8s: 標記表達基礎約束,validation-gen 產生可重複的 Go 程式碼,CI 再用單元測試、linter 與 OpenAPI 差異檢查驗證三者一致。跨欄位不變量要有獨立測試與穩定錯誤資訊,產生物禁止手改。
規則收緊前,我會回放既有物件並統計用戶端行為。ambient ratcheting 只豁免未改變的舊值,使用者一旦修改該欄位仍需符合新規則,因此仍要提供遷移工具與灰度發布。上線後觀察拒絕率、版本分布與重試,必要時回退規則版本;宣告式驗證 GA 提供統一機制,但不取代相容性治理。
常見錯誤
- 認為產生器只是程式碼格式工具,忽略它決定伺服器執行期行為。
- 把 OpenAPI schema 當作唯一驗證點,遺漏伺服器產生程式碼與版本相容。
- 誤解 ambient ratcheting 為永久放寬規則,忽略欄位被修改時仍會驗證。
- 只寫新增規則,不準備既有物件遷移、灰度指標與回滾方案。
追問及應對
為什麼不繼續手寫驗證函式?
手寫邏輯分散、難發現且容易在資源間產生不一致。標記、產生器與 linter 讓規則可審查、可重複建置,也更容易發布到 OpenAPI。
收緊最小值會不會立刻破壞舊物件?
更新未改變該欄位時,ambient ratcheting 可保留歷史值;但建立新物件或修改該欄位必須符合新規則。仍需盤點讀取、複製與重寫物件的用戶端路徑。
如何驗證產生程式碼沒有漂移?
在 CI 固定產生器版本,執行產生後檢查工作區無差異,並比較 OpenAPI、單元測試與端到端拒絕結果。升級產生器時先審查產生 diff,再進入灰度。