LESSON 40分

ストーリー

佐藤CTO
SLIの設計ができた。次はSLO — Service Level Objectiveの設定だ
あなた
SLOの目標値はどう決めればいいのでしょうか。高すぎても低すぎても問題がありそうです
佐藤CTO
鋭い指摘だ。SLOが高すぎれば変更ができなくなり、低すぎればユーザーが離れる。ユーザーの期待値ビジネスの現実のバランスを取る技術がSLO設定の核心だ

SLOの基礎

SLO設定の原則

原則説明
ユーザーの幸福度を反映する内部メトリクスではなくユーザー体験を基準にする
達成可能な目標を設定する過去のパフォーマンスデータを参考にする
100%を目指さないエラーバジェットの余地を残す
段階的に引き上げる最初は控えめに設定し、データに基づいて調整する
シンプルに保つ1サービスあたり3〜5個のSLOに絞る

SLO設定のアプローチ

graph TD
    Title["SLO設定の2つのアプローチ"]

    Title --- TopDown["トップダウン<br/><br/>ビジネス要件から<br/>逆算して目標を設定<br/><br/>「99.99%が必要」<br/>→ コストと実現性を検証する<br/><br/>推奨: SLA契約がある場合"]
    Title --- BottomUp["ボトムアップ<br/><br/>実績データから<br/>現実的な目標を導出<br/><br/>「過去6ヶ月は99.95%」<br/>→ これを基準に少し高い<br/>目標を設定する<br/><br/>推奨: 既存サービスに<br/>SLOを初めて導入する場合"]

    classDef title fill:#1a1a2e,stroke:#e94560,color:#fff
    classDef approach fill:#0d6efd,stroke:#0a58ca,color:#fff

    class Title title
    class TopDown,BottomUp approach

SLO目標値の選び方

ステップ1: 過去データの分析

interface HistoricalPerformance {
  period: string;
  availability: number;       // 可用性(%)
  latencyP50: number;        // レイテンシ p50(ms)
  latencyP99: number;        // レイテンシ p99(ms)
  errorRate: number;         // エラー率(%)
}

function analyzeSloCandidate(
  data: HistoricalPerformance[]
): {
  recommendedAvailability: number;
  recommendedLatencyP99: number;
  confidence: string;
} {
  // 過去6ヶ月の最低値を基準にする
  const minAvailability = Math.min(...data.map(d => d.availability));
  const maxLatencyP99 = Math.max(...data.map(d => d.latencyP99));

  // 過去実績の最低値よりやや高い目標を設定
  // (最低値そのものだとSLO未達が頻発する)
  const recommendedAvailability = Math.floor(minAvailability * 10) / 10;
  const recommendedLatencyP99 = Math.ceil(maxLatencyP99 / 100) * 100;

  return {
    recommendedAvailability,
    recommendedLatencyP99,
    confidence: data.length >= 6 ? '高' : '低(データ不足)',
  };
}

// 例: 過去6ヶ月のデータ
const historicalData: HistoricalPerformance[] = [
  { period: '2025-07', availability: 99.95, latencyP50: 45, latencyP99: 280, errorRate: 0.05 },
  { period: '2025-08', availability: 99.92, latencyP50: 50, latencyP99: 310, errorRate: 0.08 },
  { period: '2025-09', availability: 99.97, latencyP50: 42, latencyP99: 250, errorRate: 0.03 },
  { period: '2025-10', availability: 99.88, latencyP50: 55, latencyP99: 350, errorRate: 0.12 },
  { period: '2025-11', availability: 99.94, latencyP50: 48, latencyP99: 290, errorRate: 0.06 },
  { period: '2025-12', availability: 99.96, latencyP50: 44, latencyP99: 260, errorRate: 0.04 },
];

const recommendation = analyzeSloCandidate(historicalData);
// recommendedAvailability: 99.8%(最低値99.88%よりやや低めの安全目標)
// recommendedLatencyP99: 400ms(最大値350msに余裕をもたせた目標)

ステップ2: ユーザー期待との照合

ユーザーの期待SLIへの反映SLO目標例
「ページが即座に表示される」レイテンシ p95 < 200ms95% of requests < 200ms
「検索が使えなくなることはない」可用性99.9%
「決済が途中で止まらない」完了率99.95%
「データが消えない」耐久性99.999%

ステップ3: ビジネス制約の考慮

# SLO設定のビジネス制約チェックリスト
business_constraints:
  revenue_impact:
    question: "SLO未達の場合、1時間あたりいくらの損失が出るか?"
    analysis: "月間売上1億円 → 時間あたり約14万円"
    implication: "99.99%と99.9%の差(年間約8時間)で約112万円の差"

  competitive_landscape:
    question: "競合のサービス品質はどの程度か?"
    analysis: "主要競合は99.95%程度の可用性"
    implication: "最低でも同等以上を目指す"

  regulatory_requirements:
    question: "法規制やコンプライアンスの要件はあるか?"
    analysis: "決済はPCI DSS準拠が必要"
    implication: "決済関連のSLOは特に高い目標が必要"

  cost_budget:
    question: "信頼性向上にかけられる予算は?"
    analysis: "年間インフラ予算の20%を信頼性向上に充当可能"
    implication: "99.99%は現在の予算では困難、99.95%が現実的"

Multi-Window Multi-Burn-Rate アラート設計

設計の考え方

                重大度

         Critical │ ◆ 短期間で急速消費
                  │   (1h window, burn rate 14.4x)

          Warning │ ◆ 中期間で中速消費
                  │   (6h window, burn rate 6x)

             Info │ ◆ 長期間で緩やか消費
                  │   (3d window, burn rate 3x)

                  └──────────────────────────→ 検知までの時間
                   5分    30分    6時間    3日

具体的なアラートルール(Prometheus)

# Prometheus Recording Rules
groups:
  - name: slo_rules
    interval: 30s
    rules:
      # SLI: 可用性(成功率)
      - record: sli:availability:rate5m
        expr: |
          sum(rate(http_requests_total{status!~"5.."}[5m]))
          /
          sum(rate(http_requests_total[5m]))

      # エラー率(各ウィンドウ)
      - record: slo:error_ratio:5m
        expr: 1 - sli:availability:rate5m

      - record: slo:error_ratio:30m
        expr: |
          1 - (
            sum(rate(http_requests_total{status!~"5.."}[30m]))
            /
            sum(rate(http_requests_total[30m]))
          )

      - record: slo:error_ratio:1h
        expr: |
          1 - (
            sum(rate(http_requests_total{status!~"5.."}[1h]))
            /
            sum(rate(http_requests_total[1h]))
          )

      - record: slo:error_ratio:6h
        expr: |
          1 - (
            sum(rate(http_requests_total{status!~"5.."}[6h]))
            /
            sum(rate(http_requests_total[6h]))
          )

      - record: slo:error_ratio:3d
        expr: |
          1 - (
            sum(rate(http_requests_total{status!~"5.."}[3d]))
            /
            sum(rate(http_requests_total[3d]))
          )

---
# Prometheus Alerting Rules
groups:
  - name: slo_alerts
    rules:
      # Critical: 2日でバジェット消尽するペース
      - alert: SLO_HighBurnRate_Critical
        expr: |
          slo:error_ratio:1h > (14.4 * 0.001)
          and
          slo:error_ratio:5m > (14.4 * 0.001)
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "SLO高速バーンレート検出(Critical)"
          description: |
            1時間エラー率: {{ $value | humanizePercentage }}
            バーンレート: {{ $value | humanize }}x
            このペースでは約2日でエラーバジェットが枯渇します

      # Warning: 5日でバジェット消尽するペース
      - alert: SLO_HighBurnRate_Warning
        expr: |
          slo:error_ratio:6h > (6 * 0.001)
          and
          slo:error_ratio:30m > (6 * 0.001)
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "SLO中速バーンレート検出(Warning)"

      # Info: 10日でバジェット消尽するペース
      - alert: SLO_HighBurnRate_Info
        expr: |
          slo:error_ratio:3d > (3 * 0.001)
          and
          slo:error_ratio:6h > (3 * 0.001)
        for: 30m
        labels:
          severity: info
        annotations:
          summary: "SLO低速バーンレート検出(Info)"

レイテンシSLOのアラート

# レイテンシSLI: 300ms以内のリクエストの割合
# SLO: 99%のリクエストが300ms以内

- record: sli:latency_good:rate5m
  expr: |
    sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
    /
    sum(rate(http_request_duration_seconds_count[5m]))

# レイテンシSLOのバーンレートアラート
- alert: LatencySLO_HighBurnRate
  expr: |
    (1 - sli:latency_good:rate1h) > (14.4 * 0.01)
    and
    (1 - sli:latency_good:rate5m) > (14.4 * 0.01)
  for: 2m
  labels:
    severity: critical
  annotations:
    summary: "レイテンシSLO高速バーンレート検出"

SLOドキュメント

SLOドキュメントテンプレート

# SLOドキュメント
service: "ShopNow API"
version: "1.0"
owner: "SRE Team"
last_reviewed: "2026-02-01"
next_review: "2026-05-01"

slos:
  - name: "API可用性"
    sli:
      type: availability
      description: "APIが正常なレスポンス(非5xx)を返す割合"
      good_event: "HTTP status < 500"
      valid_event: "全HTTPリクエスト(ヘルスチェック除外)"
    target: 99.9%
    window: 30days
    error_budget: "43.2分/月"
    alert_burn_rates:
      critical: 14.4x
      warning: 6x
      info: 3x

  - name: "API レイテンシ"
    sli:
      type: latency
      description: "300ms以内にレスポンスを返したリクエストの割合"
      good_event: "response_time < 300ms"
      valid_event: "成功したHTTPリクエスト(status < 500)"
    target: 99%
    window: 30days
    error_budget: "全リクエストの1%がSLO超過を許容"

  - name: "決済成功率"
    sli:
      type: availability
      description: "決済処理が正常に完了した割合"
      good_event: "payment_status = 'completed'"
      valid_event: "全決済リクエスト"
    target: 99.95%
    window: 30days
    error_budget: "21.6分/月"
    note: "外部決済APIの障害はSLI計測に含む"

consequences:
  budget_exceeded:
    - "全リリースを信頼性改善目的に限定"
    - "CTO/VP Engineeringに週次報告"
    - "根本原因分析と改善計画を2週間以内に策定"
SLO設定でよくある失敗パターン
パターン問題対策
最初から高すぎるSLOエラーバジェットが即座に枯渇過去実績より少し低い目標から始める
SLOが多すぎる焦点がぼやけ、管理コストが増大1サービス3〜5個に絞る
SLOのレビューをしないビジネス環境の変化に追随できない四半期ごとにレビュー
内部メトリクスをSLOにするユーザー体験と乖離ユーザージャーニーから導出
SLOを罰則として使うチームのモチベーション低下改善のための道具として使う

まとめ

ポイント内容
SLO設定原則ユーザー体験を反映、達成可能、100%を目指さない
目標値の決め方過去データ分析→ユーザー期待照合→ビジネス制約考慮
Multi-Window Burn-Rate複数の時間ウィンドウとバーンレートでアラートを設計
SLOドキュメントサービスごとに3〜5個のSLOを文書化して定期レビュー
段階的改善最初は控えめに設定し、データに基づいて引き上げる

チェックリスト

  • SLO設定の原則とアプローチを理解した
  • 過去データからSLO目標値を導出する方法を把握した
  • Multi-Window Multi-Burn-Rateアラートを設計できる
  • PromQLでのバーンレート計算とアラートルールを記述できる
  • SLOドキュメントのテンプレートを使えるようになった

次のステップへ

次は「SLAの管理」を学びます。SLOとSLAの違い、SLA違反時の財務的影響、そしてSLA交渉のテクニックを深掘りしましょう。


推定読了時間: 40分