發布概述#
發布是持續交付的「最後一公里」,是將經過驗證的製品部署到生產環境的過程。發布系統的設計直接影響發布的效率、安全性和使用者體驗。
發布是高風險操作。大部分線上故障都與發布相關。良好的發布系統設計可以顯著降低發布風險,提升系統穩定性。
發布的五個步驟#
一次完整的發布通常包含以下五個步驟:
| 步驟 | 英文 | 說明 |
|---|---|---|
| 下線 | Markdown | 將目標伺服器從負載均衡摘除 |
| 下載 | Download | 將製品下載到目標伺服器 |
| 安裝 | Install | 解壓、組態、啟動應用 |
| 驗證 | Verify | 檢查應用是否正常運行 |
| 上線 | Markup | 將伺服器重新加入負載均衡 |
flowchart LR
A[Markdown<br/>下線] --> B[Download<br/>下載]
B --> C[Install<br/>安裝]
C --> D[Verify<br/>驗證]
D --> E[Markup<br/>上線]
D -->|失敗| F[Rollback<br/>回滾]
style A fill:#ffecb3
style E fill:#c8e6c9
style F fill:#ffcdd2灰度發布策略#
灰度發布(也稱為漸進式發布)是降低發布風險的重要手段,核心思想是逐步將流量切換到新版本。
藍綠部署(Blue-Green Deployment)#
藍綠部署維護兩套完整的生產環境,一套運行舊版本(藍),一套部署新版本(綠)。
flowchart TB
LB[Load Balancer]
LB --> Blue
LB --> Green
subgraph Blue["藍環境 (當前)"]
B1["v1.0.0"]
end
subgraph Green["綠環境 (新版本)"]
G1["v1.1.0"]
end
style Blue fill:#bbdefb
style Green fill:#c8e6c9發布流程:
- 在綠環境部署新版本
- 測試綠環境
- 切換流量到綠環境
- 藍環境作為備用(回滾時切回)
優點:
- 回滾極快(只需切換流量)
- 新舊版本完全隔離
缺點:
- 需要雙倍資源
- 資料庫結構變更需要特別處理
滾動部署(Rolling Deployment)#
滾動部署逐批次更新伺服器,不需要額外的環境資源。
| 批次 | 伺服器狀態 | 說明 |
|---|---|---|
| 批次 1 | 🟢⚪⚪⚪⚪ | 更新第一台 |
| 批次 2 | 🟢🟢⚪⚪⚪ | 更新第二台 |
| 批次 3 | 🟢🟢🟢⚪⚪ | 更新第三台 |
| … | … | … |
| 完成 | 🟢🟢🟢🟢🟢 | 全部更新完成 |
🟢 = 新版本,⚪ = 舊版本
發布流程:
- 選擇一批伺服器下線
- 更新這批伺服器
- 驗證後上線
- 重複直到全部更新
優點:
- 資源利用率高
- 可以控制發布節奏
缺點:
- 發布過程中新舊版本共存
- 回滾需要重新部署
滾動部署時,應該確保新舊版本的 API 相容。可以使用「先擴展後收縮」的策略:新版本先支援舊 API,發布完成後再移除舊 API。
金絲雀發布(Canary Release)#
金絲雀發布先將小部分流量(如 1%)導向新版本,觀察後再逐步擴大比例。
| 階段 | 新版本流量 | 舊版本流量 |
|---|---|---|
| 第一階段 | 1% | 99% |
| 第二階段 | 10% | 90% |
| 第三階段 | 50% | 50% |
| 完成 | 100% | 0% |
優點:
- 風險極低(問題只影響少量用戶)
- 可以基於真實流量驗證
- 支援 A/B 測試
缺點:
- 需要流量控制能力
- 發布週期較長
策略選擇指南#
| 策略 | 資源需求 | 回滾速度 | 風險控制 | 適用場景 |
|---|---|---|---|---|
| 藍綠 | 高 | 極快 | 中 | 關鍵服務、需要快速回滾 |
| 滾動 | 低 | 較慢 | 中 | 資源有限、無狀態服務 |
| 金絲雀 | 中 | 快 | 高 | 高流量服務、需要驗證效果 |
特性標記與發布策略結合
特性標記(Feature Flag)可以與發布策略結合,實作更靈活的發布控制:
部署 vs 發布分離
// 程式碼已部署,但功能通過開關控制
if (featureFlag.isEnabled("new-payment-flow", user)) {
return newPaymentService.process(order);
} else {
return oldPaymentService.process(order);
}好處:
- 部署和發布解耦
- 可以按用戶群體逐步開放
- 問題時可以快速關閉功能(無需部署)
組合策略:
- 使用滾動部署更新所有伺服器(功能關閉狀態)
- 使用特性標記逐步開放功能
- 問題時關閉標記,而非回滾部署
不可變基礎設施#
不可變基礎設施(Immutable Infrastructure)是現代發布系統的重要理念。
核心思想#
伺服器一旦部署,就不再修改。任何變更都透過部署新版本實作。
傳統方式(可變):
伺服器 → 組態變更 → 軟體更新 → 補丁安裝 → ... → 狀態不可預測不可變方式:
映像 v1 → 部署 → 運行
映像 v2 → 部署 → 運行(替換舊實例)
映像 v3 → 部署 → 運行(替換舊實例)三種基礎設施模式#
| 模式 | 說明 | 問題 |
|---|---|---|
| 發散型 | 手動維護,逐步漂移 | 每台伺服器狀態不同 |
| 收斂型 | 組態管理工具定期同步 | 同步間隙可能不一致 |
| 不可變 | 禁止修改,只能替換 | 需要完善的自動化能力 |
實作不可變基礎設施#
容器化是實作不可變基礎設施的最佳方式:
# Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
containers:
- name: app
image: myapp:v1.2.3 # 固定版本好處:
- 環境狀態完全可預測
- 部署即版本控制
- 回滾就是重新部署舊版本
發布系統設計#
一個成熟的發布系統需要考慮多個方面的設計。
核心架構#
flowchart TB
subgraph RS["發布系統"]
direction TB
subgraph UI["控制層"]
A1["Web UI"]
A2["API 服務"]
A3["任務引擎"]
A4["狀態機"]
end
subgraph Infra["基礎設施層"]
B1["製品倉庫"]
B2["組態中心"]
B3["Agent"]
B4["監控整合"]
end
end
RS --> S1["Server 1"]
RS --> S2["Server 2"]
RS --> S3["Server 3"]
style UI fill:#e3f2fd
style Infra fill:#fff3e0狀態機設計#
發布過程是一個狀態機,需要精確管理每個狀態的轉換:
stateDiagram-v2
[*] --> Pending: 建立發布任務
Pending --> Running: 開始發布
Running --> Success: 發布成功
Running --> Failed: 發布失敗
Failed --> Rollback: 執行回滾
Success --> Rollback: 回滾已發布版本
Rollback --> [*]: 回滾完成狀態定義:
| 狀態 | 說明 | 允許的操作 |
|---|---|---|
| Pending | 等待發布 | 開始、取消 |
| Running | 發布進行中 | 暫停、繼續、回滾 |
| Paused | 暫停中 | 繼續、回滾 |
| Success | 發布成功 | 回滾 |
| Failed | 發布失敗 | 重試、回滾 |
| Rollback | 回滾中 | - |
用戶體驗設計#
發布系統的用戶是開發和維運人員。良好的用戶體驗可以減少操作錯誤,提高發布效率。
1-2-3-4-5-6 設計原則:
| 原則 | 說明 |
|---|---|
| 1 個目標 | 發布系統的唯一目標是安全高效地完成發布 |
| 2 種用戶 | 普通用戶(開發)和管理員(維運) |
| 3 步完成 | 選擇服務 → 選擇版本 → 確認發布 |
| 4 種視圖 | 列表、詳情、日誌、監控 |
| 5 個階段 | Markdown → Download → Install → Verify → Markup |
| 6 項功能 | 發布、回滾、暫停、繼續、重試、取消 |
發布進度展示:
發布進度: user-service v1.2.3 → Production
[■■■■■■■■■░░░░░░░░░░░] 45%
批次 1/3: ████████████████ 完成 (3/3)
批次 2/3: ████████░░░░░░░░ 進行中 (1/3)
批次 3/3: ░░░░░░░░░░░░░░░░ 等待
當前操作: server-prod-02 正在下載製品...
[暫停] [繼續] [回滾]安全控制#
發布審批流程:
flowchart LR
A[開發提交] --> B[自動測試]
B --> C[Code Review]
C --> D[預發布驗證]
D --> E{發布審批}
E -->|批准| F[生產發布]
style E fill:#fff3e0
style F fill:#c8e6c9權限控制:
| 角色 | 權限 |
|---|---|
| 開發人員 | 發布到開發/測試環境 |
| 測試人員 | 發布到 UAT 環境 |
| 發布負責人 | 發布到預發布環境 |
| 維運人員 | 發布到生產環境 |
發布窗口控制:
release_windows:
production:
allowed_days: [Tuesday, Thursday]
allowed_hours: "10:00-16:00"
blackout_periods:
- "2023-11-11" # 雙十一
- "2023-12-25" # 聖誕節發布事故案例
案例:資料庫結構變更導致的故障
場景:新版本需要修改資料庫表結構
錯誤做法:
- 先修改資料庫
- 再部署新版本
- 部署過程中舊版本報錯
正確做法(向後相容遷移):
- 新增欄位(允許為空或有預設值)
- 部署新版本(同時支援新舊欄位)
- 資料遷移
- 移除舊欄位的程式碼
- 刪除舊欄位
教訓:
- 資料庫變更應該向後相容
- 大的變更應該拆分為多個小步驟
- 每個步驟都應該可以獨立回滾
業務架構對發布的影響#
系統架構會影響發布策略的選擇和實施難度。
單體 vs 微服務#
| 方面 | 單體架構 | 微服務架構 |
|---|---|---|
| 發布粒度 | 整體發布 | 可以單獨發布 |
| 影響範圍 | 所有功能 | 單個服務 |
| 依賴管理 | 簡單 | 複雜 |
| 回滾難度 | 簡單 | 需要考慮服務依賴 |
微服務發布順序#
當多個服務需要協同發布時:
依賴關係: A → B → C
發布順序:
1. 先發布 C(最底層,被依賴的服務)
2. 再發布 B
3. 最後發布 A(最上層,呼叫方)
回滾順序: A → B → C(與發布順序相反)微服務的介面變更需要考慮相容性。不相容的介面變更應該透過版本化 API 來處理,而不是強制所有相關服務同時發布。
總結#
發布系統是持續交付的關鍵基礎設施,良好的發布系統設計可以顯著降低發布風險,提升發布效率。
關鍵要點:
發布策略選擇
- 藍綠部署:快速回滾,資源需求高
- 滾動部署:資源效率高,回滾較慢
- 金絲雀發布:風險最低,週期較長
不可變基礎設施
- 禁止修改運行中的伺服器
- 任何變更都透過部署新版本實作
- 容器化是最佳實作方式
發布系統設計
- 精確的狀態機管理
- 良好的用戶體驗
- 完善的安全控制
架構考量
- 理解業務架構對發布的影響
- 微服務需要考慮服務依賴和介面相容性
發布系統的終極目標是讓發布變得「無聊」——沒有驚險、沒有意外、隨時可以發布、隨時可以回滾。達到這個狀態,需要在流程、工具、文化三個方面持續投入。