LESSON 40分

ストーリー

佐藤CTO
ランブックを整備した。アラートとオンコール体制もできた。だが、それが本当に機能するかどうかは、実際に障害が起きるまでわからない
あなた
テスト環境では動くけど、本番では想定外のことが起きますよね
佐藤CTO
まさにそこだ。カオスエンジニアリング — 意図的に障害を注入して、システムの弱点を事前に発見する手法だ。Netflixが”Chaos Monkey”で有名にした。障害が起きてから学ぶのではなく、障害を起こして学ぶのだ

カオスエンジニアリングとは

定義と原則

要素説明
定義分散システムの弱点を発見するために、本番環境で実験を行う手法
起源Netflix(2010年)- Chaos Monkey
目的システムの回復力(Resilience)を検証し、弱点を事前に修正する
前提「障害は必ず起きる」→ 起きる前に準備する

カオスエンジニアリングの原則(Principles of Chaos Engineering)

1. 定常状態の仮説を立てる(Steady State Hypothesis)
   └─ 正常時のシステム挙動を定義する

2. 現実世界の事象で変化を注入する
   └─ サーバー停止、ネットワーク遅延、ディスク障害など

3. 本番環境で実験する
   └─ テスト環境では見つからない問題がある

4. 自動化して継続的に実行する
   └─ 一度きりではなく、定常的に実施する

5. 影響範囲を最小化する
   └─ 段階的に実験の規模を拡大する

定常状態仮説(Steady State Hypothesis)

仮説の設計

カオス実験の最初のステップは、「正常な状態」を明確に定義することです。

interface SteadyStateHypothesis {
  // 仮説の説明
  description: string;
  // 検証するSLI
  sliMetrics: SliMetric[];
  // 許容閾値
  tolerances: Tolerance[];
}

interface SliMetric {
  name: string;
  query: string;        // PromQLクエリ
  normalRange: string;  // 正常範囲
}

interface Tolerance {
  metric: string;
  maxDeviation: string; // 許容される最大偏差
}

// 例: 注文処理サービスの定常状態仮説
const orderServiceHypothesis: SteadyStateHypothesis = {
  description: 'payment-serviceの1台が停止しても、注文処理は正常に継続する',
  sliMetrics: [
    {
      name: '注文成功率',
      query: 'sum(rate(order_created_total{status="success"}[5m])) / sum(rate(order_created_total[5m]))',
      normalRange: '> 99.9%',
    },
    {
      name: '注文処理レイテンシ(p99)',
      query: 'histogram_quantile(0.99, sum(rate(order_processing_duration_seconds_bucket[5m])) by (le))',
      normalRange: '< 3s',
    },
  ],
  tolerances: [
    { metric: '注文成功率', maxDeviation: '0.1%の低下まで許容' },
    { metric: '注文処理レイテンシ', maxDeviation: '500msの増加まで許容' },
  ],
};

カオス実験の種類

障害注入のカテゴリ

カテゴリ実験内容ツール
インフラ障害サーバー停止、ディスク障害Chaos Monkey, Litmus
ネットワーク障害レイテンシ注入、パケットロスtc (Linux), Toxiproxy
アプリケーション障害プロセスキル、メモリリークChaos Toolkit, Gremlin
依存サービス障害外部API障害シミュレーションWireMock, Toxiproxy
リソース枯渇CPU負荷、ディスク満杯stress-ng, Litmus
DNS障害DNS解決失敗Litmus, カスタムスクリプト

Netflixのカオスツール群

Netflix Simian Army(歴史的):
  ├─ Chaos Monkey: ランダムにインスタンスを停止
  ├─ Chaos Gorilla: AZ全体を停止
  ├─ Chaos Kong: リージョン全体を停止
  ├─ Latency Monkey: ネットワーク遅延を注入
  ├─ Doctor Monkey: ヘルスチェック不合格インスタンスを検出
  └─ Janitor Monkey: 未使用リソースを削除

現在は "Chaos Monkey for Spring Boot" と
"FIT (Failure Injection Testing)" に進化

Litmus Chaosの活用

Litmusとは

Kubernetes環境向けのオープンソースカオスエンジニアリングプラットフォームです。

カオス実験の定義(ChaosEngine)

# litmus-experiment: Pod削除実験
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
  name: payment-pod-delete
  namespace: production
spec:
  appinfo:
    appns: production
    applabel: app=payment-service
    appkind: deployment

  # 定常状態仮説の検証
  engineState: active
  chaosServiceAccount: litmus-admin

  experiments:
    - name: pod-delete
      spec:
        components:
          env:
            # 削除するPod数
            - name: TOTAL_CHAOS_DURATION
              value: "60"        # 60秒間
            - name: CHAOS_INTERVAL
              value: "10"        # 10秒ごとに1つ削除
            - name: FORCE
              value: "false"     # graceful shutdown
            - name: PODS_AFFECTED_PERC
              value: "50"        # 50%のPodを対象

        # 定常状態チェック(実験前後に実行)
        probe:
          - name: check-order-success-rate
            type: promProbe
            mode: Continuous
            runProperties:
              probeTimeout: 10
              interval: 5
              retry: 3
            promProbe/inputs:
              endpoint: "http://prometheus:9090"
              query: |
                sum(rate(order_created_total{status="success"}[1m]))
                / sum(rate(order_created_total[1m])) * 100
              comparator:
                type: float
                criteria: ">="
                value: "99.9"

ネットワーク遅延実験

# litmus-experiment: ネットワーク遅延注入
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
  name: payment-network-latency
  namespace: production
spec:
  appinfo:
    appns: production
    applabel: app=payment-service
    appkind: deployment
  engineState: active
  chaosServiceAccount: litmus-admin

  experiments:
    - name: pod-network-latency
      spec:
        components:
          env:
            - name: NETWORK_INTERFACE
              value: "eth0"
            - name: NETWORK_LATENCY
              value: "2000"      # 2000ms のレイテンシを追加
            - name: TOTAL_CHAOS_DURATION
              value: "120"       # 120秒間
            - name: DESTINATION_IPS
              value: "10.0.0.50" # DBサーバーのIPのみ対象
            - name: JITTER
              value: "500"       # 500ms のジッター

ゲームデイ(Game Day)

ゲームデイとは

チーム全体で計画的にカオス実験を実施し、インシデント対応の訓練を行うイベントです。

interface GameDay {
  date: string;
  duration: string;
  participants: string[];
  scenarios: GameDayScenario[];
  objectives: string[];
}

interface GameDayScenario {
  name: string;
  description: string;
  injectedFault: string;
  expectedBehavior: string;
  successCriteria: string[];
}

const gameDay: GameDay = {
  date: '2026-03-15',
  duration: '3時間(10:00-13:00)',
  participants: ['SREチーム', '決済チーム', 'プラットフォームチーム'],
  objectives: [
    'インシデント対応フローの検証',
    'ランブックの有効性確認',
    'エスカレーションパスの確認',
    'アラートの適切性検証',
  ],
  scenarios: [
    {
      name: 'シナリオ1: DB接続プール枯渇',
      description: 'payment-serviceのDB接続プールを意図的に枯渇させる',
      injectedFault: 'DB接続数を上限の90%まで人為的に使用',
      expectedBehavior: 'サーキットブレーカーが発動し、一部リクエストがフォールバック',
      successCriteria: [
        'アラートが5分以内に発火する',
        'ランブックに従って15分以内に対応開始',
        'ユーザー影響が5%以内に抑えられる',
      ],
    },
    {
      name: 'シナリオ2: AZ障害シミュレーション',
      description: '1つのAZのPodを全て停止させる',
      injectedFault: '特定AZのノードをcordon + drain',
      expectedBehavior: '残りのAZでサービス継続、自動スケーリング',
      successCriteria: [
        'サービスが30秒以内にフェイルオーバー',
        'SLOが維持される(99.9%以上)',
        'ステータスページが適切に更新される',
      ],
    },
  ],
};

ゲームデイの進行

事前準備(1週間前):
  ├─ シナリオの設計と関係者への共有
  ├─ ロールバック手順の確認
  ├─ モニタリングダッシュボードの準備
  └─ 中止基準(Abort Criteria)の定義

当日:
  ├─ ブリーフィング(15分): 目的・シナリオ・中止基準の確認
  ├─ シナリオ実行(各30〜45分)
  │   ├─ 障害注入
  │   ├─ 検知・対応の観察
  │   ├─ メトリクスの記録
  │   └─ 必要に応じて中止
  └─ デブリーフィング(30分): 結果の振り返り・改善点の洗い出し

事後:
  ├─ 発見事項のドキュメント化
  ├─ 改善アクションアイテムの作成
  ├─ ランブックの更新
  └─ 次回ゲームデイの計画
ブラストラディウス(影響範囲)の制御

カオス実験では、影響範囲を段階的に拡大することが重要です。

段階的拡大のアプローチ:

段階環境範囲時間
1開発環境1 Pod制限なし
2ステージングサービス単位30分以内
3本番(カナリア)トラフィックの1%10分以内
4本番(限定)トラフィックの10%15分以内
5本番(通常)サービス全体計画的に実施

中止基準(Abort Criteria):

  • SLOが閾値を下回った場合 → 即座に実験を中止
  • 予期しないサービスへの影響が確認された場合 → 即座に中止
  • データの整合性に影響が出た場合 → 即座に中止し、データ検証を実施
abort_criteria:
  - metric: "order_success_rate"
    condition: "< 99.5%"
    action: "実験を即座に中止し、注入した障害を解除"
  - metric: "payment_error_rate"
    condition: "> 1%"
    action: "実験を即座に中止し、決済チームに通知"
  - metric: "user_facing_errors"
    condition: "any increase"
    action: "影響範囲を確認し、拡大していれば中止"

まとめ

ポイント内容
カオスエンジニアリング意図的に障害を注入し、システムの弱点を事前に発見する手法
定常状態仮説実験前に「正常な状態」をSLIで定義し、実験後に検証する
Litmus ChaosKubernetes向けOSSカオスプラットフォーム
ゲームデイチーム全体でカオス実験とインシデント対応訓練を行うイベント
ブラストラディウス影響範囲を段階的に拡大し、リスクを制御する

チェックリスト

  • カオスエンジニアリングの原則と目的を説明できる
  • 定常状態仮説の設計ができる
  • Litmus Chaosの基本的な実験定義を理解した
  • ゲームデイの計画と進行方法を把握した
  • ブラストラディウスの段階的制御を理解した

次のステップへ

次は「演習:アラートとオンコールを設計しよう」です。Step 4で学んだアラート設計、オンコール体制、ランブック、カオスエンジニアリングの知識を統合した実践演習に挑戦しましょう。


推定読了時間: 40分