emahiro/b.log

日々の勉強の記録とか育児の記録とか。

障害対応時のTODOリストをまとめてみる

Overview

先日久しぶりの障害対応を行ったときに、色々鈍っていたなと痛感したのと、いくつか改めて気づいたこともあるのでその振り返りもかねての記録です。
なおTODOリストとエントリ名はしてますが、実態はかなりポエムに近いし、勢いで書いたところがほとんどなので拙い文章であることや、ところどころ話が逸れてること自体はご容赦ください。

動機

この記録を書こうと思った動機は、障害対応(インシデント対応)に関しては、危機管理側に立った情報はいくつか出揃ってきてるなという印象を持っている一方で、実際に現場で障害対応するときの手順だったり、自分自身まず何からやってるっけ?どういう順序で情報を出してるっけ?と言った実業務に即した内容はあまりないので、いい機会なのでいくつかまとめて、記録として残しておこうと思ったことです。
以下でリストとして出して、それぞれどんなことしてるっけ?って言うのをまとめてますが、もしかしたら今後増えていくかもしれません。

障害が起きたときにやることリスト

  • 障害を報告する。
    • エスカレーション。
    • 切り戻し。
      • 直近のリリース影響などが疑われる場合。
  • 一次対応
    • ケースバイケース。
    • だいたい原因調査と並行して行う。
  • 原因調査。
    • 事象の把握。
      • 期待する動作の確認。
      • 期待する動作になっていないときに、どこまでが正常に動作していて、どこからが異常なのかを把握する。
  • 原因の切り分け。
    • どこに原因があったのか?
    • コードを追って原因を特定する。
  • 障害報告書を書く。
    • 事実を集めること。
      • 書くことリスト
        • 何が起きたか?
        • どれくらい継続したか?
        • どれくらいの影響があったか?
        • 何が原因か?
          • 対応はどうするのか?(暫定・恒久)
          • 人に目を向けない。仕組みに目を向ける。
    • エンジニア以外の人が読む文章であることを意識する。
      • 専門用語は正しく伝える最低限でなるべくツールの名前などは一般化する(もちろん限界はある)。
  • 修正対応
    • 原因が特定して、修正できるのであれば修正してしまう。
    • 時間がかかるようであれば別のタスクとして切り出す。

障害を報告する

まずやるべきはこれだと思っていますが、この初動が一番難しいと思います。
というのもエンジニアなら、何かしら意図しない挙動があったときに、この振る舞いは自分が混入したものなのかどうかが気になってしまいますし、何より、障害を発生させてしまった場合に、そう報告するのって実際かなりストレスがあるなと感じてます。

ただし、そんな自分の気持ちなんかユーザーには一ミリも関係ないので、とりあえず「ヤバみ」を感じたら「障害です」と上に投げちゃう方がいいのかなと考えてます。
もちろん、ちゃんと調査したら違った、みたいな話は出てくると思いますし、そうなったらそうなったらで「拙速だったすまん」と謝ればいいかと思います。その辺の見極めって本当に難しいと思うので。自分もできてないし、「障害か?」の裏をとってる間にも状況は悪化してるかもしれない、と言うことを考えると迷ったら安全に倒す、くらいのメンタリティが大事なのではないかと思っています。
そしてこの辺の初動のスピード感については、すぐにエスカレーションが上がってくるようなチームになってることと密接に関わっていそうなので、よく言われる「組織における心理的安全性」や「人ではなく仕組みに目を向ける」といったことが体現してる組織やチームは障害対応の側面から見ても強いと思います。

話が逸れましたが、この障害かどうかの報告については、とりあえず15分程度ガッと調べて裏が取れれば、そう報告するし、迷ってもとりあえず「障害かどうかの判断に迷ってる」と言う前提と一緒に上に投げちゃうのがいいのかなと思います。
調べる時には自分は大体開発環境でも同様の事象が発生するのか?(再現手順踏まえて ※)と言うところを調べてます。
これは商用環境と開発環境で同じコードが動いてることが前提だったりするので、日頃から同じコードになるようにしておくことはこう言う時にきっと活きます。
実際のところ開発環境の検証で見つかると儲けもんなのですが、開発環境では再現しないみたいなこともしばしばあるので、その場合は再現できていない前提で、上述したように報告します。

次に直帰何かリリースがあったかを確認します。
リリースがある場合は、そのリリースによる変更が原因であることが疑われるので、まずはユーザー影響を最小限に抑えるために切り戻します。トラフィックの向き先を1つ前のバージョンに戻すか、そう言う仕組みになっていない場合は、リリースのコミットごと revert して再デプロイするのか。とはいえ、リリースによってデータに変更が生じてる場合などは...どうするんですしょうね...そのオペレーションは経験がないのでよくわからないです。
生じている変更が切り戻してもサービスに影響があるかないかをまずは確認しますし、それで影響が出る、となったらそれこそ、切り戻せないので、原因を早急に突き止めて爆速でパッチ当てる...とかになるんですかね...。 これもやったことはないので自信ないです。

※ 再現手順ってまじで大事なので、もしおかしな挙動を上げる時は再現手順とセットにして欲しい、と言うのはエンジニアとしては密かな願いでもあります。何でもかんでもバグ!障害だ!として上げられたら心折れます。

一次対応

ユーザー影響をひとまず止めるために最初にどう言う対応をするのかエスカレーションしたタイミングで何かしら決定があるはずなので、その作業を先に行います。 エンジニアで現場で実際に作業をする場合を考えると、上述した切り戻し作業を行うことになると思います。
このタイミングではビジネス側で何かしら決まって、すぐに次の原因調査に移行できることもあるでしょうし、ここは原因調査と並行で進むものですし、ケースバイケースだとは思います。

原因調査

何かしら期待しない動作がある、そしてユーザーに不利益がある、というような事象に遭遇したときに、どうしてその状況になってるのかを調査を行います。
調査を行うにあたっては手順は主に「事象の把握」と「原因の切り分け」の2つの工程を経て、原因を突き止めるまでに至ると考えています。
そしてこの原因調査のタイミングで最初にやってはいけないと思ってるのは コードを最初から追いかけること だと思います。
もちろん、障害の発生したポイントがすでにドメイン知識を持っている範囲で、かつ障害の発生に関連した変更に関わっていた場合などはすぐに原因を特定してパッチを当てたり、迅速な報告ができる、などもあるとは思います。
しかし、ここでは、自分が深く知らないドメインの領域や、触ったこともないマイクロサービスで発生した障害を想定します。
自分の知らないドメインであれ、サービスに関わっている以上は当事者として関わっていかないといけない、しそう言うところの障害が結局多い。と思っているからです。

話を戻します。
まず最初のプロセスとして、事象の把握で何をしてるかですが、ここではまずどう言う症状が起きてるのか?から確認していきます。そもそもどういうことを期待していて、今そうなっていないのか、がわからないと調べようも対応のしようもありません。
そのため、まずはプロダクトの振る舞いとして「何を期待するのか?」を確認するのが大事です。
ときには、この段階で「そんな風には作ってない」と言う想定外の使われ方、みたいなケースがサッと出てきて、次のステップに進めることもあります。これができればラッキーです。あとはその裏を取るためにコードを追う作業にいけるので。
次に期待結果を得るためにはシステムがどう言う風に動く必要があるのかの見通しを立てます。ここまでできてから実際に現状のシステムに置いて「どこまでが正常に動作していて、どこからが期待した動作をしていないのか?」の切り分け作業を進めながら原因の切り分けと特定を行なっています。
実際に原因を調べるときは データの状態やり、リクエストログなりを手がかりにして、1つ1つ切り分けを行なっていくと思います。
そしてこの切り分けを行うときの注意点としては、意図した振る舞いになっていないからといって、すぐにUI側の実装を疑ったり、みたいなことをしないことです。(僕はこの間やりました。完全にミスでした。)
UIはAPIから返したデータを描画するように作ってあるかもしれないし、そうした場合にはAPIのレスポンスが意図した振る舞いをするためのレスポンスになっていない、と言うことになります。

ここで初めてコードを追いかけることになると思います。
結局ここで伝えたかったのは、すぐにコードを追うな。コードを追っかけ始めるのは一番最後、と言うことをルールとして決めるだけでも障害対応の進め方は変わってくるのではないかな?ということでした。

障害報告書を書く

原因調査と並行して障害報告を書きます。 ここでは、原因調査でわかっている事実を書きます。逆を言えば、原因が見つかっていない場合は 調査中。判明次第更新します と書いて「...に原因がありそうです」みたいな憶測は書きません。 この文章はエンジニア以外の人向けに書かないといけないので、専門用語やツール名は正確な情報を記述するための最低限に留めます。

書く内容としては以下かなと思います。あくまで僕の考えるところが大きいので、チームごとに内容は変わってしかるべきかと思います。

  • 障害内容
    • 何が起きたか?
  • 影響範囲
    • どれくらいのユーザーに影響があったか?
  • 障害発生時刻
    • どれくらいの時間続いたのか?
    • すでに収束してるのか?現在も継続中なのか?
  • 対応について -1
  • 原因
    • なぜ障害が発生したのか?
  • 対応について - 2
    • 恒久対応
      • 原因となった事象に対してどう言う対応を取るのか?
        • 多くはコードを修正することになると思います。
        • または既存の何かしらの仕組みを変更することになると思います。

繰り返しですが、ここでは 事実のみ を記載することがポイントです。そして、原因は Blemeless である必要があります。原因は人に求めず、仕組みに求めます。

修正対応

原因を特定できた、修正できるのであれば修正しましょう。この修正をどのタイミングでリリースするかは、すぐの時もあるでしょうし、翌営業日、と言うようなこともあると思います。障害が発生したのがピークタイムの時間の場合には、安全を期して翌営業日リリースと言うパターンが多いと思います。
すぐには改善できない原因もあると思いますし、その場合は別途イシュー化して対応の優先順位を意思決定層と相談することになると思います。
まぁ優先度周りについては現場に居る人間としては、あまり意識するところではないかもしれません。

振り返り(と言うかポエム)

大なり小なり、障害って日々発生してるものだと思っていて、ユーザーに対して期待する価値を提供できていない、もしくはサービスが壊れていると言う状態がままある、サービスに関わるエンジニアとしては常に向かい合わないといけないことだと思います。そんなしょっちゅう起きてても、オイオイ...って思いますが、成長して、常に何かしらの変更を加えているサービスでは、障害は日々発生する可能性があります。

正直このエントリで書いたことが自分で「ちゃんと」できてるかと言われると、できてないことの方が多いです。
障害対応ってまじでストレスのかかる仕事だし、起こした当人が一番頭混乱してるので、二次災害をどう起こさないか、みたいなところで最低限の冷静さを保ちながらチームをうまくまとめるのは実はめちゃくちゃハイスキルな対応です。
こればっかりは完全に場数勝負、経験が物を言う世界なのかなと。。。
昔ある人にエンジニアの戦闘力をどこで測ってます?と言う質問をしたときに「障害対応を行ってきた経験があること」と言うニュアンスのことを言っていて、改めてなるほどと思わされます。

そして、いくつかエントリの中で触れたリストの中に「...と並行して」と書きましたが、この言葉の指す通り障害対応はチームで行う作業です。
誰かが原因調査をしてるときに並行して、エスカレーションする内容をまとめたり、それを障害報告の文章に起こしたり、と言うことは協同して行います。

最後に、原因の切り分けプロセスにおいて、技術に詳しいことはそれ自体がアドバンテージになります。
例えばバックエンドのエンジニアが、サービスで使われてるフロントエンドの技術を少しでも触ったり、理屈をわかっていれば原因の切り分けの速度は上がります。
土日に勉強しろ!とは思いませんし、土日に勉強してる人が偉いとも、評価されるべきとも考えてはいませんが、日頃の技術的な研鑽はいざというときに間違いなく活きる、と言うことは事実として存在すると思います。

例えば Vue のコンポーネントにおいて、props の受け渡しがどう行われるのかを知ってると知らないとでは、APIから正しいデータを返してるかもしれないときに UI 側の原因だと突き止めることはできません。
それを作った人に聞ける、と言う恵まれた環境であればそれはそれでラッキーですが、現実はすでに作った人がいない、なんてことはザラにあります。
ドメインの知識はないけど、技術を理解していれば作った人ほど速くとは行かないまでも、切り分けを行いながら原因にたどり着ける可能性は増します。

正しく技術を理解していること、そしてそれを使えるように日頃から素振りをしてるとそれが思っていないときに日の目を見たりするので、自分ももう少し素振りの時間は取りたいなと思いました。本当は業務でそれができるとベストではありますが。

余談: カオスエンジニアリング

カオスエンジニアリングとは、雑に言うと障害対応訓練(雑すぎて刺されそうですが)で、マイクロサービスアーキテクチャのような小さなサービスが複数で協調して1つのシステムを作り上げてるケースの障害対応だったり、サービスの安定運用のために、それこそ日頃の素振りとして行われる類のものなのですが、例えば、仕様の漏れとか想定外の使われた方を原因とした障害って実際訓練しようがなくないですかね?なんてことを考えました。

そもそも想定してない使われ方をできてしまうことが問題ではありますが、訓練項目に入らないようなことが発生したら、訓練でやったこと全ては活きることなく、その時々で最善を尽くす他ないのかなと。 もちろん、訓練の中でログの見方だったり、APIの仕様だったりをシュッと調べられて原因特定のスピードは改善していくと思うので訓練や素振りが全て無駄にはなりませんが、訓練項目書を作る、と言うか仕様を把握するって難しいなと....。

と言う単なるぼやきでした。

まとめ

まとまってないけど、障害対応はエンジニアとして成長するいい機会だと思います。