ちょっと話題の記事

今日からできる。初めての障害対応ガイド

2019.12.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こむろ@札幌です。

今年もまた大きなプロジェクトのサービス運用を担当し、サービス運用経験者としていろんなところに顔を出したりことの多い1年でした。自分自身が障害対応の前線に立つだけでなく、ほかの人の障害対応の手伝いをするなど、いろんな視点で運用の現場に関わってきました。

元々サービスのまともな運用経験ゼロの私が、多様な技術的負債や自分があまりかかわっていないサービスの運用を紆余曲折の結果、抱えるようになって数年経過し、サービス運用にまつわる様々な知見が蓄積しました。2019年の締めにそれらをまとめて文章にしておこうと思います。

今回のターゲットは開発をメインでやっているエンジニアです。運用を経験したことがない人にとっては、障害対応時にどのように立ち回ってよいのかがわからず、なんとなく行動した結果、サービス利用者への障害が長引いてしまう、状況をより悪化させてしまう、といった状態を招きかねません。

この記事の内容は大体 Yakst - インシデント指揮官トレーニングの手引き こちらに記載されているものです。わたしは経験的にこのあたりの知見を得ましたが、概ね同じような事が書いてありました(もっと早く知りたかった)ので、普段あまり運用に関わらない人や緊急時にどのように関われば良いかのガイドになれば幸いです。

とても長いですが、言いたいことは Yakst - インシデント指揮官トレーニングの手引き こちらを読みましょうのみです。

前提

AWS上に構築したWebアプリケーションの運用の知見をベースにこちらの記事を執筆しました。すべてのシステムの障害に対して、これらの知見が有効かはわかりません。予めご了承ください。

一人で対応しない

障害という異常な状況で冷静である保証がありません。一人で対応した場合、ミスや間違いに気づける人がいません。

メトリクスの読み違い、対応のための修正コードや調査用のスクリプトの実装ミス、顧客環境へのアクセスが必要な場合はそれらの手順等、緊急時であればあるほど冷静に行わなければならない作業が大量にあります。二次被害、三次被害を招きかねないのは想像に難くないのではないでしょうか。

もし今までうまくいっていたとしても、それは単にラッキーであっただけで障害の種類、重度は毎度異なります。同じ状況は二度とないはずです。 *1

障害が発生した際には「もしかして自分が何かやらかしたのか?」と不安になり、とにかく原因を確かめようとします。ログを見たり、リソースのメトリクスを確認するなどするでしょう。発生している事象の状況を一旦立ち止まって正確に把握し、調査方針や対象を見極めるためには一人でやるのではなくやはり複数名のチェックが必要なのではないでしょうか。

チームで対応する

では具体的にどのようなチームを組めば良いか。

単純に人数を増やして全員が一斉にログを解析しても意味がありません。それぞれのメンバーに明確な役割が必要です。役割を担える人数として最低3名は必要だと考えています(兼務が必要なのでこれ以上アサインできるならばそれぞれの兼務を分離すべき)

  1. 司令塔(外部通信役)
  2. 原因調査・復旧
  3. 現在の状況観測(記録役)

Yakst - インシデント指揮官トレーニングの手引き こちらに大体書いてあります。ええ、ほとんどこの方針そのままです。

司令塔

チームには必ず司令塔の役割を担うメンバーをアサインします。司令塔は以下の役割を担い、障害対応を行うチームの中心として動きます。

  • 他メンバーへ直接情報が伝達したりすることのないように情報の経路をコントロールする
  • 障害対応の状況等を適切に管理し、外部へ報告を行う
  • 状況によってはメンバーの増員、役割の変更等も柔軟に行うため社内調整等を行う

司令塔はすべての情報をコントロールする役割です。この役割がうまく動かないと対応チームはうまく動作しません。

Yakst - インシデント指揮官トレーニングの手引き には外部通信役とは明確に切り離されていますが、そこまで人的リソースが避けない場合は、司令塔が兼務が良さそうとわたしは考えています。

情報経路をコントロールする

なぜ必要なのか?

障害が発生すると、関係各所から様々な問い合わせ(時には罵声や怒号)、社内からの問い合わせ等々、大量のリクエストが 必ず 飛んできます。これを障害対応で原因調査、復旧を行っているメンバーが直接対応するのはナンセンスです。調査作業や復旧作業の邪魔にしかなりません。

また、障害対応の状況を報告するにしても、現場の手を止めて都度どういう状況なのかを報告するのは無駄にもほどがあります。ノイズです。対応メンバーに直接SlackでDMしてきたりする人もいますが、全て却下してください。

司令塔はこれらの情報経路をコントロールし、すべて窓口として一か所に集めて統制します。対応しているエンジニアからの情報も直接外へは出さずにまずは司令塔にすべてを集約するようにします。こうすることで、障害対応を行っているチームを外部の様々なノイズから隔離し、調査や復旧作業に集中できる状況を作ります。

メンバー増員、役割の変更

司令塔はチームの状況についてもつぶさに把握する必要があります。障害の原因によって対応するエンジニアやチームが変わるでしょう。対応の状況次第でメンバーの増員を行う場合には社内調整が必要です。そういった調整も司令塔が行い、対応チームを統制します。

決定する

様々な情報が司令塔へ集約されます。その中で、一番大切なのは決めることです。調査の方針、対応の優先順位や役割の分配など、今ある材料の中で決めることが大量にあります。上記にも書きましたがチームの編成の決定も司令塔が原則行います。状況を判断できるのは司令塔だけです。

原因調査・復旧担当

言うまでもなく、原因調査を行うメンバーは必須です。最前線で対応を行います。原因調査以外にも以下のような役割があります。

  • 障害の原因調査
  • 障害によって発生した影響とその範囲
  • 暫定対応策の考案、実装

最前線は当然ながら燃え盛る炎の中で作業する必要があります。そのため、密に連携の取れる複数名で対応したほうが良いかもしれません(人的リソースに余裕があるならば)

ただし、複数名の場合、個々人の判断で作業に取り掛かるよりもリーダーと作業者に分け、一人がかならずすべてのタスクを管理した方が良いかと思います。

例えば障害によるデータ不整合の調査であっても、どの作業者がどこのサーバーのどの期間を調査しているという情報がうまく共有されない場合、期間や対象サーバーの欠落、対象の重複等が発生する可能性があるため、それらを別途突き合わせる必要があります(人数が少なく、各個人がこういった考慮ができるスーパーなエンジニアな場合、このあたりはうまく連携が取れる可能性もあります。)

Yakst - インシデント指揮官トレーニングの手引き にはSMEといった役割がありますが、調査チームはかならずこのSMEを必ず一人アサインし、それ以外のメンバーはSMEを中心に連携を行います。

障害の原因調査

障害の当該時刻のリソースのメトリクス、アプリケーションログ、ロードバランサーのアクセスログ等、多様な視点で状況を分析し原因を特定します。可能性、推測の場合は具体的にそれを指し示す根拠となるメトリクスや数値を集めます。

すべての調査の報告は司令塔に行います。決して自身の判断で外部へ報告しないこと。司令塔の知らない経路で情報伝達が行われることがないようにします。

調査の仕方については開発しているサービスによるかと思いますが、自分の場合は以下のような確認手順で調査を行っています。

  1. エラーとなっているサービスのアプリケーションログを確認する
  2. アプリケーションログで別サービスを呼び出している箇所でエラーがないかを確認する
  3. もし別サービスからのエラーが有るならば別サービスのアプリケーションログを確認する
    • これを特定できるまで繰り返す
    • アプリケーションエラーならば原因特定まですすめる
  4. 何も出てなければ、当該サービスが利用しているAWSリソースのメトリクスを確認する
    • AWSリソースに何らかのエラーが出ている場合は、アプリケーションログにも出ている事が多いはずですが、そもそもアプリケーションまでリクエストが到達していない場合などはALBのアクセスログ等も合わせて確認する(アプリケーションまで転送されてるのかとか)
  5. これらを複合的に重ね合わせて、当該時刻に発生したと思われる現象の原因を特定していく

アプリケーションからAWSリソースへ向けて調査範囲を拡大していく形でボトムアップのような調査を行っています。 *2

推測は根拠を示す

原因がはっきりとするまでは、仮設と検証を繰り返しながら特定を行います。観測したメトリクスやログから原因を推測し、仮設を立てそこに対して調査や検証を行うかと思います。

当然ながら上辺のメトリクスのみをさらっただけの憶測や思い込みは禁物です。必ず調査する対象については根拠を示し、原因の推測を行います。ただでさえ緊急時で時間がない中、闇雲に調査することは時間の無駄です。

影響とその範囲

原因を特定した後、その障害による影響と考えうる最大の影響範囲を確認する必要があります。サービスの利用者にとってはこちらのほうが重要です。

影響範囲が数人なのかそれとも数十万人のユーザーかで、どのような対応をとるのか、公式で障害による謝罪を行わなければならない規模なのか等が変わってきます。何らかの根拠を持って説明できる数値が必要です。これらを集計する必要があります。

例えば決済が絡んでいる処理の場合、原因によっては何らかの復旧(もしくはやり直し)対応が必要になる可能性があります。障害がビジネスに対してどれくらいのインパクトがあったのかをすぐに報告する必要があります。

暫定(恒久)対応

何らかの暫定対応(もしくは根本的な解決がすぐできるなら恒久対応)を施す必要があります。根本的な解決が即図れれば一番良いのですが稀です。

しばらくは障害が起こりうる原因を認識しつつ、共存しながら延命を図る対応を迫られます。過去経験した対応については以下のようなものがありました。

  • データ不整合が発生したならばその状況の調査と是正
  • 再実行が必要な処理があるならば、その対象の抽出と手動での再実行
  • 一時的なAWSリソースの増強による延命措置及び、事前に危険水域にあることを認識できるメトリクスの追加
  • 壊れてしまった環境やイメージの復旧作業

Python, Ruby, Shell等のスクリプトによる(もしくは手作業)調査や復旧作業を行います。この暫定対応の際にはいくつか気をつけるべきことがあります。

対象を絞り込むための調査をする際に、読み込みのみでも本番環境へのリソースの負荷を必ず考慮する

読み込みのみでも当然リソースへの負荷がかかります。うっかり全件を走査し二次被害を発生させないように注意が必要です。場合によってはリソースの増強等を行い、稼働サービスへの影響を最小限にします。

場合によってはあるタイムスタンプのスナップショットからデータの複製を行い、そこに対して調査を行うという手順も有効です。ただし、一般的にスナップショットからのデータ複製には時間がかかるので、その時間込みでの作業時間が必要になります。

データ更新が必要な際には細心の注意を払う

当然ながら復旧対象でないデータに対して、強制的な更新をかけることは望ましいことではありません。

そのため、更新対象の抽出はデータ更新の一環で行うのではなく別途作業を分けて、実際に抽出した対象が正しいことが確認できてから、その対象に対してデータ更新を行うのが良いと個人的には考えています。

対象の抽出から更新まで人の手を介することなくできるのが一番良いのですが、緊急時に実装したコードがどれだけ信頼できるのかわかりません。私は自信がないので対象を必ず確認するようにしています。 *3

書き込みは読み込み以上にリソースの負荷を考慮します。読み込みの場合は、リードレプリカを利用したりスナップショットからの復元によって負荷を分離することができますが、書き込みの場合は本番環境のデータストアへ書き込まねばなりません。

また、対象調査段階からさらに時刻が進んでいるため、その間のデータ差分もどのように扱うかは調整が必要になります。

現在の状況観測(記録役)

司令塔、調査担当のみでは難しいのが記録と現在の状況の観測です。障害の状況にもよりますが、一度発生してしまうと継続的に回復できないものと、ある期間発生してその後回復しているものがあります。

特に前者の場合、対応が完了するまで障害状態が一定である保証はありません。時々刻々と状況は変化します。原因調査を行っているメンバーは過去発生した事象に目を向けて全力で取り組んでいるため、「現在」の状況を観測できる目がありません。現在の状況をこれ以上悪化させない、そして状況が変わったことをすぐに気づくために、これらを観測できるメンバーが必要です。

状況を悪化させないための作業としては以下のようなものが考えられます。

  • 次に障害状態になりそうなインスタンスを退避し、新たなインスタンスへ入れ替える
  • リソース状況が切迫しているならばリソースを増強して対応までの延命を図る

また記録役も重要です。状況の推移とともにどのような対応を行ったか、どのようなアナウンスを行ったか等をすべて時系列で記録します。これらは後の障害報告書に記載する重要な記録となるため、障害発生から収束に至る全てのイベントについて記載する必要があります。(専用のSlackチャンネルを作ってそこに書き溜めていくのは良いかもしれません。自動的にタイムスタンプが付与されるので)

記録役と兼務となっていますが、もし障害状況が継続し、状況が悪化している状況がある場合は明確に切り離します。

役割が大事

Yakst - インシデント指揮官トレーニングの手引き にも書いてありますが、障害対応時には一時的に明確な役割による階層構造が必要です。必ずこれらの役割を担うメンバーを決めてから事に当たります。

自らこの役割でやると宣言しても良いですし、誰かがあなたはこの役割です、と任命しても良いですが、何の役割もない状態で対応チームに入ってもあまり意味はありません。

もしアドバイスや様々な情報を持っているならば、それを司令塔へ伝え、場合によってはXXの役割で入ってくださいという依頼があるかもしれません。その場合は、与えられた役割の責任の中で調査、作業を行います。すべての決定権は司令塔が握っているのでそれに従います。

チームが組めるほど人材がいない場合は?

開発メンバー等でも上記の役割に従ってであれば問題なく作業ができるはずです。 *4

それでも障害対応に人材が割けないのであれば、諦めてすべてのロールを一人でやりましょう。様々な割り込みが入ってきたり怒号が飛んできますが、頑張りましょう。 *5

まとめ

実際に書き出してみると、運用をやっていた人たちからすると当たり前ではないかと思われていること、すでに知見としてまとめられているものも多く、自分は車輪の再開発のごとく同じような経験をしました。似た道のりをたどった結果、Yakst - インシデント指揮官トレーニングの手引き ここに書かれているものと同じような結論に行き着きました。

来年もまた安定したサービスの提供へ向けて頑張っていこうかと思います。

クラスメソッド の事業開発部ではソフトウェアエンジニアを募集しています

現在私は事業開発部で prismatix というサービスの開発及び運用に携わっています。 事業開発部ではソフトウェアエンジニアを募集しています。

もし興味のある方がいましたら、こちらのページを見ていただけますと幸いです。

来年もまたよろしくおねがいします。

参照

脚注

  1. 同じ障害、同じ状況があったとしたら、それはエンジニアとしての完全敗北だと個人的には思ってます。暫定対応で延命できているならば障害が起きる前に対処するべきだし、障害が発生するまで気づけないのは監視設定の見直しができていない。
  2. AWSの障害よりもアプリケーションの不具合のほうが確率的に高いため。
  3. とはいえ件数が多い場合は全件確認は無理なので、ランダムピックアップで確認する程度です。かけられる時間と確実性とのトレードオフになります。何をもって「更新対象である」という定義ができるならば、それを確認するスクリプトを書いて全件確認するという方法もあるかもしれません。
  4. 開発してるのにログの場所がわからないとかはないはず。ただし顧客環境へのアクセス権限がない可能性があるため、そういったものは別途調整が必要です。
  5. 心身ともに疲弊するので本番環境の障害対応を一人で対応するのはあまりオススメしません。一週間で3kgくらい痩せられるかもしれません?