恢復力與部署安全
概述
事情總會出錯。我們的立場不是「預防所有失敗」,而是小規模失敗、快速恢復、每次學習。可靠性並非沒有失敗,而是在失敗發生時,能夠控制爆炸半徑並縮短恢復時間。
部署安全 — 每個部署都可逆且漸進式暴露
- 工件是不可變的,並且透過晉升而非重建。 一個映像檔,在 CI 中建構一次並由其內容摘要識別,依序在預覽 → 暫存 → 生產環境之間移動,不做任何變更。為每個環境重建等同於部署了你從未測試過的內容。
- 標籤是可變的指標;摘要是身份。 標籤可以被覆寫,並默默地指向新的位置。內容摘要則無法。每個環境會記錄它驗證過的摘要,而生產環境只會執行經過較低環境驗證的摘要 — 因此「我們測試過的確切內容」是管道強制執行的屬性,而非需要某人記住的紀律。
- 生產環境的部署需要經過人為決策。 對於獨立維護者而言,這是一個刻意的暫停和審計記錄,而非職責分離。請說明是哪一種情況;不要過度承諾。
- 執行中的版本是在部署時注入的,永遠不應內建到映像檔中。 將版本作為建構參數內建會迫使為了標記版本而重建,而重建正是晉升機制所要避免的。
- 當基礎架構存在於自己的儲存庫時,透過擴張/收縮來協調。 基礎架構先擴張(新增、向後相容),應用程式在後續部署中使用新功能,然後收縮基礎架構(僅在沒有任何線上工件依賴舊結構時才進行)— 這與資料庫綱要變更的紀律相同(參見
zero-downtime-migrations)。不變條件:絕不部署一個需要尚未上線的基礎架構變更的應用程式工件。 遵守這點,每個儲存庫都能獨立回滾,這使得在兩者不同步時回滾變得可行。 - 僅在能夠回滾時才向前推進。 在風險變更上線之前,就需要存在並測試過回滾路徑。「我們要如何撤銷這個?」這個問題應在計劃中回答,而非在事件發生期間。
- 回滾就是重新部署先前良好的摘要。 該摘要仍然存在於登錄檔中且不可變,因此回滾就是反向的晉升 — 永遠不需要重建,也永遠不需要「照原樣」重建。
- 漸進式暴露。 新版本逐步到達使用者手中(健康檢查門控的金絲雀部署),因此壞版本只會影響一部分使用者,而非所有人。
- 綱要變更與程式碼部署解耦,並遵循擴張/收縮模式(參見
zero-downtime-migrations)。部署絕不能要求同時執行破壞性遷移。 - 部署就緒檢查清單門控生產環境: 可觀察性到位、回滾已驗證、遷移擴張安全、SLO 未中斷。
事件應對 — 失敗是學習的輸入
- 依嚴重性分類並按比例回應;要有已知的途徑來聯繫適當的人員。
- 每個影響使用者的事件都要進行無責備事後檢討。 記錄時間線、促成原因(系統性,而非個人)、具體行動項目。問題是「系統的哪個部分讓這件事發生」,絕非「誰搞砸了」。
- 行動項目應被追蹤,而非遺忘 — 它們應流入未來考量文件(參見
recording-decisions)並成為實際工作。 - 由錯誤預算來治理。 當可靠性預算已用盡時,可靠性工作的優先級高於功能,直到預算恢復。
快速參考
| 風險部署前 | 確認事項 |
|---|---|
| 工件 | 在 CI 中建構一次;透過摘要晉升;與暫存環境驗證過的相同 |
| 關卡 | 在進入生產環境前記錄人為決策 |
| 回滾 | 存在路徑並已測試 |
| 暴露 | 漸進式/金絲雀,而非一次全部 |
| 綱要 | 擴張安全,與程式碼部署解耦 |
| 可觀察性 | 你能看出它是否出錯了嗎? |
何時擴展此技能
本地/發佈前專案現在就遵循這些規則,在第一批真實使用者上線時啟用。這些屬性是可移植的 — 建構一次、晉升經過測試的內容、在生產前決策、能夠回滾 — 但其機制並非如此:摘要晉升在容器主機上有意義,但對靜態網站來說 largely moot,而託管平台可能免費提供預覽環境和即時回滾。請在專案的交付技能中命名該機制;在此技能中保留屬性。疊加機制(k8s 探針、金絲雀、每個 PR 的環境):cloud-delivery-aks。
完整理由:章程第十二條,捆綁在 engineering-constitution/references/engineering-constitution.md 中。