ストーリー
佐藤CTOはグラフを描きながら続けます。
エラーバジェットとは
基本概念
エラーバジェットは「SLO目標を達成しつつ、許容できる不信頼性の量」です。
エラーバジェット = 100% - SLO目標
例: SLO = 99.9% の場合
エラーバジェット = 100% - 99.9% = 0.1%
→ 30日間で 0.1% × 30 × 24 × 60 = 43.2分 の障害が許容される
エラーバジェットが解決する問題
| 従来の対立 | エラーバジェットによる解決 |
|---|---|
| 開発チーム「もっとリリースしたい」 | バジェットが残っていればリリースOK |
| 運用チーム「変更は最小限にしたい」 | バジェット消費率で客観的に判断 |
| 経営層「速く、かつ安定して」 | SLOとバジェットで両方を数値管理 |
| 品質議論「十分安定しているのか?」 | エラーバジェットの残量で明確に回答 |
エラーバジェットの計算
基本的な計算
interface ErrorBudgetConfig {
sloTarget: number; // 例: 0.999 (99.9%)
windowDays: number; // 計測ウィンドウ(例: 30日)
totalRequests?: number; // リクエストベースの場合
}
interface ErrorBudgetStatus {
totalBudgetMinutes: number;
consumedMinutes: number;
remainingMinutes: number;
consumedPercentage: number;
burnRate: number; // 1.0 = 予定通りの消費速度
}
function calculateErrorBudget(
config: ErrorBudgetConfig,
downtimeMinutes: number
): ErrorBudgetStatus {
const totalMinutes = config.windowDays * 24 * 60;
const errorBudgetRatio = 1 - config.sloTarget;
const totalBudgetMinutes = totalMinutes * errorBudgetRatio;
const consumedPercentage = (downtimeMinutes / totalBudgetMinutes) * 100;
const burnRate = consumedPercentage / 100;
return {
totalBudgetMinutes,
consumedMinutes: downtimeMinutes,
remainingMinutes: totalBudgetMinutes - downtimeMinutes,
consumedPercentage,
burnRate,
};
}
// 例: SLO 99.9%, 30日ウィンドウ, これまでに15分のダウンタイム
const status = calculateErrorBudget(
{ sloTarget: 0.999, windowDays: 30 },
15
);
// totalBudgetMinutes: 43.2分
// consumedMinutes: 15分
// remainingMinutes: 28.2分
// consumedPercentage: 34.7%
// burnRate: 0.347
リクエストベースのエラーバジェット
function calculateRequestBasedBudget(
sloTarget: number,
totalRequests: number,
failedRequests: number
): {
allowedErrors: number;
actualErrors: number;
remainingBudget: number;
budgetConsumedPercent: number;
} {
const allowedErrors = Math.floor(totalRequests * (1 - sloTarget));
const remainingBudget = allowedErrors - failedRequests;
const budgetConsumedPercent = (failedRequests / allowedErrors) * 100;
return {
allowedErrors,
actualErrors: failedRequests,
remainingBudget,
budgetConsumedPercent,
};
}
// 例: SLO 99.9%, 今月100万リクエスト, 500リクエスト失敗
const reqBudget = calculateRequestBasedBudget(0.999, 1_000_000, 500);
// allowedErrors: 1000
// actualErrors: 500
// remainingBudget: 500
// budgetConsumedPercent: 50%
エラーバジェットポリシー
エラーバジェットポリシーは、バジェットの消費状況に応じて取るべきアクションを定義したものです。
ポリシーテンプレート
# エラーバジェットポリシー
service: "payment-service"
slo_target: 99.95%
window: 30days
# バジェット消費レベルごとのアクション
levels:
green:
condition: "消費率 < 50%"
actions:
- 通常のリリースサイクルを継続
- リスクの高い変更(大規模リファクタリング等)も許可
- 新機能の実験的デプロイを許可
review: 月次レビュー
yellow:
condition: "消費率 50% - 80%"
actions:
- リスクの高い変更は延期
- リリース前のテスト基準を強化
- ロールバック手順の再確認
- 信頼性改善タスクの優先度を上げる
review: 週次レビュー
orange:
condition: "消費率 80% - 100%"
actions:
- 信頼性に直接寄与しない変更を凍結
- インシデント振り返りを即日実施
- SREチームが全リリースをレビュー
- 自動ロールバックの閾値を厳格化
review: 日次レビュー
red:
condition: "消費率 > 100%(SLO未達成)"
actions:
- 全変更を凍結(セキュリティ修正を除く)
- 経営層にエスカレーション
- 信頼性改善を最優先プロジェクトとする
- ポストモーテムを実施し根本原因を解消
review: 日次レビュー(経営層参加)
# バジェットのリセット
reset:
schedule: "毎月1日"
carryover: false # 未消費分の繰越なし
ポリシーの運用フロー
graph TD
Check["毎日のバジェット確認"]
Check --> Green["消費率 < 50%(Green)<br/>通常運用、イノベーション加速"]
Check --> Yellow["消費率 50-80%(Yellow)<br/>リスク軽減、テスト強化"]
Check --> Orange["消費率 80-100%(Orange)<br/>変更制限、信頼性改善優先"]
Check --> Red["消費率 > 100%(Red)<br/>変更凍結、緊急対応モード"]
Red --> Fix["根本原因の解消"]
Fix --> Green
classDef check fill:#6c757d,stroke:#495057,color:#fff
classDef green fill:#198754,stroke:#146c43,color:#fff
classDef yellow fill:#f5a623,stroke:#c47d10,color:#fff
classDef orange fill:#fd7e14,stroke:#ca6510,color:#fff
classDef red fill:#e94560,stroke:#c23050,color:#fff
class Check check
class Green green
class Yellow yellow
class Orange orange
class Red,Fix red
バーンレート(Burn Rate)
バーンレートは、エラーバジェットがどのくらいの速度で消費されているかを示す指標です。
バーンレートの計算
バーンレート = 実際のエラー率 / 許容エラー率
例: SLO 99.9%(許容エラー率 0.1%)
現在のエラー率が 0.5% の場合
バーンレート = 0.5% / 0.1% = 5.0
→ 通常の5倍の速度でバジェットを消費している
Multi-Window Multi-Burn-Rate アラート
Googleが推奨するアラート手法で、複数の時間ウィンドウとバーンレートを組み合わせてアラートを設定します。
# Multi-Window Multi-Burn-Rate アラート設定
# SLO: 99.9% (30日ウィンドウ)
alerts:
# 急激なバジェット消費(高バーンレート × 短いウィンドウ)
- name: "急速バーンレートアラート"
severity: critical
burn_rate: 14.4 # 30日分のバジェットを2日で消費するペース
long_window: 1h # 長いウィンドウ
short_window: 5m # 短いウィンドウ(誤検知防止)
action: "即座にページ(オンコール呼び出し)"
# 中程度のバジェット消費
- name: "中速バーンレートアラート"
severity: warning
burn_rate: 6.0 # 30日分のバジェットを5日で消費するペース
long_window: 6h
short_window: 30m
action: "チケット作成、当日中に対応"
# 緩やかなバジェット消費
- name: "低速バーンレートアラート"
severity: info
burn_rate: 3.0 # 30日分のバジェットを10日で消費するペース
long_window: 3d
short_window: 6h
action: "次のスプリントで対応"
PromQLでのバーンレート計算
# 1時間ウィンドウでのバーンレート計算
# SLO: 99.9% (許容エラー率: 0.001)
# エラー率の計算
- record: slo:error_rate:1h
expr: |
1 - (
sum(rate(http_requests_total{status!~"5.."}[1h]))
/
sum(rate(http_requests_total[1h]))
)
# バーンレートの計算
- record: slo:burn_rate:1h
expr: |
slo:error_rate:1h / 0.001
# 急速バーンレートアラート
- alert: HighBurnRate
expr: |
slo:burn_rate:1h > 14.4
and
slo:burn_rate:5m > 14.4
for: 2m
labels:
severity: critical
annotations:
summary: "エラーバジェットが急速に消費されています"
description: "バーンレート: {{ $value }}x(1時間ウィンドウ)"
バーンレートの閾値の導出方法
Multi-Window のバーンレート閾値は、以下の考え方で導出されます。
30日ウィンドウのSLOの場合:
| 消費速度 | バーンレート | 意味 |
|---|---|---|
| 2日で30日分消費 | 14.4x | 全バジェット消費まで2日 |
| 5日で30日分消費 | 6.0x | 全バジェット消費まで5日 |
| 10日で30日分消費 | 3.0x | 全バジェット消費まで10日 |
| 30日で30日分消費 | 1.0x | ちょうどSLO境界上 |
計算式: バーンレート = SLOウィンドウ日数 / 消費完了日数
例: 30日 / 2日 = 15(実際は14.4 = 30 * 24 / (2 * 24 + αの余裕))
短いウィンドウは「長いウィンドウのアラートが誤検知でないことを確認する」ために使います。長いウィンドウだけだと、過去の障害の影響で誤報が発生しやすくなります。
エラーバジェットの活用パターン
パターン1: リリース判断
interface ReleaseDecision {
canRelease: boolean;
reason: string;
conditions: string[];
}
function makeReleaseDecision(
budgetConsumedPercent: number,
changeRisk: 'low' | 'medium' | 'high',
hasRollbackPlan: boolean
): ReleaseDecision {
// Red: 変更凍結
if (budgetConsumedPercent > 100) {
return {
canRelease: false,
reason: 'SLO未達成 - 全変更凍結中',
conditions: ['信頼性改善のみ許可'],
};
}
// Orange: 信頼性に寄与しない変更は凍結
if (budgetConsumedPercent > 80) {
return {
canRelease: changeRisk === 'low' && hasRollbackPlan,
reason: 'バジェット残量少 - 低リスク変更のみ',
conditions: [
'ロールバック手順が確認済みであること',
'SREレビューを通過していること',
],
};
}
// Yellow: リスクの高い変更は延期
if (budgetConsumedPercent > 50) {
if (changeRisk === 'high') {
return {
canRelease: false,
reason: 'バジェット注意レベル - 高リスク変更は延期',
conditions: ['次のウィンドウまで延期を推奨'],
};
}
return {
canRelease: hasRollbackPlan,
reason: 'バジェット注意レベル - ロールバック計画必須',
conditions: ['ロールバック手順を用意すること'],
};
}
// Green: 通常リリース
return {
canRelease: true,
reason: 'バジェット十分 - 通常リリース可能',
conditions: [],
};
}
パターン2: 開発チームとの対話
開発チーム: 「大規模なDBマイグレーションを実施したい」
SREチーム確認:
- 現在のバジェット消費率: 35%(Green)
- 残りバジェット: 28分
- 想定リスク: High(過去の類似作業で10分のダウンタイム)
- 判断: 実施可能。ただし以下の条件付き
1. メンテナンスウィンドウ内で実施
2. ロールバック手順を事前に検証
3. 段階的にマイグレーション(シャドーテーブル方式)
まとめ
| ポイント | 内容 |
|---|---|
| エラーバジェット | 100% - SLO目標 = 許容できる不信頼性の量 |
| ポリシー | バジェット消費率に応じてGreen/Yellow/Orange/Redのアクションを定義 |
| バーンレート | バジェット消費の速度。Multi-Window方式でアラートを設計 |
| リリース判断 | バジェット残量と変更リスクを組み合わせて客観的に判断 |
| チーム間の共通言語 | 開発と運用の対立をデータで解消する |
チェックリスト
- エラーバジェットの計算方法を理解した
- エラーバジェットポリシーの4段階を説明できる
- バーンレートの概念とMulti-Window方式を理解した
- PromQLでのバーンレートアラート設定を把握した
- エラーバジェットを使ったリリース判断の考え方を理解した
次のステップへ
次は「トイルの削減」を学びます。SREの業務時間の50%以上をエンジニアリングに充てるために、手作業的な運用作業(トイル)をどう特定し、削減するかを学びましょう。
推定読了時間: 30分