# サービス障害が発生した場合の対応方法

サービスを運用していると、様々な障害に遭遇することがあります。その際、原因特定のためにトラブルシューティングをしていくことになりますが、ここでは(ある程度)汎用的に適用できるトラブルシューティングを進めていく上での考え方をまとめます。\
特定のサービスに向けたものではなく、一般化して記載しています。そのため、実際にはここに書かれた概念を前提に、サービス固有の知識と組み合わせてトラブルシューティングを進めていくことになります。

特にトラブルシューティングになれてない場合にはこれらを意識しておかないと、当てずっぽうな思いつきのトラブルシューティングになりやすくなります。その結果、原因特定まで遅くなったり、たどり着かない可能性も考えられます。慣れている人は無意識にできていたり、経験から原因の勘所に当たりをつけられることもあります。しかし、ここでの考え方を抑えておくと、慣れていないサービスや未知の事象であっても比較的スムーズにトラブルシューティングをすることに繋げられるかと思います。

大まかに一般化したものであるため、ここに書かれた事象の例外に出くわすことも多々あります。その場合は、経験値やさらなる深堀りで対処していくことになります。が、ここではそういった内容は対象外とします。

サービスのどこかしらに異常が見られるといった場合には、こちらの記事の内容を参考にしていくと調査の役に立つかもしれません。\
サービスを利用しているときに、問題が発生していて問題箇所が漠然としているような状況を特に想定していますが、すでに問題箇所が特定のサービスであるとはっきりしている場合にも役に立つかと思います。問題箇所がはっきりしているように見えても、それより上流のコンポーネントが問題になる可能性もあるので、そのような発想の際にも役立つかもしれません。

なお、具体例を書き始めると、全くと言っていいほどキリがなくなってしまうので、例はあまり多く出せていません。\
備忘録のために、自分で書いていてあとから何言っているのか最低限に理解できる程度に例を出していますが、中途半端な情報過ぎて却ってわかりにくくなっていたら申し訳ありません。\
読んでいてもいまいちピンと来ない場合は、実際のトラブルシューティングの際にここでの話を思い出しながら照らし合わせて対応してみると良いかも知れません。

普段仕事でやっている人にとっては、当たり前に感じられる情報しかないと感じられる方もいらっしゃるかもしれませんが、悪しからず、、

おかしなことを言っていたり、もっといいやり方あるよ的なことがあれば、TwitterのDMやメール等でも結構ですので、そっと教えていただけると嬉しいです。

**お決まり文句ですが、この記事の内容はは所属組織の見解とは一切関係なく、あくまで個人の考えに基づいているということについて強調させていただきます。**

### 基本情報

トラブルシューティングをはじめるにあたって、システムのアーキテクチャの理解が大事です。どのような構成になっているのかを理解していなければ想像で原因分析をすすめていかざるを得ません（シンプルで典型的なアーキテクチャであればなんとかなるかもしれませんが）。

アーキテクチャを把握した後は、まずは以下のような情報を収集し、整理しておくことが大事です。ここに書いてあるものはあくまで一例です。状況によって取得するべき情報は変わります。サービスによって挙げているものの粒度が異なることもありますが、すべて列挙することを目標としているものではありません。また、挙げたものすべてがいつも必要になるわけではありません。基本となる考え方のおおよその参考として捉えていただければと思います。

* 日時
  * 事象開始時刻
    * その時刻に何か変更が行われたか
    * その時刻で何かイベントが発生していたか
  * 事象終了時刻
    * 現在も継続しているか
  * 事象発生頻度
    * 事象の再現性
      * 再現性がある場合、再現方法および確認方法
        * 行った操作の手順
  * タイムゾーン含む
    * 見ているログやアプリケーションによってタイムゾーンがUTCであったりJSTであったりPSTであったりばらばらなことがあるので、それぞれを明確に意識する必要があります。
* リソース
  * アクセス元/先
    * 影響範囲
      * アクセス先(元)が複数ある場合どのリソースか、全体のうち、どのぐらいの割合で発生しているか
      * 複数リソースあるうちの一部で問題が発生している場合における、正常なものと異常なものの差分
  * 特定の処理のみか処理全体か
    * 例. Webサイトに対するリクエストで、URLの特定のパスのみか、パス全体か
    * 例. RDBMSで、特定クエリーのみか、クエリー全体か
* 確認している事象
  * 詳細
    * サービスに接続できないといった粒度で終わるのではなく、接続後即エラーが返ってくるのか、長い時間を待ったあとにエラー画面が返ってくるのか。長い時間を待つ場合、その具体的な時間等
  * エラーメッセージのテキスト文
  * 上記困難な場合、確認している画面のスクリーンショット
  * 具体的な実行コマンド
* 環境情報
  * 利用しているOSやアプリケーションの種類やバージョン情報
    * Webサーバーの種類やアプリケーションサーバー
    * SDK/CLI
  * 実行しているユーザー情報
    * AWSであればIAMユーザー名、IAMロール情報等（、AWS Organizationsのサービスコントロールポリシー(SCP)）
      * 例) API実行の権限エラー等
* ログ/調査コマンド 一例 (必要な情報は状況によるので、あくまで大凡の参考までに記載)
  * コマンド実行時のデバッグ出力
    * `-v`オプションや`--debug`オプションなど、利用しているコマンドや関数に用意されているオプションを確認しましょう。
  * ロードバランサー/Webサーバー/アプリケーションサーバー
    * アクセスログ/エラーログ
      * Nginx/Apacheのアクセスログやエラーログ
      * ロードバランサーのアクセスログ
    * 設定ファイル
  * ネットワーク環境のログ
    * AWSであれば、VPCフローログ
  * OS内の情報
    * メトリクス (Ref. [Linux Performance Analysis in 60,000 Milliseconds](https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55))
      * `uptime`
      * `dmesg | tail`
      * `vmstat 1`
      * `mpstat -P ALL 1`
      * `pidstat 1`
      * `iostat -xz 1`
      * `free -m`
      * `sar -n DEV 1`
      * `sar -n TCP,ETCP 1`
      * `top`
    * ログ
      * Linux
        * `/var/log/messages`
        * `/var/log/secure`
        * `/var/log/dmesg`
      * Windows
        * `Application.evtx`
        * `System.evtx`
  * データベースのエラーログなどの各種ログ
    * RDBMS
      * MySQL/MariaDB
        * エラーログ
        * スローログ
        * 一般ログ
      * PostgreSQL
        * ログ(例: `postgresql.log.2022-03-21-03`)
      * Oracle
        * アラートログ
        * トレースファイル
        * リスナーログ
        * Statspackレポート、AWRレポート
      * SQL Server
        * エラーログ(例: `ERROR`)
        * エージェントログ(例: `SQLAGENT.OUT`)
        * 拡張イベントファイル(例: `test_0_1234567891011120000.xel"`)、トレースファイル(例: `test.trc`)
    * インメモリーデータベース
      * Redis
        * `INFO`コマンド(例: `INFO ALL`)
        * エンジンログ(例: `redis.log`)
        * スローログ(例: `SLOWLOG GET 30`)
      * Memcached
        * `stats`コマンド

上記について情報を収集後、例えば以下のように考えていきます。

* まずは、事象の影響範囲を抑えることが大事です。
  * 接続先/接続元が一部か全体で発生している事象か
    * 例えば、ロードバランサー配下の接続先のサーバーが一台のみで発生している場合は、そのサーバー自体の問題の可能性が高いと考えられますが、ロードバランサー配下のすべての接続先のサーバーで問題が発生している場合は、それらのサーバーで共通にしている処理、例えば、サーバーが依存している接続先のデータベースやデプロイ処理で問題が発生している可能性などが考えられます。もしくは、AMI（インスタンスを起動するのに必要なOSやボリュームなどが含まれたテンプレート情報のようなもの）を定期的に作成していて、ある時点から起動したバックエンドインスタンスが共通のイメージを使用するような処理をしている場合、作成されたAMIに問題がある可能性があります。
    * 同様に、接続元のあるクライアントのみで問題が発生している場合はそのクライアントに問題が発生している可能性が高いと考えられますが、すべての接続元のクライアントで問題が発生している場合は、接続先のロードバランサーやサーバーなどの問題の可能性が高いと考えられます。
  * 特定の処理のみか処理全体か
    * 例
      * URLで特定パスのみか複数のパスで起こっている事象か
        * レイテンシーが大きいリクエストがURLの単一のパスのみではなく、パス全体で発生している場合は、バックエンド全体が高負荷な場合や、バックエンドのCPUが低いといった場合にはデータベースなど外部依存に関する影響の可能性も考えられます。一方で、単一のパスのみで問題があるといった場合には、他のパスにはなく該当パスのみにある処理の仮定でレイテンシーに繋がりうる箇所を特定していくといった形で調査をすることにつなげていきます。
      * 単一クエリか複数クエリか
        * RDBMSで、単一クエリであれば、MySQLやMariaDB(、PostgreSQL)であればスロークエリの確認、Oracleであればスロークエリ機能はなくStatspack、AWRを見たり、SQL Serverであれば拡張イベント、sys.dm\_exec\_query\_stats(キャッシュされたクエリプランの統計)を見たり、AWSであればRDSのPerformance Insightsなどを確認
          * 他に大量にクエリが実行されていて、スロークエリが特定クエリのみであれば、そのクエリの詳細な調査を行う
            * MySQL、MariaDBであれば、例えば、EXPLAINなどでそのクエリの実行計画などを確認し、大量のレコードの中から少量のレコードしか取得しないにもかかわらず、テーブルスキャンが行われていれば、インデックスの追加などをする。適宜エラーログやperformance\_schemaなど、他の情報と合わせて確認
            * PostgreSQLであれば、例えば、EXPLAINなどでそのクエリの実行計画などを確認。適宜ログや標準統計情報ビューなど、他の情報と合わせて確認
            * Oracleであれば、実行計画の確認は複数の実行方法があるが、例えば、`V$SQL`や`V$SQLAREA`より当該クエリを指定して`SQL_ID`を確認し、`DBMS_XPLAN.DISPLAY_CURSOR`(実行例. `SELECT * FROM table (DBMS_XPLAN.DISPLAY_CURSOR('xxxxxxxxxxxxx'));`)を実行することによって確認 Ref. [212 DBMS\_XPLAN](https://docs.oracle.com/cd/F19136_01/arpls/DBMS_XPLAN.html#GUID-492CB99B-62C3-4FC3-951C-4BE876670218)
            * SQL Serverであれば、実行計画の確認には、推定実行プラン、実際の実行プランを利用 Ref. [実行プランの表示と保存](https://docs.microsoft.com/ja-jp/sql/relational-databases/performance/display-and-save-execution-plans?view=sql-server-ver15)
        * 複数クエリであれば、サーバー側のボトルネックになっていないかの確認のために、メトリクスを見渡したりする。エラーログも適宜なにかヒントがないか確認を行う
          * ディスクI/Oが頭打ちになっていたら、適切な処理性能のディスクに変更してあげるなど。RDSであればいくつか種類やオプションがあるので、それに応じて選択してあげる
* 事象がいつ発生しているか
  * ある時点から事象が発生している場合、例えば、以下のような可能性などのように絞っていくことができます。
    * デプロイや設定変更
      * 心当たりがあるものを深堀りしていく必要があります。
        * 対象の例
          * OS環境の変更やアプリケーションの更新、設定変更のデプロイ
            * コンテナイメージの入れ替え等、pull型による更新
            * Capistrano等のpush型のデプロイツールによるデプロイ
            * 仮想マシン（VM）イメージやAmazon マシンイメージ (AMI) の更新等
          * バージョンアップ
            * RDBMS等でエンジンのバージョンアップした場合は、それ以前のバージョンに適した統計情報になっている可能性があるので、`ANALYZE`などで統計情報を更新したり、Oracleであれば、そのバージョンに合わせた統計情報の設定をしてあげることなどできたり、統計情報を以前のものに戻したりすることができる。MySQLやMariaDBであればそういったことはできないので、`ANALYZE`で統計情報の更新をするなど
        * タイミング
          * 定期処理や何らかのトリガーによる自動デプロイ
            * 例: cronなどの定期処理、CI/CDによるデプロイ
          * ノード入れ替えに伴い、設定更新後の状態で起動
            * 例: KubernetesのReplicaSet、Amazon EC2 Auto Scaling
          * 手動デプロイ
          * メンテナンス時間
    * ワークロードの変化
      * イベント開始
      * サービスの特性上、利用者数が多い時間
        * こういったときのことに備えて、本番環境と同等もしくはそれに近いワークロードで事前に負荷テスト等実施して準備しておくことが大事です。
  * 接続Issueの事象が数回に一回といった場合は、少なくとも設定ミスにより疎通ができない可能性は低いことが想定できます。エッジケースで無い限り、明らかに可能性を無くせる設定箇所などから原因の切り分けを進めていくと良いでしょう。
    * ただし、ローカルマシンを前提に動作するような設定になっている場合に、複数マシンにルーティングされることで動作しないといったように設定ミスはありうるので、文脈に応じて柔軟に判断はする必要があります。
      * 例: ロードバランサーのセッション維持機能でステートフルな管理を期待する構成で、セッション維持を利用するための設定に問題
* 事象の再現性
  * 事象に再現性があると、原因箇所の絞り込みや事象発生時のログの出力の取得等の観点で調査が非常にスムーズに進めることができます。そのため、こちらの観点も大事です。
  * 再現検証が必要な場面もあるでしょう。効率的な調査のためには、スムーズに検証できる準備もしておくとよいでしょう。ただし、リソースの立ち上げっぱなしはコストがかかりますので、スクリプトや構成管理ツール、Dockerなどのコンテナ等で、必要なときに必要な環境をすぐに構築できるようにしておくことも良いでしょう。
* ログ/調査コマンド
  * 調査に必要な情報取得のために、バージョンごとにどういった機能やログを取ることができるのか確認しておいた方が良いこともあるでしょう。ソフトウェアや機能によっては、バージョンが新しくなってもあまり変わらないこともあります。久しぶりに触れると以前の実施方法が非推奨になっていることもありますので、アップデートを追いきれていない技術について利用可能な手段を再確認するのも良いかもしれません。

一度に上記すべての情報を揃える必要は必ずしもありません。原因の切り分けの仮定で必要であることがわかったものから取得していく方が現実的かと思います。その辺りは経験値や扱っている技術の知識が増えるにつれて、要件や緊急度等に応じて、調査に必要な情報を柔軟に絞ってけるようになるでしょう。しかしながら、上記の内容は基本的な情報といっても差し支えが無いでしょう。いざとなったときにこれらの観点を引き出せるようにしておくと良いでしょう。

### 原因の切り分け方法（被疑箇所の特定）

原因特定をする上で、思いついたものや目についたものを原因だと考え、当てずっぽうで調査をしても原因にたどり着かないことも多くなりかねません。まずは、システムの大枠を捉えて、考えられる可能性を列挙して、得られた情報から、可能性を一つ一つ潰していきながら、最終的に考えられる可能性が一つとなるようにロジカルに調査を進めていくことが、スムーズに原因を特定する上で大事です。

サービス開始から数年間障害なく運用していて、何も操作していないにも関わらず突然障害が発生した場合であっても、それが自分たちのアプリケーションの問題ではなく、利用しているクラウドの障害が原因などといきなり決めつけてしまわないようにしましょう（ただし、一見相反するようですが、クラウドを利用している場合であってもいつでも障害は発生するものと仮定してアーキテクチャを事前に検討して組む必要があります。複数台で構成するように高可用性を意識したり、インメモリキャッシュでノード障害が起こったことをトリガーに、メモリー上のデータが消えてしまったことで、サービスがダウンするといったことがないように事前に計画を立てておきましょう）。

熟練した方であれば、勘所を抑えており、最初から原因箇所を当ててしまうことは実際のところも多いかと思います。しかしながら、以下を意識することで、どなたでもある程度スムーズにトラブルシューティングをしていく基礎力を身につけられるかと思います。

#### Decision Tree

* 以下の手順
  * 例えば、ある事象が発生した際に、その事象の原因となる直接的な可能性の選択肢を可能な限り列挙します。それらそれぞれの選択肢について、原因となる直接的な可能性の選択肢を広げていくといった形の作業を繰り返していきます。
  * その過程で集めた情報を総合的に判断して、可能性の無いものは枝刈りをしていきます。
  * 枝刈りを繰り返していき、可能性のある選択肢を減らしていき、可能性のある選択肢は深堀りすることを繰り返していきます。
  * 最終的に選択肢が1つになった場合にたどり着いたところが根本的な原因
* 例えば、ある事象が発生した際に、その事象を直接引き起こる可能性のあるイベントがいくつかあった際にそれらをA,B,C,Dとします。さらにそれぞれのイベントを直接引き起こる可能性のあるイベントを列挙するといったことを繰り返していきます。例えば、イベントAを引き起こしうるイベントはA1,A2,A3といった具合です。
  *   イメージ

      ```
      - Issue
          - Event A
              - Event A1
                  - Event A1-1
                      - Event A1-1-1 ○
                          - ....
                  - Evente A1-2 ×
              - Event A2
                  - Event A2-1 ×
              - Event A3 ×
          - Event B
              - Event B1
                  - Event B1-1
              - Event B2 ×
              - Event B3 ×
              - Event B4 ×
          - Event C ×
          - Event D
              - Event D1 ×
          - Event E
              - Event E1 ×
              - Event E2 ×
      ```
  * 列挙しておき、例えば、メトリクスをみてリソース全体の概要を掴みつつ、事象を直接引き起こす可能性のあるイベントとして列挙していたもので、可能性がないものについては削除していきます。例えば、イベントCがこの時点でない場合にはここで枝刈りを行い、他の可能性がある選択肢について可能性がないか等の観点で絞り込みを行っていきます。
  * ある選択肢の可能性を削除するには、根拠が足りない場合は、その選択肢は一旦Pendingにしておき、他の選択肢の可能性を消しておき、Pending状態の選択肢を判断しないと次に進めない段階になってはじめて、深堀りしておくことも一つの手です。
    * すべての情報が揃った状態だと、原因の切り分けを効率的に行うことができます。ただし、情報の取得に時間を要する可能性があります。一方で、一部の情報だけでトラブルシューティングを進めると、確実に原因切り分けできるところが少ないため、複数の可能性を消すことができないまま調査を進めていかないといけない可能性もあります。ただし、"運が良ければ"、最低限の情報取得で調査が完了する可能性もあります。
    * 必要なログ情報等を全て揃えるのは、それなりに大変な作業です。特に大事な情報から取得していき、取得していない情報によって切り分けができない原因についてはPendingしておくといった要領でいくのも場合によってはよいでしょう。
* トラブルシューティングになれていると、上記の流れを無意識に行われていたり、不要に可能性を列挙せず、ある程度あたりをつけて絞り込んでいくこともできていることがありますが、この考え方が頭にあることで、多くの人でも論理的に、右往左往することも少なくスムーズに原因を絞込んでいけるでしょう。
* 選択肢を列挙できるようにしておくためには、知識量や関連技術や類似事例を如何に多く見てきているかで、効率的に処理できるかに影響するので、日頃のインプットや経験値は一つ一つものにしていくことが大事です。
  * 調査が必要な選択肢を最初から最低限に絞り込めることが効率的なトラブルシューティングに繋がりますが、その判断をするためには知識量や経験はやはり大事です。逆に言うと、知識量や経験が不十分だと、不要な調査が発生し、右に行ったり左に行ったりしていく結果、非効率なトラブルシューティングに繋がります。
    * 選択肢が十分に列挙できていないと、再現検証しても間違った方向に考えが進んでしまい、調査で後戻りが発生する可能性も出てきます。
    * 特にエッジケースでは往々にして、あとから選択肢を一部列挙し逃していることに気づくこともあります。そのときはトラブルシューティングの効率面で改善の余地はあるものの、改めてその時点から調査を進めていけば問題ないでしょう。
* あるイベントに因果関係があるか分からず可能性のある選択肢として、挙げにくい時は、適宜仮説の正当性確認のために検証を行います。
  * 対象の技術の知識があることでスムーズに選択肢を多く挙げていくことができ、効率的なトラブルシューティングに繋げられますが、ある程度の知識があっても断定できない場合、もしくは知識がない場合には自分でその状況を再現して確かめることも可能です。
  * 再現検証は時間がかかるものの、列挙している選択肢の確実性や事実確認の正確性を高めます。ただし、知識が不十分だと不要に検証を行ったり、間違った知識が含まれた前提のまま検証を進めても誤った結論に導くことにも繋がります。そもそも知識不足だと試行錯誤が多かったり、検索エンジンで検索の要領などを得るのが難しく時間がかかることもあるかと思います。そのため、やはりそういった観点でも知識のインプットは大事です。
    * ある程度選択肢を絞り込んでから、最小限に検証を行うことが効率的なハンドリングに繋がります。ただし、場合によっては最初から検証に持ち込んで再現性を確認していくことが大事な場合もあります。

#### 基本的にトップダウン

* 例えば、ロードバランサー、バックエンド、データベースなどの構成を想定してみます。
  * 例とは異なるアーキテクチャであっても、基本的に考え方は同様です。
  *   被疑箇所は大きく以下にわけられます。すなわち、関連する個々のリソース、およびその間のネットワーク等、一つ一つが原因の可能性になり得ます。

      ```
      1. クライアント
          2. クライアント-ロードバランサー間のネットワーク
      3. ロードバランサー
          4. ロードバランサー-バックエンド間のネットワーク
      5. バックエンド
          6. バックエンド-データベース間のネットワーク
      7. データベース
      ```
  * 提供しているサービスにユーザー視点で異常が見られ調査をするときを考えてみましょう。サービス全体をみたときにロードバランサーが最初の受け口となる場合には、ロードバランサーのメトリクスの概要の把握からはじめていき、必要に応じてバックエンド、データベースのメトリクスも見ていきます。
    * 被疑箇所を徐々に絞り込んでいく
    * 上記のDecision Treeを意識してメトリクス全体を眺めて、ある程度可能性を絞り込んでおくと、後々の調査箇所を少なくしておくことができる
      * Decistion Treeにおいて調査方向を絞り込んだ上で、バックエンドの調査やデータベース等の調査に移っていく
      * あるメトリクスが異常なのがたまたま目について、これが悪いと決めつけてはいけません。そのため、メトリクス全体を眺めていき、起こっている事象の概要をまずは把握することが大事です。
      * メトリクス全体を眺めていくにしても、どのメトリクスを特に重視しておくかなどを抑えておくと効率的なトラブルシューティングが可能ですが、これは知識量や経験、ネットや本等のノウハウ量、慣れなどの要素に依存するかと思います。
      * 確認例
        * ロードバランサーなど上流からの調査
          * メトリクスの確認
          * アクセスログの分析
            * アクセスログの分析を行い、ステータスコードごとの分析や応答時間の大きいものから整理するなどして全体の概要を掴むことも手段の一つです。
            * 特定のリクエストのみであると言った場合には、そのリクエストのレコードの分析や適宜前後のレコードも見比べます。
            * シェルスクリプトやELBのアクセスログやCloudTrailの履歴等であればAthena等もログ分析の手段として活用可能です。
        * バックエンドの調査
          * メトリクスとしては、CPUが高くないか、ディスクI/Oに問題がないか、ネットワークのスループットやppsに問題がないか、メモリー状況やスワップの具合などを確認。AWSであればクレジット、インスタンスやシステムのステータスチェックなども確認
          * アクセスログやエラーログ、設定ファイルなどの確認
        * ロードバランサーとバックエンド間のネットワークなど、コンポーネント間の状況確認
          * インターネット接続を確認
            * パケットがどのように処理されていくのかイメージしながら、順をおってどの部分で問題が発生しているのか、確認していく必要があります。
              * IPレイヤー、TCPレイヤー、アプリケーションレイヤーなどのようにレイヤーを掘り下げていって原因となるものがないかの確認
                * 例
                  * IPレイヤーでは`ping`
                    * ただし、`ping`で使用するICMP自体がファイアウォール等でブロックされていないことを確認の上、実施してください。
                  * TCPレイヤーでは
                    * ポートが空いているか `telnet` / `nc` / `nmap`
                    * ポートがリッスンしているか `ss` / `netstat`
                  * アプリケーションレイヤーでは
                    * ファイアウォール
                      * ルールの確認(`firewalld` / `iptables`)
                      * AWSであれば、セキュリティグループやネットワークACLも確認
                * `traceroute` / `tcptraceroute`および`mtr`で経路状況の確認
                  * ただし、トレースの結果の確認には注意事項があります。
                    * インターネット上のデバイスでは、ICMPベースのリクエストベースに対する応答の優先度が低く設定されていることが多いです。そのため、必ずしもこの結果により、実際のリクエスト処理が遅くなっていることを意味しません。適宜、`traceroute`であれば`-T`オプションなどTCPベースのトレースを実行するのも手段です。
                    * 経路は逐一変わり得ます。複数回の実行結果を取得してそれらを総合的に判断することも大事です。
                    * 双方向から実行することが有効なこともあります。
                    * tracerouteでは、TTLを減算していくことで、ターゲットへの到達を確認します。ターゲット到達の際、TTLが0となり、このときに実行されるCPUの処理がレイテンシーの支配要因になる可能性もあります。この場合、得られた結果は情報としては参考にしずらく、実行結果のレイテンシーが必ずしも、コンポーネント間のネットワークのレイテンシーによる影響を意味するわけではない点については注意が必要です。あくまで複数回取得して傾向を掴むことや正常時と比較しないと、誤った結論を導く可能性があります。
              * DNSレベルで到達性の確認
          * OS内
            * インターフェイスの状況確認（`ip addr show eth0` / `ifconfig eth0`）
              * インターフェイスが上がっているか
              * TX/RXキュー、MTU
            * ルーティングの設定および状況
              * ホストのデフォルトゲートウェイの設定(`route -n`)およびデフォルトゲートウェイへの疎通性
              * AWSであれば、ルーティングテーブルも確認
            * カーネルレベルのネットワークスタック
    * ユーザー視点での異常をきっかけに調査するのではなく、アラートを各種メトリクス等に対して設定しておき、こちらをきっかけに原因調査をする場合もあるかと思います。その場合は、トップダウンのアプローチであっても、ある程度下の方まで進んだところから調査をするので十分な場合もあります。
  * クライアントやバックエンドを被疑箇所とする場合であっても、複数あるクライアントやバックエンドの中で、特定のクライアントのみかクライアント全体か、特定のバックエンドのみかバックエンド全体かなどのように影響範囲を考えることが大事です。
    * 例えば、特定のリソースのみであれば、そのリソースを対象に調査することが大事ですが、リソース全体であれば前段のネットワークやリソースが原因の可能性が考えられます。
    * 事象発生頻度が少なく特定リソースのみの場合は、たまたまそのリソースのみで事象が発生している可能性があるので、サンプルが少ない場合に容易な判断は避けたほうが良いでしょう。
* 問題箇所がはっきりしている場合には、一部調査をスキップすることができる場合もあるでしょう。ただし、ある箇所で問題が発生していても根本原因はその箇所ではなく、上流の箇所である可能性は留意しておくべきでしょう。その場合、その箇所以降下の部分で全体的にメトリクスに問題が出ている可能性があります。

#### ダメな例

* 調子が悪いから、とりあえず再起動しよう
  * 再起動せざるを得ない時はあり、戦略的に実施する分には問題ありません。
* ページ開くの遅いから、とりあえずマシンのスペックあげてみよう
  * 最終的に同じ結論になる可能性はありますが、まずは原因分析をするところから始めないと的はずれな対応を行うことになりかねません。
  * クラウドを活用している場合には、むやみにパラメータチューニング等にこだわり秘伝の状態を作り出していかずに、スケールアップが推奨される場面はあります。内部を変更しすぎて起動できないなどの安定性の問題が出るぐらいであれば、ハードウェア等の物理的な制約から開放され、バックアップやリカバリが容易なクラウドの特性を活かした対応が良いでしょう。
* 通信でたまにエラーがでるから、バックエンドでパケットキャプチャをまずはとってみたら、なんか変な通信のやり取りがある気がする！
  * 特に低レイヤーな問題であるような場合には、その分野の知識に長けていても、パケットキャプチャで起こっている事象を把握できるはできるでしょう。では具体的になぜそういった事象が起こっているのか考えるときに、推測の域を超えられないことがあります。まずは大枠から見ていき、ロジカルに整理していくことが、パケットキャプチャ内で確認できる起こっている事象をよりクリアに理解することに繋がります。

### 取得した情報の分析

情報を取得したら、それらの情報を元に分析を進めていきます。ここでは、メトリクスやコマンドの取得情報、アクセスログの観点で簡単に意識しておくべき点を説明します。

#### メトリクス分析

* 時系列に基づいた整理
  * 特徴のあるメトリクスをいくつかみつけていき、その変化の発生した時刻を基準に時系列に整理していくことが大事です。
    * 特に複雑な事象の場合には、1分などの最小単位で特徴のあるメトリクスを順に整理していくことは大事です。
    * 整理された時系列から、可能性のあるメトリクス間の因果関係を整理していき、先程のDecision Treeの判断材料に繋げていきます。
* 頭打ちのような形状のメトリクス
  * このようなメトリクスがみられる場合にはどこかしらの値が制限に触れている可能性があります。たまたまそのようなメトリクスになっている可能性もありますが、頭打ちになったメトリクスをより詳しく計算してみることで制限に触れているかを確認することも場合によっては必要です。
    * 例
      * リソースの枯渇
        * 例: CPUやメモリー、ディスクのIOPSやネットワーク(帯域やpps、接続数)、その他（Ephemeral Port、ファイルディスクリプタなど)の制限
      * 設定やアプリケーションの性質による制限
        * 例: 古いバージョンのRedisでシングルスレッド処理によって2vCPUのマシンでCPUが50%。マシン全体のvCPUに対してスレッド数の設定による制限等
      * ロック機能による制限
        * 例: vCPUが増えても100万req/s近くで頭打ち
  * 頭打ちになっているからといって対象のリソースのキャパシティの問題だとすぐに決めつけるのは避けましょう。これまで書いてきたこととも重複しますが、サーバーのメトリクスを見ている場合は、サーバーだけではなく、クライアント側やクライアントとサーバー間などのリソースの可能性も忘れないで確認しておきましょう。

#### コマンドの取得結果の分析

* あるコマンドの取得結果を分析する場合に、その取得結果のみで十分な場合もありますが、定期的に取得しておき、その結果を比較していくことで起こっている事象がみえてくるときがあります。
  * 例えば、MySQLで`SHOW EINGINE INNODB STATUS`コマンドや`SHOW FULL PROCESSLIST`コマンドなどを30秒おきに取得して、時間経過ごとの整理をしていく。

#### アクセスログ分析

* 問題発生時のレコードや前後の状況を確認していきます。アクセスログから特定時間の傾向を調べる必要がある場合で、ログの量が多いと目で一つ一つを追っていくことは困難です。そういった場合には、シェルスクリプトやスクリプト言語、Athenaなどのサービスを活用することで、効率的にログ分析を進めていくことができます。
* Ref. [コピペで使えるELBのアクセスログ解析による事象分析 (ShellScript, Athena)](https://hayashier.com/article/elb-accesslog-analysis)

### 注意点

調査を進めるにあたって、いくつか注意点や留意点も説明します。これらを見落とすことで誤った結論に行き着いたり、調査効率が著しく落ちる可能性があるので、意識しておくと良いでしょう。

#### 正常時と異常時の比較

* 問題発生時の状況だけをみてもどこに問題があるか判斷しにくいときがあります。その場合、正常時の状況と比較することで、異常時はどこに問題が手がかりがつかめやすくなります。
* 複雑なアプリケーションで正常時のログも理解しにくいときは、関連技術でプレーンな状態を確認するためにサンプルアプリケーションを動かして動作を理解しておくのが有効な場合もあるかもしれません。

#### メトリクスの粒度

* 例えば、スパイクが発生していたことを確認する場合において、数秒のみアクセス数が非常に多いが、その他の時間はアクセス数が殆どないと言った場合に、1分粒度の値をみて、そこから秒間あたりのリクエスト数をみても、値がならされてしまい、小さく見えることで問題の可能性を見逃さないようにしておくことは頭に常においておく必要があります。
* 時間経過するにつれて、メトリクスの粒度を落として保存している場合、調査開始が事象発生から時間が経過していると、十分な粒度のメトリクスを確認できず、正確な調査ができないこともあります。また、調査から時間が経過していると、ログローテーションなどで調査に必要なログが残っていないこともあります。事象発生後、なるべくすみやかに調査をするようにしましょう。

#### ログの取得体制

* いざサービスに障害が発生していてもログの取得設定をしていないと、調査に必要なログが揃わない可能性があります。その場合は、ログの設定をして事象の再現待ちをし、その時のトラブルシューティングは諦めざるを得ない可能性があります。事前に、CDNやロードバランサー、バックエンドサーバー（Webサーバー、アプリケーションサーバー）などで必要なログ情報を取得できる設定になっているか確認しておきましょう。
  * ログを取得している場合であってもリクエストごとに必要な情報が取れる状態であるか、ログフォーマットの設定を事前に見直しておきましょう。
* ログにエラー情報がないからといって必ずしも問題がないと判断することはできません。
  * 前述のとおり、ログフォーマットで取得している情報に見落としがないか確認しておきましょう。
    * 例えば、ロードバランサーからのヘルスチェックに対して、Webサーバーからの応答は200 OKしかないとします。しかしながら、バックエンド側が高負荷などが原因で、ヘルスチェックの応答に時間がかかっている場合には、ヘルスチェックに設定したタイムアウトが原因で失敗することもあります。
    * ApacheなどのWebサーバーはデフォルトのログフォーマットではリクエストの処理時間を記録しません。そのため、先程のような例の状況ではバックエンドからのヘルスチェックの応答に一見問題がないようにも取れてしまう状況が発生します。その場合、ロードバランサー側のレイテンシーの記録などである程度原因を推測することはできても確実な裏取りのためには情報が不足する可能性があります。リクエスト処理時間を記録するために、ApacheであればLogFormatディレクティブに`%D`を追加したり、Nginxであれば`log_format`に`$request_time`, `$upstream_response_time`など必要に応じて記録されるように設定しておきましょう。
  * WebサーバーのアクセスログがHTTPレベルで記録されるものである場合、それよりレイヤーの低いTCPレイヤーなどで問題が発生しており、HTTPレイヤーの処理まで行き着いていない場合は、アクセスログにエラーは記録されません。
  * エラーログでデバッグレベルの調整し、より詳細な情報が記録されるようにしておく必要がある場合もあります。
  * あるクライアントから複数台から構成されるノードにアクセスしている際に、どのノードにアクセスしていたかのログが残っていると(ロードバランサーのアクセスログやバックエンドのWebサーバーのアクセスログ等)、問題発生時の調査が効率的になります。

#### 問題発生後はできるだけ速やかに調査をする

* 事象発生後、しばらくしてから調査を進めては、例えば、ログ取得の設定をしていも、必要なログがログローテーションなどで削除されていたり、ログの保持期間を過ぎていることも考えられます。また、メトリクスの粒度も十分に保持されておらず、正確に情報を捉えられないこともあります。事象発生後、原因調査をする必要がある場合には、なるべくすみやかに実施することで、原因特定の可能性が高くなります。

#### 因果関係の逆転

* ある事象の問題分析の際に、複数の事象が発生している場合に、片方の事象が原因でもう一方の事象が発生しているのか、それとも片方の事象はもう一方の事象が原因で発生しているのか、いずれかによって原因は全く変わってきます。
* そのため、複数の事象が発生した際は、時系列を細かい粒度で整理することや順序付けが十分となる程度にログ等の情報を集めた上で判断づけをする必要があります。
  * 例. 接続数の増加とレイテンシーの増加
    * 流入するリクエスト数が増加し、インスタンスの処理が追いつかなくなった結果、レスポンスタイムの増加
    * バックエンドや依存先のコンポーネントで競合しレスポンス時間が増加した結果、クライアントが接続を破棄してリトライし、接続数が増加

#### 同じエラー文であっても、同じ事象が起こっていると判斷してはいけない

* 異なる事象が発生していても同じエラー文が出力されることはよくあります。逆に言うと、同じエラー文であっても、過去にみた事象と同じことが起こっていると判断してはいけません。
* 例えば、MySQLで`MySQL server has gone away`のようなエラー文がクライアント側で発生した場合に、原因として、サーバがタイムアウトしてコネクションを終了している場合や、セッションを稼働しているスレッドがKILLされる場合、クライアント側のTCP/IPコネクションのタイムアウトしている場合など考えられます。これらが、`connect_timeout`, `interactive_timeout`, `wait_timeout`, `net_read_timeout`, `net_write_timeout`, `max_allowed_packet`といったパラメーター起因によることもありますし、バグ起因でクラッシュしている場合などもあります。そのため、ネットでエラー文で検索して出てきた対応をやみくもに実施しても効果が出ないことがあるでしょう。基本的な調査の考え方を身に着けておくのが、原因解決のために最も効率的な方法でしょう。
  * このエラー文については、MySQL 8.0.24以降、原因によって一部詳細化されて出力されるように改善されていますが、必ずしもこれが頼りになるとは限らず、基本的な調査の考え方が不要になることを意味しません。
  * Ref. [B.3.2.7 MySQL server has gone away](https://dev.mysql.com/doc/refman/8.0/en/gone-away.html)

#### エラー文に惑わされすぎない

* あるエラーが発生した場合に、そのエラーが根本原因ではなく、サイド効果にすぎないことがあります。特にシステムが複雑な場合に顕著になります。
  * 例えば、利用可能なディスクスペースを使い切ってしまった場合、それがイベントログで埋め尽くされていたことが原因と判斷し、ログを退避しては問題解決することになりません。イベントログで埋め尽くされていた原因がなぜか、さらに深堀りしてき、対象のプロセスで定期的にクリーンアップされなかった原因など、本当の原因を考えていく必要があります。
* 解消しようとしている問題と関係ないエラーが出力されていることもあります。もしくはエラー文が大量に吐かれていることもあり、それら全て解決することが、解消している問題の解決に意味を持たないこともあります。そもそも実際に起こっている事象とは全く異なるエラー文が出力されてしまうこともあります。問題発生時は、エラー文のみに着目するのではなく、前後のメッセージ等も追って状況を把握していくことが大事です。

#### 事象の再現待ち

* 場合によっては、トラブルシューティングを進めても原因の特定に至らないことがあるかもしれません。その場合は、事象が再現した場合に共通要素などを洗い出して、事象発生条件を明確にしていくことで、調査をすすめていくことが必要な場合もあり得ます。また、事象再発時の調査のために取得しておくべき情報を洗い出しておき、情報の取得体制を整えておくことも大事です。

#### 原因調査優先か復旧優先か

* 問題発生時に理想的には原因を特定後、修正し、再発しないようにできることが大事です。
* しかしながら、時には原因調査に時間がかかる状況もあり、サービスに大きな影響が継続していると、原因調査のために問題発生時の状況を保全できない場合もあります。その場合は、原因調査を諦めて復旧を優先する場合もあります。ただし、復旧調査を優先すると、原因調査に必要なリソースを失うこともあります。そうしますと、事後調査ができなくなり、問題が起こった原因が分からないままになってしまうため、再発することを覚悟しておかないといけません。障害が発生した場合に備えて、どの程度の時間までにどの程度復旧させる必要があるのかを想定した準備を事前にしておきましょう。例えば、個人ブログ程度であればダウンタイムが許容できることも多いかと思いますが、金融関連のシステムだとダウンタイムやデータロスはかなりシビアに考える要件が多いでしょう。
* 原因調査を優先する際には、調査に必要なログやリソースは保全しておいてください。調査に時間がかかる場合は、ログのローテーションなどで途中で削除されることがないように注意してください。また、調査に時間がかかる場合で、かつその間もサービスに影響がある場合、サービスの利用者への対応方針なども別途検討しておきましょう。
* 復旧優先対応をする際には、事前に取得しておいたバックアップから復元したり、問題箇所を切り捨てて取り替えるといった対応があります。サービスによっては復旧ツールが提供されていることもあります。
  * いざとなったときにバックアップがない、もしくは古いものしかないといったことがないように、バックアップ計画は事前にしっかりと立てておきましょう。また、バックアップを取ったことで満足せずに、いざとなったときにバックアップから正常に復元できることまで含めて確認して準備しておきましょう。

### 原因となるリソースの特定の過程/特定後

原因の切り分けにも広範囲かつ、それぞれの分野についてある程度知識を要しますが、調査の過程および原因となるリソースの特定後には、当然ながらそのリソースに関する深い技術の知識を問われる場面が多々あります。\
その技術に関する動作の仕組みやアーキテクチャを理解しておくことで、起こっている事象を演繹的に把握することに繋げられ、事象発生時の原因分析に大きく活かすことができます。

関係する技術スタックのすべての知識がある（ここでは、トラブルシューティングで原因特定をするのに十分な知識）ことに越したことはなく、動作の仕組みをイメージできることで、問題発生時の原因の切り分けもスムーズですが、現実的には難しいことも多いかもしれません。ただし、ここまでで説明したような切り分けの最低限の手段や知識さえ抑えておけば、原因箇所を絞り込み後、その技術にフォーカスして理解すれば十分なことも多いです。

原因箇所絞り込み後(および、原因箇所の切り分けの過程)に、ログ内容やスタックトレース、複数あるメトリクス等を見て、そこからどういった結論が出せるか(および、どういった可能性の選択肢を列挙できるか)は、その技術の知識が必要になります。ログ内容やスタックトレースがどういった実装で出力されているのか、ソースコードを深堀りしないといけないときもあるかもしれません。

ある動作が期待した通りにならない場合は、その技術が正常時はどういったフローで処理が行われていくかを理解し、異常時はその過程のどの部分で問題が発生しているかを考えていくことも有効です。

接続先のサーバー全てで問題がレイテンシーが大きくなるなどの問題が発生しているといった状況が発生している場合には、サーバーから共通に依存しているデータベースなどの外部要因が原因の一つとして考えられることは既に言及しました。サーバーから共通に[Redis](https://hayashier.com/article/dive-deep-redis-getting-started/)/[Memcached](https://hayashier.com/article/dive-deep-memcached-getting-started/)のようなインメモリーデータベースを利用していて、こちらを調査する場合、この記事で書いたような考え方とサービス固有の知識(ここでは、[Redis](https://hayashier.com/article/dive-deep-redis-getting-started/)、[Memcached](https://hayashier.com/article/dive-deep-memcached-getting-started/))の知識も駆使しながら調査を進めていくことになります。その場合、その技術の基本的な概念などを理解していく必要があります。サーバーから共通に、オブジェクトストレージ、サードパーティサービスのAPIにアクセスしているといった場合でも考え方は同様です。

特に原因箇所がとても複雑なアプリケーションである場合、システムの動作の仕組みを深く理解しないとハンドリングが非常に非効率になります。たとえば、いくつもの技術スタックが積み重なって成り立つ技術の場合、それらのスタックがどのように相互作用しながら動作するのかを理解する必要があります。そのためには、日頃の勉強やいざ必要となったときに事前に理解しておくといったことも必要かと思います。

※上に挙げた"原因の切り分け方法"でも、各コンポーネントの知識は少なくともある程度必要になりますが、原因箇所特定後の深堀りほどなくてもなんとかなるときは多々あります。

各種コンポーネントがそれぞれのログを吐き出したときに、どこからどのようにログを見ていくか、集めた情報からどのように状況を整理するかを考える際に大変重要です。\
エラー文がはっきりと出力されるような場合(権限不足などの設定ミスや外部サービスによるエラーなど)には、アーキテクチャの深い理解がなくてもなんとかなるときもあります。しかし、はっきりとでないことや問題の原因とは全然無関係なエラーが(ときには大量に)出ること、もしくはそもそも意図せず実際に起こっている事象とは根本的に全く異なるエラー文として出ることなどは多々あります。その場合、扱っている技術のアーキテクチャや原理などを頭においた上で、ログと比較していきながら、状況を把握していきます。

また、どのログから確認するべきかの判断のためにも重要です。アーキテクチャを理解していないことで、不要にたくさんあるログを確認して、調査が非効率になることもあります。

その際、"注意点"で挙げたようなことも意識しながら、確認作業を進めていくと、問題の原因となる箇所が浮き彫りになってくるかもあるでしょう。

問題が発生しているリソースの特定前後でも、マクロとミクロな目線の違いはあるものの、調査の進め方の考え方は基本的に同様です。

### 自身の力で特定しきれない時

ここまでトラブルシューティング方法の考え方について説明してきました。それぞれの詳細について、深堀りしていくとどこまででもボリュームが大きくなるので、ここではあくまで全体の考え方の概要レベルの紹介にとどめ、適宜、イメージを持っていただくために、具体例や注意点などの説明を少しだけ追加しました。実際にはここで述べた抽象的な概念を元に、扱う技術に具体化して考えていく形になります。

ときには、自身の力で特定しきれない場合もあるかもしれません。その場合、有識者に相談したり、サービス提供元のサポートへ問い合わせる必要が出てくる場合もあります。\
ただし、素早く的確な回答を得るためには質問をする側、質問をされる側の双方にスキルが必要です。

なんで質問する側に質問のスキルを要求されるんだと、不満に思う人もいるかもしれません。いちいち質問するのに手間がかかるのは嫌だし、できる人であればいろいろ汲み取って答えられるであろうとも思う人もいるかもしれません。\
しかし、これは相手のためであると同時に、自分のためでもあります。

例えば、何か問題が発生したときに、Webサイトに繋げませんと伝えられた場合、伝えられた側は具体的に何が起こっているかの状況を把握することができません。その結果、質問をする側は、期待した結果を得ることができません。質問を受ける側は的確な答えが出せるように適宜ヒアリングを行い、寄り添うこともあるかと思いますが、それでも、質問をする側は期待した結果を得られないこともあります。質問をした相手やサポートに対して失望したり、不満を感じる人もいるかと思います。このままではいつまで経っても状況は改善しませんし、双方にとっても得がありません。これでは勿体ありません。

質問をして期待する結果を得るためには、質問する側が、状況を正確に伝える必要があります。正確に自分が直面している問題を伝えることで、より期待に沿った回答をすることに繋がります。ただし、これには質問をする側のスキルを求められてしまう側面もあります。

例えば、問題解決をする際には、この記事に書かれているような観点が大事であることを言及しました。すなわち、質問をする側もこれらの情報を提供することで、質問を受ける側も状況が把握しやすくなります(最低限、記事の前半で述べた基本情報の内容ぐらいはあると良いかもしれません)。Webサイトに繋げないといった曖昧で抽象的な表現ではなく、確認したエラー文をテキストとして共有する(スクリーンショットでは検索などの際に手間になりますので、質問を受ける側の気持ちも配慮しておけると良いでしょう。文字でうまく表現するのが難しい場合にスクリーンショットを使う分には効果的だと思います)など具体的に状況を共有することが重要です。

また、質問をしようとしている不明点を解消することが、自分がそもそも解決したい問題に対して意味がないこともあり得ます(Ref. [XyProblem](http://mywiki.wooledge.org/XyProblem))。原因調査を推測しながら調査している場合に前提条件や根拠とした事実が間違えている場合などにこういったことが起こりえますし、かなりそういった事が多く起こっているのを見かけます。質問の際は、質問に至った背景を合わせて説明することで、質問をする側の状況を質問を受ける側が正確に理解し、より期待した回答をすることが可能になります。

漠然とした質問だと、質問を受ける側は該当するドキュメントを読んでない可能性を質問を受けた側が考えることもあります。知っているドキュメントをポイントされたり、一般論のみの回答で、質問をする側は「そんなの知ってる内容だ！」となりかねません。質問をするときは、確認したドキュメントの内容や自身で調査された内容、ドキュメントを読んだ上で、ご自身の理解とドキュメントの記載内容の差分等を事前に詳細に説明することで、質問を受ける側は、質問する側が本当に何を困っているのかより詳細に把握することが可能になります。

これらの情報を整理することは、質問する側の負担になります。しかしながら、このようにすることで、結果的に原因特定まで早く至ることになり、ご自身の負担軽減に繋がります。質問をする側が、必要な情報を揃えられない場合、質問する側にエスパーすることを強いることもあります。これには的確に回答するには限界があり、推測レベルの結論しか引き出せないこともあります。質問をする側はシンプルな内容だからすぐに答えられる内容であろうと思っていても、そうではないことが往々にしてあります。

サポートに問い合わせた際にたくさんのログ情報の依頼があり、大変に感じたことがある方もいらっしゃるのではないでしょうか。一部の情報では調査に時間がかかったり、最終的に原因がはっきりしなかったり、推測情報が多くなる可能性があることは留意しておいた方が良いでしょう。できるだけ少ないやりとりで問題解決につなげるためには最初に情報を揃えていくことが大事です。ただし、可能性の一つの切り分けのためにログの取得やパケットキャプチャを取得したくても、現実的にはシステムの制約（例: 十分な処理能力がない場合）や組織の体制上（例: 別の組織で管理しているシステムであるため、容易に情報取得ができない）、取得が困難なことも場合によってはあるかもしれません。どうしても情報を揃えることが困難な場合、上記の問題は留意しつつ、理由を説明しながら一部の情報で調査を進められる可能性が少しでもないか相談してみるのも良いかもしれません。

当然ですが、質問を受ける側は、質問をする人の頭の中が見えるわけではありません。しかしながら、いざ問題が発生している状況に出くわすと、この事実が頭から抜け落ちてしまうことも中にはあります。こうなってしまうと、お互いに不幸になる可能性がある点については念頭に置いておいて良いでしょう。

まとめると、質問をしても期待した回答が返ってこない時には、質問の仕方を見直すことも大事です。面倒であっても、最低限エラー文を含め、リソース情報の詳細や質問にいたった背景、自身での調査内容、期待する結果と実際の結果等の詳細を添えて質問をすることで、スムーズにより期待する回答を得ることに繋がりますので、おすすめします。

以下の記事について、ここに書かれていることは、いろんなサポートへ問い合わせるときだけではなく、普段同じ職場内での同僚に対して質問をする場合にも大いに役に立つかと思いますので、参照してみてください。

* [技術的なお問い合わせに関するガイドライン](https://aws.amazon.com/jp/premiumsupport/tech-support-guidelines/)
* [How To Ask Questions The Smart Way](http://www.catb.org/~esr/faqs/smart-questions.html) (日本語訳: [賢い質問のしかた](https://www.ranvis.com/articles/smart-questions.ja.html))

質問をする側が必要なアクションを取った上で、それでも期待した結果にならないことも場合によってはあるかもしれません。その期待している内容が、サポートのサービスの提供外の内容(例. マネージドサービスで非公開の内部アーキテクチャなどの内部情報を問い詰める)や、確認した動作が仕様かを明確にすること(すべての動作が仕様として定義されているとは限らず、検証等をして確認された内容が現状の挙動としか言えないこともあります)を期待しても、やりとりが良い方向に向かないでしょう。

適切ではない方向で問い詰められている場合には、技術の正しい扱い方などのように適切な方向に誘導されることもあるかと思います。これは、論点を反らしたいわけではありません。前述の通り、背景情報を事前にお伝えしつつ、方向性の適切さも念頭においておくとよいかもしれません。

Yes/Noのように明確に結論がほしい方もいるかと思います。質問の前提がすべてクリアでなかった場合や仮定している前提の根拠に誤りが含まれている場合には、順を追って説明したり様々なパターンを考慮して説明する必要がある場合があり、このとき説明は長くなるかもしれません。なるべく端的な説明を求められる場合には、リソース情報の詳細や、質問者が置かれている前提や背景を正確、かつなるべく多く情報を提示すると良いかと思います(これは難しいことかと思います)。

サービスの範囲内である場合には、適切にフィードバックをすることで改善される可能性もあります。ただ不満を言うのみでは状況は改善しませんので検討してみると良いでしょう。サービスによってはフィードバックはかなり真摯に受け取ってもらえることもあるかと思います。フィードバックする際には、その内容が感情的である場合には内容が支離滅裂になりかねません。質問をする側の問題と捉えられかねませんので、フィードバック内容が妥当である理由を詳細に記載することで、より効果が大きくなるかもしれません。フィードバックの効果はサービスや提供元による点については留意しておいてください。

本番環境のサービスに影響が発生している場合には、気持ちが高ぶって焦ったり、温度感が高くなってしまうこともあるかと思います。原因分析の際に、そういった気持ちは、原因特定の上で逆効果になりかねませんので、落ち着いて対応することが大事です。そういった場合でも、質問をする際は、冷静に必要な情報を提供することが、早く問題を解決することに繋がるでしょう。
