カオスエンジニアリングはサーバー障害だけの話じゃない
きっかけは、大事な打ち合わせの5分前に起きたトラブルでした。Zoomを開いたらカメラが認識されない。マイクも反応しない。再起動しても直らず、結局スマホから入り直した。
サーバーの障害対策は考えていたのに、手元のカメラやマイクが突然壊れたらどうするか、は考えていなかった。デバイス故障や環境要因にもカオスエンジニアリングの考え方が使えるんじゃないか。そう思って調べていくうちに、この分野の出発点であるNetflixのChaos Monkeyにたどり着きました。
2008年、DVDが届かなくなった
Netflixの歴史を変えたのは、2008年のデータベース障害でした。DVD出荷が3日間停止し、自社データセンターの限界が露呈した。この経験がAWSへの大規模クラウド移行を決断させます。
移行は成功しましたが、新しい問題が生まれました。クラウド環境では仮想マシンが予告なく終了します。ネットワーク遅延もデータセンター時代とは違うパターンで発生する。障害は「起きるかもしれないもの」ではなく、「日常的に起きるもの」になりました。
Netflixの選んだ解は逆説的でした。障害を避けるのではなく、わざと障害を起こすことにしたのです。
Chaos Monkey -- サーバールームに猿を放つ
2010年、NetflixのエンジニアチームはChaos Monkeyを開発しました。やることは単純です。本番環境の仮想マシンをランダムに終了させる。営業時間中に、予告なく、容赦なく。
「サーバールームに猿を放つ」イメージが名前の由来です。猿がケーブルを引き抜いても、スイッチを切っても、サービスは動き続けるべきだという思想を体現しています。正気の沙汰とは思えませんが、これが後にソフトウェア業界全体の障害対策を変えることになります。
2011年にYury IzrailevskiがNetflixの技術ブログでChaos Monkeyを含むSimian Army(サルの軍団)を公式発表しました。
| ツール名 | 役割 | 障害の種類 |
|---|---|---|
| Chaos Monkey | インスタンスをランダム終了 | サーバー障害 |
| Latency Monkey | 人工的な遅延を注入 | ネットワーク劣化 |
| Conformity Monkey | ベストプラクティス違反を検出 | 設定不備 |
| Chaos Gorilla | AZ全体を停止 | リージョン障害 |
Chaos Monkeyがサーバー1台なら、Chaos Gorillaはデータセンター群ごと消す。命名センスが物騒ですが、やっていることは至って論理的です。
カオス実験の4原則
Netflix以降、カオスエンジニアリングは方法論として体系化されました。principlesofchaos.org に定められた4つの原則があります。
1. 定常状態の仮説を立てる
「この障害が起きても、1分あたりの注文数は5%以上低下しない」のように、ビジネスメトリクスで仮説を立てます。CPU使用率だけ見ても意味がない。ユーザーに影響があるかどうかが本質です。
2. 現実世界のイベントを再現する
技術的に面白い障害ではなく、実際に起きうる障害を選びます。過去のインシデント履歴から優先度をつける。「NTPのずれ」は面白いけど、まず「プロセスが死ぬ」から始める方が実用的です。
3. 本番環境で実験する
ステージング環境では本番のトラフィックパターンやデータ量を再現できません。ただし「いきなり本番で試せ」ではなく、開発→ステージング→本番と段階的に進めるのが現実的です。
4. 影響範囲を最小化する
実験が想定外のダメージを与えたら即座に停止できるようにしておく。カオスエンジニアリングは「壊す」ことが目的ではなく、「壊れたときに何が起きるか」を知ることが目的です。
自分のPCでChaos Monkeyを試してみた
原則はわかった。でも本番でいきなり猿を放つのは怖い。そこで、ローカルPCで簡易Chaos Monkey実験をやってみました。
実験構成
[Client] → ラウンドロビン → [Server A (port 8001)]
→ [Server B (port 8002)]
PythonのHTTPサーバーを2台起動して、クライアントがラウンドロビンで100リクエストを送ります。これが「定常状態」。ここにChaos Monkey(プロセスのSIGKILL)を注入します。
シナリオと結果
3つのシナリオを実行しました。
# Chaos Monkeyの核心: プロセスをランダムにkill
victim = random.choice(range(len(procs)))
os.kill(procs[victim].pid, signal.SIGKILL)
| シナリオ | 条件 | 成功率 |
|---|---|---|
| ベースライン | 2台稼働 | 100% |
| 1台kill(復旧なし) | kill後100リクエスト | 50% |
| 1台kill + 自動復旧(1秒) | kill→1秒後に再起動→100リクエスト | 100% |
何がわかったか
50%という数字の生々しさ。サーバーが1台死んだだけで、リクエストの半分が失敗する。2台構成のラウンドロビンでは、死んだサーバーに振り分けられたリクエストが全滅します。ヘルスチェックなしのロードバランシングは、1台の障害でスループットが半減する。頭ではわかっていても、数字で見ると印象が違います。
自動復旧の劇的な効果。1秒で再起動すると成功率は100%に戻りました。復旧の仕組みがあるかないかで、50%と100%の差が出る。冗長化と自動復旧はセットで意味がある。片方だけでは不十分です。
実験コード全体で120行。Chaos Monkeyの核心はos.kill(pid, signal.SIGKILL)の1行です。本番のChaos Monkeyはもっと複雑ですが、「プロセスを殺して何が起きるか観察する」という本質は同じ。特別なツールがなくても始められます。
「壊す文化」を始める最小ステップ
Netflixのように本番でChaos Gorillaを放つのはハードルが高い。でもカオスエンジニアリングの考え方は、もっと小さなところから始められます。
Step 1: CIでプロセスを殺す
テスト実行中にバックグラウンドサービスを1つ落として、テストが通るか確認する。これだけでも「依存サービスが死んだときにどうなるか」がわかります。
Step 2: 依存サービスのタイムアウトを短くする
外部APIのタイムアウトを本来の10秒から1秒に設定してテストを回す。タイムアウト時のエラーハンドリングが正しく動くか。意外と動かないことが多い。
Step 3: Game Dayを設ける
月1回、チームで「今日はここを壊す」を決めて実験する。Netflixでは「Game Day」と呼ばれる定期的な障害注入訓練を実施しています。最初は開発環境で、慣れたらステージング、いずれ本番へ。
カオスエンジニアリングの要点は、ツールでも本番環境でもなく、「障害は起きる」という前提を受け入れて、事前に備えるという文化です。壮大に聞こえますが、やることは「プロセスを殺してみる」からです。Chaos Monkeyはその文化を象徴するツールにすぎません。猿を放つ前に、まず「猿が来たらどうする?」を考えることから始めてみてください。
参考
- Casey Rosenthal, Nora Jones 著「Chaos Engineering」(O'Reilly)
- Principles of Chaos Engineering
- Netflix Tech Blog "The Netflix Simian Army" (Yury Izrailevsky, 2011)