SLI/SLO/Error Budget#

上一章 12 可靠性與風險管理 決定了「該追求多少可靠性」,本章談的是如何把那個模糊的目標,量化成可衡量、可驅動決策的指標體系:用 SLI 衡量、用 SLO 設定目標、用 Error Budget 把目標轉化為發布節奏的籌碼。各類監控訊號(指標、日誌、追蹤)的採集細節見 09 可觀測性

三者辨析#

名詞中文本質範例
SLI(Service Level Indicator)服務等級指標一個量化的測量值成功請求數 / 總請求數 = 99.95%
SLO(Service Level Objective)服務等級目標對 SLI 設定的目標過去 28 天可用率 ≥ 99.9%
SLA(Service Level Agreement)服務等級協議對外承諾與罰則未達 99.5% 則賠償客戶

三者的關係層層遞進:SLI 是事實,SLO 是內部目標,SLA 是對外承諾。實務上 SLO 應該嚴於 SLA,留出緩衝——對外承諾 99.5%,對內就該瞄準 99.9%,這樣在真正觸及 SLA 紅線前還有反應空間。

SLA 一旦寫進合約就帶有法律與賠償後果,因此通常比 SLO 寬鬆。工程團隊日常盯的是 SLO,而不是 SLA。

如何選 SLI#

好的 SLI 直接反映使用者的體驗,而不是反映系統的內部狀態。挑選原則:

  • 從使用者價值倒推:問「使用者在乎什麼?」——通常是「請求有沒有成功」「回應夠不夠快」「資料是不是新的」,而不是「CPU 用了多少」。
  • 用百分位而非平均值:平均延遲會被大量快請求拉低,掩蓋掉長尾的糟糕體驗。應該用 P95、P99 這類百分位,因為使用者體驗到的是「我這一次」而不是「平均下來」。
  • 比率形式最易用:把 SLI 表達為「好事件 / 有效事件」的比率,落在 0–100% 之間,天然適合設定門檻。

常見的 SLI 類型,可依服務性質挑選一到數個組合使用:

SLI 類型衡量什麼典型定義適用服務
可用性(Availability)請求是否成功成功請求數 / 總請求數幾乎所有服務
延遲(Latency)回應是否夠快延遲低於門檻的請求數 / 總請求數互動式服務
品質(Quality)降級回應的比例完整回應數 / 總回應數有降級機制的服務
新鮮度(Freshness)資料是否夠新在時限內更新的資料 / 全部資料批次、快取、管線
正確性(Correctness)輸出是否正確正確結果數 / 總結果數資料處理、計算服務
吞吐量(Throughput)資料傳輸是否達標達標傳輸數 / 總傳輸數大檔傳輸、串流

如何訂 SLO#

  • 不要從現狀出發:如果直接拿「目前系統剛好能做到 99.7%」當目標,等於把現況合理化。SLO 應由 12 章 的風險決策反推——使用者真正需要多少。
  • 留安全餘裕:對外 SLA 與對內 SLO 之間要留緩衝;同樣地,內部營運目標(如告警觸發點)又該比 SLO 更嚴,讓問題在燒穿預算前就被攔截。
  • 目標數字要少而精:SLO 太多會稀釋注意力。聚焦在少數幾個真正代表使用者體驗的 SLI 上。
  • SLO 是活的:隨業務演進定期檢視,過嚴拖慢迭代、過鬆傷害使用者,都要調整。

Error Budget 與停機時間換算#

Error Budget(錯誤預算)是 SLO 的另一面:

$$\text{Error Budget} = 1 - \text{SLO}$$

它代表「在不違反 SLO 的前提下,這段期間允許失敗的額度」。把可用率目標換算成可容忍的停機時間:

$$\text{允許停機時間} = (1 - \text{SLO}) \times \text{時間週期}$$

以一個月(取 $30$ 天 $= 43200$ 分鐘)為週期,常見可用率對應的每月可容忍停機如下:

$$T_{\text{down}} = (1 - 0.999) \times 43200\ \text{min} = 43.2\ \text{min}$$

SLO(可用率)錯誤預算每月可容忍停機每年可容忍停機
99%1%約 7.2 小時約 3.65 天
99.9%0.1%約 43.2 分鐘約 8.76 小時
99.95%0.05%約 21.6 分鐘約 4.38 小時
99.99%0.01%約 4.32 分鐘約 52.6 分鐘
99.999%0.001%約 25.9 秒約 5.26 分鐘

「每多一個 9」對應的可容忍停機時間就少一個數量級。這正是 12 章 成本曲線陡升的量化來源——從 99.9% 到 99.99%,等於把每月的「失敗額度」從 43 分鐘壓縮到 4 分鐘。

用錯誤預算驅動發布節奏#

Error Budget 最大的價值在於把「穩定」與「創新」之間的張力,變成一條客觀的決策規則,而不是靠開發與維運互相角力:

  • 預算還很充裕 ➡️ 可以大膽發布、實驗、承擔變更風險。
  • 預算快要耗盡 ➡️ 凍結非必要的功能發布,把工程力轉向修穩定性問題,直到預算回補。
  • 預算已經燒穿 ➡️ 只允許修復可靠性的變更上線,新功能全部排隊等待。
flowchart TD
    A[計算當期已消耗的 Error Budget] --> B{預算餘額?}
    B -->|充裕| C[正常發布<br/>可承擔變更風險]
    B -->|偏低| D[放慢節奏<br/>凍結非必要發布]
    B -->|耗盡| E[發布凍結<br/>只准修穩定性]
    C --> F[持續監控 SLI]
    D --> F
    E --> G[預算回補後解凍]
    G --> F
    F --> A

這條規則之所以有效,是因為它讓「該不該發布」不再是立場之爭:只要 SLO 與預算是雙方共同認可的,後續的放行或凍結就只是查表,沒有情緒。

SLO 設定範例#

以 YAML 描述一組 SLO,可被告警系統與發布閘門共同消費:

service: checkout-api
slos:
  - name: availability
    description: "成功處理的結帳請求比例"
    sli:
      good: 'http_requests_total{status!~"5..",route="/checkout"}'
      total: 'http_requests_total{route="/checkout"}'
    objective: 0.999 # 99.9%
    window: 28d # 滾動窗口
  - name: latency
    description: "P99 結帳延遲低於 500ms 的比例"
    sli:
      good: 'http_request_duration_seconds_bucket{le="0.5",route="/checkout"}'
      total: 'http_request_duration_seconds_count{route="/checkout"}'
    objective: 0.99
    window: 28d
error_budget_policy:
  - condition: "budget_remaining > 50%"
    action: "正常發布"
  - condition: "budget_remaining <= 50%"
    action: "放慢發布、優先修穩定性"
  - condition: "budget_remaining <= 0%"
    action: "凍結功能發布,只准可靠性修復"
燃燒率(Burn Rate)告警

比起「預算剩多少」,更靈敏的做法是看「預算消耗得多快」——燃燒率(burn rate)。

燃燒率 = 1 表示按 SLO 允許的速度均勻消耗,剛好在窗口結束時用完預算;燃燒率 = 14.4 表示如果持續這個速度,會在窗口的 $1/14.4$ 時間內就燒光整月預算。

$$\text{Burn Rate} = \frac{\text{實際錯誤率}}{1 - \text{SLO}}$$

實務上用「多窗口、多燃燒率」組合告警:高燃燒率(如 14.4 倍)配短窗口,捕捉突發大故障;低燃燒率(如 3 倍)配長窗口,捕捉緩慢滲漏。告警規則的具體寫法見 16 On-Call 與告警設計

小結#

  • SLI 是事實、SLO 是內部目標、SLA 是對外承諾;SLO 應嚴於 SLA 並留緩衝。
  • 選 SLI 從使用者價值倒推、用百分位、表達成比率;訂 SLO 不從現狀出發、保留安全餘裕。
  • Error Budget = 1 − SLO,可換算成具體的可容忍停機時間,量化了「每多一個 9」的代價。
  • 用錯誤預算驅動發布節奏,把穩定與創新的張力變成客觀、可查表的決策規則。