👨‍🚒

元消防士が障害訓練の統制やってみた

に公開

はじめに

はじめまして。HiroVodka です。
皆さん、障害訓練してますか?

私は以前、消防士として働いていました。消防の世界では、訓練をしない日は基本的にないと言っていいくらい、毎日のように訓練があります。

一方で、エンジニアとして働くようになってから感じたのは、本番障害は起きるけど、障害訓練はあまりやっていないチームが意外と多いということです。

このエントリでは、実際に私のチームで行った障害訓練の事例と、そこで得た学びを紹介します。

障害訓練とは?

ここでいう「障害訓練」は、本番相当環境で擬似的に障害を発生させて対応する訓練のことを指します。
消防の世界でいう「想定訓練」に近いイメージです。

訓練では、大きくふたつの役割に分かれます。

  • 訓練統制(ゲームマスター役)
    • 擬似的に障害を発生させる
    • 訓練の進行・時間管理・ヒント出しを行う
    • 障害対応そのものは原則として行わない
  • プレーヤー
    • 発生した障害を検知し、原因を調査し、復旧させる
    • 実際の障害対応と同じように振る舞う

「統制」という言葉にピンとこない方は、ゲームマスターと考えてもらえれば大丈夫です。

訓練統制の心得

消防士でもエンジニアでも、訓練の成否の大部分は統制の事前準備で決まると感じています。
ここがグダグダだと、せっかく協力してもらったメンバーの時間がもったいないです。

1. 訓練の目的を決める

いきなりシナリオから考えるのではなく、必ず訓練の目的から決めます。

  • 例:
    • 「DB 障害の調査フローに慣れてほしい」
    • 「新しく入ってきたメンバーに障害対応の一連の流れを体験してほしい」
    • 「障害対応マニュアルの抜け漏れを洗い出したい」

「なぜ訓練を行うのか」「訓練を通して何ができるようになっていてほしいのか」等の目的を統制側の中で決めておきましょう

2. 訓練想定(シナリオ)を作る

目的が決まったら、次にどんな障害が起きる設定かを考えていきます。
訓練目的から逆算して訓練想定を作ることで、より目的に沿った訓練を行うことができます。
また、複雑な想定よりも単純な方が好ましいです。

私の思うポイントは以下の通りです。

  • 現実的か?
    • 自分たちのサービス構成・開発フローで「実際にあり得そうか」を意識する
  • 目的とずれていないか?
    • 目的が「DB 調査に慣れてほしい」なのに、アプリ側バグ起因の障害だと目的とミスマッチとなる
  • 難易度は適切か?
    • 参加者がまったく対応できないレベルだと、訓練になりません。仮に自分がプレーヤー側だとしたらとても嫌な気持ちになるだけなのでやめましょう
    • 障害が複雑すぎると、訓練で予期せぬアクシデントが起きやすくなる。統制がコントロール可能なシンプルな障害にしましょう

3. タイムラインを作る

統制側の強い味方になるのがタイムラインです。
訓練全体の時間を決めて、以下を時系列で書き出しておきます。

  • いつ・何を発生させるのか
  • そのときシステムはどんな状態になるのか
  • プレーヤーに期待するアクション
  • 期待したアクションが出なかったときのフォロー方法(ヒントの出し方)

4. 「解決できなかった場合」まで想定する

特に、障害対応経験の少ないメンバーが参加する場合は、

  • 「時間内に完全に復旧できない」
  • 「どこかで詰まって先に進めない」

ということがあるかもしれません。

そのため、タイムラインにはあらかじめ

  • ○分経っても A ができていなかったら、統制側からこのヒントを出す
  • 残り○分になったら、統制側が復旧手順を口頭で伝えて一緒にやる

といった「失敗したときのレール」も書いておくと安心です。

実際にやってみた訓練

ここからは、実際に私たちのチームで実施した訓練の流れを紹介します。

1. 訓練目的

今回の訓練の目的は、次のとおりでした。

チームの障害対応マニュアルを実際に使ってみて、改善点を見つける

背景としては:

  • 以前から「障害対応が属人的になっている」という課題感があった
  • 障害対応マニュアルを作成したが、その後障害が発生しておらず、一度も本番で使えていなかった

マニュアルが使えるかどうかは実際に障害が発生しないと分からないため、一度訓練で使ってみようという意図です。

2. 訓練想定(シナリオ)

今回のシナリオは、次のようなものにしました。

社内の別プロダクトから大量の API リクエストが飛んできて、サーバーがダウンする

私たちのサービスは、社内向けに Internal API を提供しています。
そのため、他の社内サービスがバグをリリースした結果、想定以上のトラフィックが来る可能性は現実的にあり得ます。

どのようなプロセスでサーバーがダウンするか(キュー詰まりなのか、リソース不足なのか、DB がボトルネックなのか)といった詳細は今回の記事では割愛しますが、
統制側では事前に実際にその状態を再現できるか? を確認しました。

  • 意図した Alert を発報させられるか?
  • メトリクス(CPU、リクエスト数、エラー率)が想定通りの形になるか?
  • ログに異常がちゃんと出るか?

ここまで確認できたため、タイムライン作成に進みました。

3. タイムライン

実際に作成したタイムラインのイメージは、以下のような感じです。

時刻 統制アクション システム状態 期待されるプレーヤーの行動 解決しなかった場合のフォロー
10:00 負荷ツール起動 Internal API サーバーへのリクエスト数が急増 Alert / Slack 通知に気づく 10:05 までに気づかなければ、Slack で「アラート気づいていますか?」
10:05 さらに負荷を上げる 5xx エラー率が上昇、CPU 使用率が 90% 近くに メトリクスダッシュボードを開き、異常なグラフを特定 「メトリクスも確認してみてください」と統制からヒント
10:10 DB 負荷も増加 DB 接続数が上限近く、レスポンス遅延 DB 関連のメトリクスや Slow Query を確認 「DB 周辺のメトリクスも怪しいかも」とヒント
10:15 一部 Pod の Readiness Probe を意図的に失敗させる Pod が順次 Unready になり、トラフィックが他 Pod に集中 Pod の状態確認、デプロイ状況の確認 状況が進んでいなければ、kubectl / コンソールでの確認を促す
10:25 統制判断で「トラフィック遮断 / スケールアウト」可能にする 対応に応じて徐々にエラー率が下がる or 続く ALB ログやリクエスト元サービスを特定し、暫定対処を実行 残り 5 分で統制側から復旧手順を提案し、一緒に実施
10:30 訓練終了 システムは正常状態に戻す 障害報告テンプレートをベースに、振り返り用メモを作成 統制側から論点を整理して共有

実際にここまで細かく書けていると、当日の統制はかなり楽になります。
統制専用の資料としてタイムラインを用意しておき、訓練中はこれだけ見て進行できる状態を目指しました。

4. 訓練リハーサル

リハーサルでは、統制側だけでタイムライン通りに障害を発生させられるかを確認しました。
実際にリハーサルを行うと、やはり想定通りでないことが発生しました。

  • 負荷をかけても、サーバー側の自動リカバリ機構のおかげですぐ復旧してしまう
  • 想定していたアラートが思ったより遅れて発報される

…など、事前に気づけてよかったポイントがいくつも出てきました。

このリハーサルをやらずに本番訓練に突入していたら、統制側がトラブルシューティングしている間、プレーヤーが暇になるという、本末転倒な状態になっていたと思います。

5. 事前説明会

訓練当日より前に、プレーヤー向けに簡単な説明会(15〜30 分程度)を行いました。

そこで伝えた内容は主に以下です。

  • 訓練の目的

    • 今回は「障害対応マニュアルの実践と改善」がメインであること
    • そのため、障害対応マニュアル通りに作業してほしいということ
  • 訓練の前提

    • 実サービスへの影響はないテスト構成にしていること
    • 訓練のためにサーバーのリソースを下げているが、その設定を通常の設定として扱うこと
    • 障害報告などを行う際は、実際にインフラチームや上長へ連絡せずに、統制側へメンションすること
    • その他は実際の本番環境と同等のアラートやエラーログが発生すること

ここで目的を共有しておくことで、訓練の意図がプレーヤー側にも伝わりやすくなります。

また、前提として訓練中だけ行って欲しいこと、気にしないで欲しいことを伝えておくことで、当日の進行もスムーズになります。

6. 訓練当日の運営

訓練当日は、以下のような運営にしました。

  • 統制専用の Slack チャンネルを作成

    • 統制メンバーが「今何をしているか」「何を感じたか」を、時系列でメモする

    • 例:

      • 10:05 プレーヤーが障害報告を行うまでに5分程度かかった
      • 10:12 障害報告はもう少し詳細を記載してほしい
  • 上長・マネージャにもオブザーバーとして参加してもらう

    • 普段は「報告を受ける側」の視点で、どのような情報がほしいかフィードバックしてもらう
  • 統制側も障害対応マニュアルを見ながら進行

    • プレーヤーと同じマニュアルを見ながら、「ここに情報が足りない」「この手順は現実的ではない」といった気付きをリアルタイムで書き溜める

Slack 上にログを残しておくことで、後のふりかえりで時系列に沿って状況を確認できるのがとてもよかったです。

7. 訓練のふりかえり

訓練後のふりかえりでは、

  1. 訓練目的(マニュアルの実践&改善)に対するふりかえり
  2. 訓練そのものの運営に対するふりかえり

の 2 つを分けて行いました。

今回の訓練で出た課題の一例です。

  • マニュアル関連

    • ALB ログをどう検索すればよいかが、マニュアルに書かれていなかった
    • 障害報告用テンプレートの項目が少なく、報告が薄くなりがちだった
    • 調査に使うダッシュボードやリンク集がバラバラで、毎回探す必要があった
  • 訓練運営関連

    • 参加者の選定をもう少しローテーションできそう
    • 統制の事前準備をもう少しテンプレート化できそう

目的であった

「チームの障害対応マニュアルの実践、改善点を見つける」

については、期待通りのフィードバックを得ることができました。

訓練運営についても、普段の開発と同じように少しずつ改善を回していくことで、持続的な障害訓練にしていきたいと考えています。

消防士時代に学んだことと、エンジニアリング

最後に、少しだけ消防士時代の話をします。

昔職場の隊長に、こんなことを言われました。

「100 回訓練するよりも、1 回現場に入った方が成長する」

今振り返っても、本当にその通りだと思います。
現場でしか得られない緊張感や判断は、確かに存在します。

ただし、これは同時に

「訓練をしているからこそ、現場で活動できる」

という前提付きの言葉でもあります。
訓練をしていない人間が、いきなり現場に放り込まれても動けません。

エンジニアリングの世界でも、これに近い構造があると感じています。

  • 実際の障害対応中は、とにかく時間との勝負になりがち
  • 経験の浅いメンバーに任せてみたい気持ちはあっても、現場ではなかなか難しい

その結果、障害対応をするメンバーが固定化されてしまう、という状況は珍しくないと思います。

だからこそ、今回紹介したような障害訓練は、

  • 経験の浅いメンバーに「安全な失敗の場」を提供する
  • チームとして「同じやり方で考え、動く」ための共通フレームを育てる

という意味でも、非常に価値があると感じました。

最後に

実際に自分たちで障害訓練をやってみて、改めて感じたことはひとつです。

障害訓練は、どれだけ事前準備をするかで成功するかどうかが決まる

  • 障害対応が特定のメンバーに偏っている
  • 障害対応マニュアルが「作ったまま放置」になっている

もしあなたのチームがこんな状況なら、ぜひ一度障害訓練を行ってみてください。

Money Forward Developers

Discussion