サービスで障害が起きた時の調査方法まとめ(バックエンドエンジニア向け)


こんな人に読んで欲しい

  • サーバーサイドエンジニアの人
  • 障害・エラー発生時にあわわわわってなってしまう人
  • 担当しているサービスをあんまり理解してないから調べ方わからん、と言う人
  • どこから調べればよいかわからない人

何について話す?

WEBエンジニアとして、サービスを提供する開発をしていると

  • リリース時
  • 運用中
  • 何もしていないのに突然

などエラーや障害が発生することがあるでしょう。
自分が所属するチームでは一つのコンテンツを長く管理しつつ、
他チーム離散など政治的事情で新しいコンテンツを受け入れる機会が多いです。
新しいコンテンツを受け入れた際に、突然来ます、エラーが、障害が・・・

そんなエラーが発生した際にコンテンツへの理解がなくても原因を特定できた、
という機会がままあります。
(テーブル構成とかアーキテクトとか全く知らないけど、エラーを見つけて対応もできた、とか)

そのような経験を通して、コンテンツへの理解があるからこそ調べられる調査と、
理解がなくても調べられる調査があると感じました。

よくわからないコンテンツでもある程度の調査ができる勘所を紹介していきます。

調査能力を身に付けるための技術を身に付ける

コンテンツへの理解がなくても調べられる、と言いましたが技術的な知識は必要です。
AWSを扱っているのであれば「CloudWatchLogsってなんぞ?」
Linuxサーバで構築しているのであれば「apacheってなんぞ?log出力されているところってどこぞ?」
などと言われてしまうと調査ハードルは格段に上がると思います。

以下の資格を取れる程度の知識を身に付けておくことをおすすめします。

  • AWSソリューションアーキテクト(最低限クラウドプラクティショナー程度)
  • LinuC(最低限Level1程度)

これらの知識がなくてもこれから提案する調査の勘所は参考になると思うので、
引き続き見てもらえますと幸いです。

障害発生時フェーズ

1.上司・関係者に報告する

兎にも角にも関係者に報告しましょう。
このような報告を怠ってエラー解消に尽力しがちですが、あとで何故すぐに報告しなかったんだ!!となってしまいます。障害発生を関係者が検知できていないと、関係者が行うべき対策が遅れてしまうことになります。他の人にお願いするでもいいので報告しましょう。

緊急対応レベルを即座に判断できるのであれば「緊急対応レベル(判断基準は以下参照)」であれば即座に報告する、など裁量があってもいいと思います。判断に時間がかかるならとりあえず報告しましょう。

また、自分起因のエラーが発生した時に

この事象を隠蔽することができないか

頭をよぎることがあると思います。
自分も何度も頭をよぎりますが、これは隠蔽しようとしてばれた時が最も怖いです。
自身に対する信頼が失墜します。誠実さを示して関係者に正直に報告しましょう。

2.緊急レベルを判断する

まずこのエラーは即時対応する必要があるのか、今週中に対応すればいいのか、
それとも放置してもいいものなのかを判断する必要があります。
会社などで決められているルールがあればそれを遵守すればいいですが、自分であれば以下のような基準で考えています。

緊急対応レベル

  • サービス提供が不可能な状態が発生している(操作できない・不正データが登録される等)
  • サービスは提供できているが利用者のユーザビリティを著しく落としている(画面の表示崩れ等)
  • 簡易的な攻撃で不正動作ができてしまう状態(パラメータ操作やテキストエリアでSQLインジェクションができる等)

近日対応レベル

  • 社内管理画面、運用をする際に弊害があるが、代替手段が取れる状態
  • ユーザへのサービスに影響がないエラーログ等が出ている(Noticeエラーなど)

放置レベル

  • ユーザーが使う頻度が極端に少ないコンテンツでサービス提供はできている状態でのエラー
  • バッチなどで自動リカバリする仕組みが存在しているもの

ログ調査フェーズ

ここからが調査についてです。

1.障害が発生しているサーバーを特定する(知っている場合は省略可)

心当たりがあるサーバに接続して以下の部分を調べます。
apache設定を見て、対象コンテンツのディレクトリ設定があれば対象サーバになります。
apache設定がそもそもどこにあるかも特定する必要がありますが、以下で動いている可能性が高いです。

OSとインストール方法 ディレクトリ
CentOS,RHEL,Fedoraなど(パッケージ) /etc/httpd/conf/
SUSE,Debian,MacOSなど(パッケージ) /etc/apache2/
ソースインストール /usr/local/apache2/conf/

以下のコマンドを入力すればある程度のapacheの場所がわかると思います。

$ ps aux | grep httpd

▼参考Qiita
Apacheの設定ファイル httpd.confの場所

2.ログ出力の場所を特定する

対象ソースの中からログをどこに吐き出しているかソースをgrepしましょう。
ログ設定は以下のようなパターンが多いと思います。

  • アプリケーション独自に定義している
  • プログラミング言語のフレームワークの設定で定義している
  • apacheでログ設定されている
  • 各ミドルウェア・プログラミング言語のデフォルトのログ出力場所(/var/log/php等)

もしもソースにそのような設定が無かった場合、apacheを見たり会社独自のナレッジサイトがあるならそこから調査するのもいいと思います。

3.ログファイルから対象エラーログを特定する

対象のディレクトリ設定までわかれば、実際にログファイルの中で原因となるエラーを特定します。
もし対象ディレクトリ内に複数ファイルがあってどのファイルかわからない場合、障害が起きているサービスを動かしながら以下のコマンドを実行するといいです。

find [ログディレクトリ] -mmin -10

このコマンドを実行することで、対象サービスを動かした際にログが出力されたファイルが何なのか、ある程度特定することができます。

対象のファイルがわかったらファイル内をgrepしてみましょう。
grepの仕方は様々ですが以下のように調べていくといいと思います。

cat [対象ログファイル] | grep -i error
cat [対象ログファイル] | grep -i exception

とか、エラー系の文言でgrepすると引っかかると思います。もしソースのログ出力で特定のメッセージを出力することがわかっているなら、そのメッセージでgrepしてみるといいと思います。

もしくは以下のようにtailfコマンドをしつつ、エラーが発生しているサービスを動かして吐き出されたログを見ていく方法もおすすめです。(もしtailfでログが多ければ、grepで絞り込むと調査しやすい)

tailf [対象ログファイル]

エラーログが出力されていない場合

アクセスログを見てそもそもサーバまで到達しているか確認する

コンテンツによってはエラーログが出力されていないものもあると思います。
本来であればエラーログは出るはずなのに出ていないと言うものもあるかもしれません。
その切り分けをしたいのであれば、アクセスログを見てサーバまで到達しているかを確認すると良いと思います。
もし到達していない場合はネットワーク側の問題かもしれません(今回WEBエンジニア向けなのでネットワーク問題は割愛します)

→インフラ担当がいればそちらに確認しましょう。

エラーログを仕込む

そもそもソースでエラーログが出力されていない場合はエラーログを出力する処理を組み込んだ上でリリースして計測した方がいいかもしれません。かなりクリティカルな場合はインフラ側でアクセスを止めてメンテナンス画面にするなど、サービスを止める選択も関係者と相談する必要があります。

WEBコンテンツであればデベロッパーツールでエラーが出ていないか確認する

ログが出ていなければそもそもサーバ側が原因ではなく、
フロント側のJSなどでエラーが発生している可能性は大いにあります。

GoogleChromeなどでOption+Command+iでデベロッパーツールを開き、「Console」から何かエラーが発生していないか確認するといいと思います。(以下のような感じ)

→フロント担当がいればそちらに確認しましょう。

プログラム調査フェーズ

ここからはログである程度のエラーを特定したら、そのエラーを元にプログラムにどのような問題があるか調査していきます。

1.調査はサーバ上で行わない

まず、多くの人は対象ソースの調査をログ調査に引き続きサーバで行いがちな印象があります。
もし調査している人がlinuxコマンドをある程度体得しており、vimmerであれば止めないのですが個人的に対象ソースをSCPツール等でローカルに落としてきて、エディタや開発統合環境を使用して調査した方が良いです。

ローカルで調査をするメリット

  • 開発統合環境やエディタなどで関数ジャンプができる(プラグインを入れておきましょう)
  • 全体grepを行った後に、対象ソースに飛びやすい(個人的におすすめのエディタはsublime)

2.各プログラム言語のデバッグ方法を理解する

テスト環境やローカル環境でも同事象が発生しているが、原因がわからない場合、
愚直ですが一つ一つの処理を追っていって原因を特定する必要があると思います。
そこで必要になってくる技術がプログラミングのデバッグです。

言語にあったdebug方法を理解しておくことで、原因特定までの速度が格段に上がると思います。

Printデバッグを極力使わないように意識する

Printデバッグというのは

echo $test
exit

などのプリントして変数の内容を確認しながらexitで処理を止めたりしてデバッグしていく方法です。
この方法は簡単かつ脳死しながらデバッグをすることができるのですが、各プログラミング言語にはよりわかりやすくデバッグする仕組みが存在するので、そちらを積極的に使用していくべきです。
例えば以下のような例になります。

言語 デバッグ方法
PHP debug_backtrace関数を使用したPrintデバッグをする、xdebugを使用する
NodeJS debugコマンドを使用する
Ruby byebugコマンドを使用する

調査結果報告フェーズ

調査をある程度することができたら、再度関係各署に報告を行います。
報告する内容は以下のような項目です。

1.報告する内容

  • 発生した事象
  • 対象のサービス
  • 発生期間
  • 発生期間中のサービスへのアクセス数、障害影響件数
  • 発生した原因
  • 対応内容(暫定対応と恒久対応の提示)
  • 再発防止策

など提示して報告すれば良いかと思います。

2.障害影響件数の抽出方法

この障害によってどの程度の影響があったか?は報告時に提示すべき項目かと思います。
その際に件数洗い出しで見る部分はアクセスログとエラーログです。

① エラーログ件数ー実際その障害によりエラーが発生した件数はいくつか
② アクセスログ件数ー障害発生中にどの程度のアクセスが来ていたか

基本的には①の件数を出せば良いのですが、②は画面崩れなどフロント側で発生していたエラーに対する件数を図る際に抽出すると良いと思います。

kibanaなどのログをGUI化するサービスを使用していない場合は、愚直にcutコマンドやxargsを駆使して対象エラー件数を抽出しましょう。

さいごに

いかがでしたでしょうか。
会社によって環境は様々なので、障害調査に関する正解をここで提示できないのですが、
自分の経験から他のところでも上記のような観点で調査をすれば、原因特定が早いのではないかと思いまとめさせていただきました。
ご参考いただければ幸いと思いつつ、もっと良い観点での調査方法があればコメントいただけますと幸いです。