WHITEPLUS TechBlog

株式会社ホワイトプラスのエンジニアによる開発ブログです。

障害対応の予行演習会を実施しました

こんにちは!宅配クリーニングの『リネット』を運営しているホワイトプラスのエンジニアyumeです。

今回はタイトルの通り、システム障害に備えた障害対応の予行演習会についてお話しします。

日頃から障害が発生しないように最善を尽くしてはいますが、万が一の際も落ち着いて迅速かつ適切な対応ができるようにホワイトプラスでは定期的に障害対応の訓練を実施しています。 システム障害は起こらないに越したことはありませんが、地震や火事のように万が一に備えた訓練を行うことは重要ですよね。

ホワイトプラスの障害対応について

ホワイトプラスの障害対応は『インシデント指揮官』というフレームワークを導入しています。

『インシデント指揮官』を簡単にまとめると下記です。

  • 「インシデント指揮官」「主任SME」「外部通信役」「書記官」のロールに分かれて対応を行う
  • 各ロールの役割は以下
    • インシデント指揮官
      • インシデント対応の全体をリードし、対応方針を決定する
      • 各ロールへの割り当てや、指示を行い混乱を防ぐ
      • インシデント報告書のレビューを行う
      • ふりかえりをファシリテーション
    • 主任SME
      • 技術的な調査やリカバリ作業を行う
      • インシデント報告書のレビューを行う
    • 外部通信役
      • 外部の関係者との連携を行う
      • インシデント報告書の共有を行う
    • 書記官
      • インシデント対応の状況を書き残す
      • インシデント報告書を作成する
      • ふりかえりの予定を組む

導入の経緯や『インシデント指揮官』について詳しくはこちらの記事でご紹介していますので、本記事では割愛します。

blog.wh-plus.co.jp

予行演習会の準備

スケジューリング

仮日程を決めてGoogleカレンダーでエンジニアを招待します。 Slackで開催の宣言と参加者を募り、必要に応じて日程を調整します。

日程が決められたら、本番環境に見立てるステージング環境を確保しておきます。 ※ ホワイトプラスのステージング環境は複数あり、バッティングしないようにGoogleカレンダーで予約管理しています。

事業部役を演じる人も必要なので、今回はサービス理解の深いマネージャーにご協力を依頼しました。

資料の作成

以下のような資料を作成しました。

  • 予行演習会の目的
  • 日時・場所
    • 以前はGoogle Meetで行っていましたが、最近は日常的に利用しているバーチャルオフィスGatherで行っています
  • 参加者
    • エンジニア(任意参加)
  • インシデント指揮官に関する資料(おさらい用のリンク)
  • 事前準備TODOリスト
  • 設定
    • temp/incident_exercise_202502 ブランチを master ブランチに見立ててください
    • ステージング環境を本番環境に見立ててください
    • 予行演習用に埋め込んだバグによりユニットテストがこけていますが、テストで検知されずにリリースされてしまったものとしてください
  • タイムテーブル
    • 内容と流れを確認 ⌛5分
      • アジェンダの読み合わせや認識合わせを行う
    • チーム分け・移動 ⌛5分
      • 6人以上集まった場合はチームを分ける
    • 擬似インシデント対応 ⌛50分
    • 振り返り(実施後に各自記入)
  • 擬似インシデント対応の流れ
    1. 不具合発生のメッセージ送信@事業部役
    2. インシデント対応用のSlackチャンネル立ち上げ@インシデント指揮官
    3. ロール割り振り@インシデント指揮官
    4. 模擬インシデント対応開始
  • 振り返り
    • KPTとFeedBackのフォーマットをコピペできるように記載しておく

バグの埋め込み

今回のシナリオは「料金計算周りのロジックをリファクタしたところ、割引の計算処理が壊れてしまっていた」としました。

前回開催時に「コミットログを見てもいいか迷う」(答えのカンニングにならないか)という声があったことと、よりリアリティのある調査を行えるようにするため、過去のコミットに紛れ込ませたり、無害なリファクタと一緒にコミットするなどの工夫をします。

$ git checkout master
$ git checkout -b temp/incident_exercise_202502

$ git log --oneline --graph
*   1234567abc (HEAD -> temp/incident_exercise_202502) Merge pull request #12345 from WHITEPLUS/feature/xxx/base
|\  
| *   abc1234567 Merge pull request #67890 from WHITEPLUS/feature/yyy

# リベースを開始
# リベース時にコンフリクトが起こらないように直近のマージコミットを指定するとよいと思います
$ git rebase -i abc1234567
...
pick 01234abcde feat: 機能Aの実装
pick 56789abcde refactor: 不要な記述の削除
...

# バグコミットを挿入したい位置の一つ上のコミットハッシュをeditに書き換える
...
edit 01234abcde feat: 機能Aの実装
# 〜〜ここにバグコミットを挿入したい〜〜
pick 56789abcde refactor: 不要な記述の削除
...

# ファイルを書き換えてコミット(挿入位置に合わせた自然な日時を指定する)
# バグだけでなく、無害な変更も混ぜ込み、コミットメッセージも馴染むようにするとよいです
$ git commit --date="2025-02-19 14:32:12" -m "refactor: 料金計算周りの煩雑な処理を修正"

# リベースを完了させる
$ git rebase --continue

実施直前のデータ作り

当日、ステージング環境にバグを埋め込んだブランチを反映させて、 シナリオに沿った問題のあるデータを作成します。 今回は料金計算にバグを埋め込んだので、注文データをいくつか作成しておきます。

状況を作り終えたら、事業部役から送ってもらうためのメッセージも用意しておきます。 参加者以外の方を焦らせてしまわないようにしっかり注釈も入れておきます。

※※※※※ 【研修】インシデント予行演習用の模擬メッセージです!本番環境で問題は起こっていません ※※※※※
@インシデント指揮官
年間ケアパスの割引で不具合が起こっています。
事象1:
注文ID 100000008 で、年間ケアパスによって-4,577円されているという状態になっています。
https://staging/path/orders/100000008
事象2:
注文ID 100000010 で、無料会員にも関わらず年間ケアパス(-4,577円)が適用されています。
https://staging/path/orders/100000010
ご確認をお願いいたします。
※※※※※ 【研修】インシデント予行演習用の模擬メッセージです!実際に問題は起こっていません ※※※※※

ふりかえり

👏 よかった点

不具合のリアリティや難易度がちょうどよくでき、予定していた時間ぴったりに解決まで辿り着けました。 また、事業部役からも「16時までに解消されないと出荷に影響してしまいますが間に合いますか?」というようにリアルな問い合わせも随時あり、実際のインシデント対応に近い予行演習ができました! 適度に焦りや緊張感がありながらも、それぞれの役割に沿って進行し、状況の確認やフォローができていてよかったです。

今回の実施やふりかえりによって、予行演習会の資料がブラッシュアップできました。 雛形を作成して企画者の準備作業を最小限にし、より手軽に予行演習会を実施できるようにしていければと思います。

🚀 のびしろ

バグ埋め込みによって想定外の不具合も発生して不要な混乱を招き、「〜というテイでお願いします」といった場面が出てしまいました。 これはリベース時にコンフリクトが大量に起こって丁寧に解消する時間を惜しみ強気に処理した結果でした。 次回は上記バグ埋め込みのセクションに記載しているように、リベース開始位置を工夫してコンフリクトが起こらないようにできれば良さそうに思います。

そしてロールの役割や初動について戸惑う場面もありました。 今回はインシデント指揮官のおさらいを割愛してしまったのですが、対応に入る前におさらいと認識合わせの時間を設けるようにするとよりスムーズに進行できそうでした。 次回のタイムテーブルに反映したいと思います。

さいごに

ホワイトプラスでは、ビジョンバリューに共感していただけるエンジニアを募集しています!

宅配クリーニングの「リネット」など、「生活領域×テクノロジー」で事業を展開しています。

弊社に興味がある方は、オウンドメディア「ホワプラSTYLE」をご覧ください。

オンラインでのカジュアル面談も可能ですので、ぜひお気軽にお問い合わせください。