發布概述#

發布是持續交付的「最後一公里」,是將經過驗證的製品部署到生產環境的過程。發布系統的設計直接影響發布的效率、安全性和使用者體驗。

發布是高風險操作。大部分線上故障都與發布相關。良好的發布系統設計可以顯著降低發布風險,提升系統穩定性。

發布的五個步驟#

一次完整的發布通常包含以下五個步驟:

步驟英文說明
下線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

發布流程:

  1. 在綠環境部署新版本
  2. 測試綠環境
  3. 切換流量到綠環境
  4. 藍環境作為備用(回滾時切回)

優點:

  • 回滾極快(只需切換流量)
  • 新舊版本完全隔離

缺點:

  • 需要雙倍資源
  • 資料庫結構變更需要特別處理

滾動部署(Rolling Deployment)#

滾動部署逐批次更新伺服器,不需要額外的環境資源。

批次伺服器狀態說明
批次 1🟢⚪⚪⚪⚪更新第一台
批次 2🟢🟢⚪⚪⚪更新第二台
批次 3🟢🟢🟢⚪⚪更新第三台
完成🟢🟢🟢🟢🟢全部更新完成

🟢 = 新版本,⚪ = 舊版本

發布流程:

  1. 選擇一批伺服器下線
  2. 更新這批伺服器
  3. 驗證後上線
  4. 重複直到全部更新

優點:

  • 資源利用率高
  • 可以控制發布節奏

缺點:

  • 發布過程中新舊版本共存
  • 回滾需要重新部署

滾動部署時,應該確保新舊版本的 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);
}

好處:

  • 部署和發布解耦
  • 可以按用戶群體逐步開放
  • 問題時可以快速關閉功能(無需部署)

組合策略:

  1. 使用滾動部署更新所有伺服器(功能關閉狀態)
  2. 使用特性標記逐步開放功能
  3. 問題時關閉標記,而非回滾部署

不可變基礎設施#

不可變基礎設施(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" # 聖誕節
發布事故案例

案例:資料庫結構變更導致的故障

場景:新版本需要修改資料庫表結構

錯誤做法:

  1. 先修改資料庫
  2. 再部署新版本
  3. 部署過程中舊版本報錯

正確做法(向後相容遷移):

  1. 新增欄位(允許為空或有預設值)
  2. 部署新版本(同時支援新舊欄位)
  3. 資料遷移
  4. 移除舊欄位的程式碼
  5. 刪除舊欄位

教訓:

  • 資料庫變更應該向後相容
  • 大的變更應該拆分為多個小步驟
  • 每個步驟都應該可以獨立回滾

業務架構對發布的影響#

系統架構會影響發布策略的選擇和實施難度。

單體 vs 微服務#

方面單體架構微服務架構
發布粒度整體發布可以單獨發布
影響範圍所有功能單個服務
依賴管理簡單複雜
回滾難度簡單需要考慮服務依賴

微服務發布順序#

當多個服務需要協同發布時:

依賴關係: A → B → C

發布順序:
1. 先發布 C(最底層,被依賴的服務)
2. 再發布 B
3. 最後發布 A(最上層,呼叫方)

回滾順序: A → B → C(與發布順序相反)

微服務的介面變更需要考慮相容性。不相容的介面變更應該透過版本化 API 來處理,而不是強制所有相關服務同時發布。

總結#

發布系統是持續交付的關鍵基礎設施,良好的發布系統設計可以顯著降低發布風險,提升發布效率。

關鍵要點:

  1. 發布策略選擇

    • 藍綠部署:快速回滾,資源需求高
    • 滾動部署:資源效率高,回滾較慢
    • 金絲雀發布:風險最低,週期較長
  2. 不可變基礎設施

    • 禁止修改運行中的伺服器
    • 任何變更都透過部署新版本實作
    • 容器化是最佳實作方式
  3. 發布系統設計

    • 精確的狀態機管理
    • 良好的用戶體驗
    • 完善的安全控制
  4. 架構考量

    • 理解業務架構對發布的影響
    • 微服務需要考慮服務依賴和介面相容性

發布系統的終極目標是讓發布變得「無聊」——沒有驚險、沒有意外、隨時可以發布、隨時可以回滾。達到這個狀態,需要在流程、工具、文化三個方面持續投入。