ストーリー
カオスエンジニアリングとは
定義と原則
| 要素 | 説明 |
|---|---|
| 定義 | 分散システムの弱点を発見するために、本番環境で実験を行う手法 |
| 起源 | 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 Chaos | Kubernetes向けOSSカオスプラットフォーム |
| ゲームデイ | チーム全体でカオス実験とインシデント対応訓練を行うイベント |
| ブラストラディウス | 影響範囲を段階的に拡大し、リスクを制御する |
チェックリスト
- カオスエンジニアリングの原則と目的を説明できる
- 定常状態仮説の設計ができる
- Litmus Chaosの基本的な実験定義を理解した
- ゲームデイの計画と進行方法を把握した
- ブラストラディウスの段階的制御を理解した
次のステップへ
次は「演習:アラートとオンコールを設計しよう」です。Step 4で学んだアラート設計、オンコール体制、ランブック、カオスエンジニアリングの知識を統合した実践演習に挑戦しましょう。
推定読了時間: 40分