
每次變更都直接部署到正式環境可能很可怕,但不直接部署到正式環境更可怕。
這是當年我在 Amazon 帶領團隊服務數億客戶時所採用的流程。在我的顧問工作中,我帶領多個工程團隊,從每兩週的排程發佈,進化到每次合併(merge)就發佈上線。
先從顯而易見的部分開始:
你一定會造成服務中斷(outage)。這不是「會不會」的問題,而是「什麼時候」的問題。
無論多少單元測試、整合測試、內部試用(dogfooding)、端到端什麼的,或是向部署之神獻祭,都無法抓到所有 bug。
你一週前對功能所做的測試,並沒有涵蓋到你同事最新的變更。
你的測試是針對同事服務的 pre-prod 版本跑的,而那個版本現在已經改變,還包含了一個向後不相容的變更。
你等得越久,release 上堆疊的變更就越多。如果真的需要 rollback,你得回滾兩週的變更,而不是 1-2 小時的變更。
如果我們接受「服務中斷無可避免」這項前提,花費大量資源為 release 做 QA 就顯得意義不大;相反的,我們應該把資源集中在監控與觀察 release,並準備好在服務中斷發生時立即處理。
接下來,我們來談談怎麼達成:
前置條件:
CI/CD
測試的重要性遠低於你的想像。測試無法證明你的變更在正式環境是安全的,沒有任何東西能證明。測試的價值在於讓失敗變得很便宜。在 CI 抓到的 bug 只花幾分鐘;在正式環境抓到的 bug 會燒掉你一整個晚上做 rollback。
所以,每次 merge 都要跑完整的測試套件,或至少作為 pipeline 的一部分:單元測試、整合測試、端到端測試。Bug 在 pipeline 中走得越遠,解決的成本就越高。
監控/可觀測性(Monitoring/Observability)
重點在於盡可能早地抓到 regression。要達成這點,你需要一流的監控。具體形式包括:
- metrics:錯誤率、延遲、可用性
- 帶有 correlation id 的 logs
- 針對上述兩者設定的 sev-3 與 sev-2(paging)alarms
調整 alarm 閾值既是一門藝術,也是一門科學。你需要在敏感度與真實 incident 發生時的反應速度之間取得平衡。sev-2 的目標警示時間應該是 5-10 分鐘。
一開始,你的設定很可能會出錯,而且很可能太敏感。不幸的是,這主要靠試誤來學習,所以你可能會先經歷幾次凌晨 2 點被叫醒。
Feature Flags
任何有風險的變更,都應該透過 feature flag/remote config 來發佈。Feature flag 讓你能在幾分鐘內回滾或關閉任何變更,而不需要回滾整個部署。此外,如果你的 feature flag 服務支援的話(應該要支援),你可以按百分比或特定群組逐步推出功能,進一步降低不良變更的影響。
這讓我們能將「部署程式碼」與「啟動程式碼」兩件事解耦。這雖然細微,卻是降低風險的遊戲規則改變者。
注意:你需要一個清理這些 flag 的流程。理想上,每建立一個 flag 就開一張移除 ticket。否則,當你的 feature flag 服務掛掉時(它總會掛的),你會遭遇嚴重的 regression。想知道我怎麼知道的嗎?問我就好。
自動回滾(部署時的 circuit breaker)
部署時的 circuit breaker 是一種功能:當你在將部署推送到整個 fleet 的過程中,看到特定數量或比例的錯誤時,就能自動回滾部署。現在大部分雲端服務供應商都有這個功能,勾選一個核取方塊即可。
向後相容的變更
你本來就應該這樣做,但每次 commit 都部署會強迫你落實這項做法。在滾動部署(rolling deployment)期間,舊版本和新版本會同時運行。每一項變更都必須能與前一個版本並存。你過去靠「半夜部署」來閃避這個問題的招數,已經行不通了。
部署策略
有了上述基礎,我們可以來看看幾種不同的部署策略,幫助你在推出變更時降低風險。
單一主機(Canary)
單一主機部署是將你的變更部署到整個 fleet 中的一台機器上。這樣可以將任何不良變更的影響範圍縮小到只有一台 host。
你部署後讓它運行一段時間,接收整體流量中的一小部分。你在這台機器上設定好監控與 alerting,一旦有任何問題就會發出警示。
滾動部署(Rolling Deployments)
滾動部署讓你能按百分比逐步推出,如果發生災難性錯誤,你可以在它影響所有機器之前發現,然後開始回滾。
區域 rollout
隨著公司成長,你最終會有多區域部署。與其同時部署到所有區域,你可以先部署到某一個特定區域(通常是流量最低的那個)。
不適用的情況
App Store
發佈手機 App 並不完全適用這個指南。App Store 的審查佇列會限制你的部署節奏,需要不同的策略。
認證環境
醫療設備、航空電子、工業控制等。如果你需要監管機構認證 build,你就無法持續部署。
地端/自架(On-prem / Self-hosted)
你無法控制升級時機。你還是可以對你營運的所有系統持續部署,但必須為每個變更建立版本,由客戶決定何時採用。
從哪裡開始
不要一次做完所有事情。順序很重要:
- 讓 CI 保持綠色且快速。理想上 15 分鐘內完成
- 針對錯誤率、延遲與可用性建立 metrics 與 alarms。這是整個過程中最重要的一環
- 把所有有風險的變更放到 flag 後面
- 加入單一主機部署 + 自動回滾
- 刪掉 release 行事曆
- 既然不用再安排 release,為你多出來的時間找新的用途
我合作過的大多數團隊大約花一季就能完成這些。工具反而是最簡單的部分。組織流程,以及打破「排程發佈很安全」的幻覺,才是最困難的部分。
如果你的團隊還在用 release 行事曆,而且想擺脫它,那就是我在做的工作。私訊我。





