【AWS】障害時の調査事項まとめ ～ELB・ECS・RDS～

# はじめに
現在はAWSで構築されたシステムの運用保守業務に携わっており、その一環として障害調査を行うことが多々あります。
少しは経験値が上がったため、障害が発生した際に初動で確認する事項をまとめてみました。
インフラ基盤観点で障害調査を行うさいの参考になれば幸いです。

# 前提条件
当システムの構成は以下となっているため、それに即した調査項目となっています。
* ALB/NLB・ECS・RDSを利用している
* ECSはEC2上で実行している（Fargateでは利用していない）
* ECSクラスター（以下クラスター）の自動スケーリング設定をしている
* ECS サービス（以下サービス）の自動スケーリング設定をしている
* RDSはAuroraを利用している

また、障害は**予期せぬコンテナの停止**を想定しています。


# NLB/ALBの調査事項
### メトリクス
初めにロードバランサーのメトリクスからターゲットの状態を確認します。

扱っているシステムでは、HealthyHostCountメトリクスを利用してターゲットであるコンテナの死活監視をしています。
HealthyHostCountの閾値を下回ることによりアラートがなるので、まずは下記メトリクスを確認して異常なコンテナがあるか確認をします。

|メトリクス名  |統計値  |単位  |詳細  |確認観点  |
|:-:|:-:|:-:|:-:|:-:|
|HealthyHostCount  |最小  |ターゲットグループ  |正常とみなされる<br>（ヘルスチェックに成功した）<br>ターゲットの数。  |正常なコンテナ数  |
|UnHealthyHostCount  |最大  |ターゲットグループ  |異常とみなされる<br>（ヘルスチェックに失敗した）<br>ターゲットの数。  |異常なコンテナがあるか  |

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html



### 確認観点
基本的にヘルスチェックに失敗するとHealthyHostCountメトリクスが下がり、UnHealthyHostCountメトリクスが1以上になります。そして異常なコンテナは停止し、新しいコンテナが起動します。
しかし、ロードバランサーの挙動によりどちらかのメトリクスのみに変化が見られる場合や、必ずしもコンテナの入れ替わりが発生しない場合もあるので注意です。
場合分けを行い、わかる範囲で事象が発生する可能性についても記載しています。

|項目  |事象  |事象発生の可能性  |
|:-:|:-:|:-:|
|1  |HealthyHostCountの減少<br>かつ<br>UnHealthyHostCountの上昇  |ほぼ確でコンテナに異常が発生<br>かつ<br>コンテナの入れ替わりも発生している  |-  |
|2  |HealthyHostCount減少のみ  |AWSの誤検知<br>または<br>B/Gデプロイ<br>（ターゲットの切り替えのさいに一時的に0になる）<br>または<br>EC2のリソース不足※  |
|3  |UnHealthyHostCount上昇のみ  |AWSの誤検知<br>または<br>ロードバランサーの入れ替え（主にALB）<br>または<br>ロードバランサーのスケーリング  |

2.3のB/Gデプロイ以外の要因はユーザ側ではわからないので、**AWSに問い合わせ**を実施します。

:::note 
**アラームの設定について**
アラーム設定はHealthyHostCountの個数の閾値を設定して、その閾値を下回った場合にしています。
その場合だとB/Gデプロイ時に条件に引っかかってしまうため、以前**HealthyHostCountとUnHealthyHostCountをand条件**でアラートとして設定する検討をしました。しかしその際は"HealthyHostCount減少のみ"に検知できる**EC2のリソース不足**によるコンテナの起動失敗を検知できなくなるため断念しました。
この場合**EC2のリソース不足**とは、土台となるEC2にコンテナが新規に起動するためのCPUやメモリが不足した状態をさします。
:::




# ECSの調査事項
次はECS関連の調査です。
**サービス単位**と**クラスター単位**でそれぞれ調査を行います。

## サービス単位の調査

### メトリクス
サービス単位で確認するメトリクスは以下です。

|メトリクス名  |統計値  |詳細  |確認観点  |
|:-:|:-:|:-:|:-:|
|RunningTaskCount  |最大  |RUNNING 状態にある<br>タスクの数  |タスクの増減  |
|CpuUtilized※  |最大  |リソースのタスクにより<br>使用されている<br>CPUユニット数  |負荷状況  |
|MemoryUtilized※  |最大  |リソースのタスクにより<br>使用されているメモリ  |負荷状況  |
|CPUUtilization※  |最大  |サービスで使用されている<br>CPUの割合  |負荷状況  |
|MemoryUtilization※  |最大  |サービスで使用されている<br>メモリの割合  |負荷状況  |

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cloudwatch-metrics.html

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Container-Insights-metrics-ECS.html


#### タスク定義による予約について
タスク定義で事前に利用するタスクのCPUやメモリの予約の設定ができます。
EC2からあらかじめ最低限の利用分としてリソースを確保してくれるイメージです。
設定分しかCPUやメモリが使えないわけではなく、土台となるEC2に余力があれば予約以上のCPUやメモリを使うことができます
また設定しなければコンテナが利用できないわけではありません。

ですが、非常に大事な値なので**適切に設定する方がよい**です。

理由はいくつかあるのですが、今回の内容に即したものを紹介します。


#### 予約をもとにしているメトリクスが参照できなくなる

上記に記載した CpuUtilized・MemoryUtilized メトリクス に関しては、それぞれCPU・メモリ予約をしていないと**メトリクスを収集することができません**。

また、CPUUtilization・MemoryUtilization メトリクス に関しては、**サービスに属するタスクによって使用されている CPU ユニットの合計を、サービスに属するタスク用に予約されている CPU ユニットの合計で割った数**で計算されているため、予約値によっては出鱈目な値となってしまいます。

メトリクス以外にも予約の値を参照して取得している数値が多数あるので、タスク定義の予約は適切に設定するのがよいです。


:::note info
**CPUUtilization・MemoryUtilizationについて**
CPUUtilization・MemoryUtilization メトリクスは、スパイクが発生すると数値100％を超えることが多々あります。

しかし、"100％を超える=コンテナが処理落ちする"かというとそうではありません。

上記でも記載したように、メトリクスの値はタスク定義の予約値をもとに計算されており、実際はEC2に余裕があれば予約値以上のCPUやメモリを利用することができるため、100％以上の負荷でもある程度耐えることができます。
:::


### ログ
サービス単位で確認するログは以下です。
#### サービスのイベントログ

コンソールでは、[サービス] > [イベント]で確認することができ、以下情報を取集します。
* タスクの増減が発生しているか
* タスクが増減した時間
* タスクが増減した理由

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs_cwe_events.html#ecs_task_events


## クラスター単位の調査


### メトリクス
クラスター単位で確認するメトリクスは以下です。

|メトリクス名  |統計値  |詳細  |確認観点  |
|:-:|:-:|:-:|:-:|
|ContainerInstanceCount  |最大  |クラスターに<br>登録されている<br> Amazon ECS エージェント<br>を実行している<br> EC2 インスタンスの数  |オートスケールが<br>発生しているか  |
|CPUUtilization  |最大  |クラスターで<br>使用されている<br>CPUの割合  |CPU不足に<br>なっていないか  |
|MemoryUtilization  |最大  |クラスターで<br>使用されている<br>メモリの割合  |メモリ不足に<br>なっていないか  |
|CpuReserved  |最大  |クラスターで<br>タスクを実行することを<br>予約されているCPUの割合  |CPU不足に<br>なっていないか  |
|MemoryReserved  |最大  |クラスターで<br>タスクを実行することを<br>予約されているメモリの割合  |メモリ不足に<br>なっていないか  |

## Container Insights
Container Insights を有効化することで、通常提供されているメトリクスよりもさらに**詳細なコンテナに関する情報を収集すること**ができます。
追加料金はかかりますが金額以上の価値があるため**絶対に有効化した方がよい**です！
（上記で紹介しているメトリクスの中にもContainer Insightsによって収集しているものがあります）

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ContainerInsights.html

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/deploy-container-insights-ECS-cluster.html


# EC2の調査事項
次は土台となるEC2（コンテナインスタンス）の調査です。
クラスターの調査と似た部分もありますが、インスタンス単位で調査することでわかることもあり、どちらも確認が必要です。
また特定のインスタンスに異常があった場合は、AWSの基盤の問題の可能性もあります。

### メトリクス
確認するメトリクスは以下です。

|メトリクス名  |統計値  |詳細  |確認観点  |
|:-:|:-:|:-:|:-:|
|CPUUtilization  |最大  |インスタンスを実行するために<br>使用する物理 CPU 時間の割合  |CPU不足に<br>なっていないか  |
|NetworkIn  |最大/<br>最小  |ネットワークインターフェイスを通じ<br>このインスタンスによって<br>受信されたバイトの数  |負荷状況  |
|NetworkOut  |最大/<br>最小  |ネットワークインターフェイスを通じ<br>このインスタンスから<br>送信されたバイトの数  |負荷状況  |

:::note info
**CPUUtilizationの違い**
クラスターとEC2ではCPUUtilizationの計算方法が異なります。
ちょっとした違いですが、知っておくことは大事です。

* クラスター：ECSクラスター内の**タスクが使用したCPUユニットの合計**を使用
　　　　　　 (タスク外で使用されたCPUについては含まれない)
```
                            (Total CPU units used by tasks in cluster) x 100
Cluster CPU utilization =   ---------------------------------------------------------------
                            (Total CPU units registered by container instances in cluster)
```


                
* EC2：インスタンス上で実施されている**すべてのCPUユニットの合計**を使用
　　（OS等のCPUも含まれる)

:::

### ログ
以下ログを確認します。

#### AutoScalingのアクティビティ
コンソールでは、[AutoScaling] > [アクティビティ]で確認することができ、以下情報を取集します。
* インスタンスの増減が発生しているか
* インスタンスが増減した時間
* インスタンスが増減した理由

コンテナインスタンスの数はContainerInstanceCount メトリクスでもわかりますが、
詳細な状況を把握するためにAutoScalingのアクティビティまで確認した方がよいです。


#### ECSログコレクター
コンテナインスタンスのさまざまなログを一括で**1つのファイルに圧縮およびアーカイブ**できます。

ユーザ側で調査を行うときに利用するだけでなく、**AWSサポートにコンテナインスタンス関連の問い合わせを行うと、高頻度で採取を求められます**。（AWS基盤側で障害が発生していないかの調査にも利用されているっぽいです）

コンテナインスタンス上でスクリプトをダウンロードし実行することで簡単に利用ができます。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-logs-collector.html




# RDSの調査事項
最後はRDSの調査です。

### メトリクス
確認するメトリクスは以下です。
クラスター・インスタンス単位（特にライターを注視）でそれぞれ確認します。

|メトリクス名  |統計値  |詳細  |確認観点  |
|:-:|:-:|:-:|:-:|
|CPUUtilization  |最大  |CPU使用率  |CPU不足に<br>なっていないか  |
|DatabaseConnections  |合計  |データベースインスタンスへの<br>クライアントネットワーク接続の数  |上限に<br>到達して<br>いないか  |
|FreeableMemory  |最小  |使用可能な RAM の容量  |メモリ不足に<br>なっていないか  |
|ReadIOPS  |最大  |1秒あたりのディスク読み取り<br>I/O オペレーションの平均回数  |負荷状況  |
|WriteIOPS  |最大  |1秒あたりのディスク書き込み<br>I/O オペレーションの平均回数  |負荷状況  |
|ReadThroughput  |最大  |1秒あたりのディスクからの<br>平均読み取りバイト数  |負荷状況  |
|WriteThroughput  |最大  |1秒あたりのディスクへの<br>平均書き込みバイト数  |負荷状況  |


## Performance insights
データベースパフォーマンスのチューニングとモニタリングを行う機能です。

インスタンス単位で**データベースの負荷をすばやく評価する**ことが可能で、負荷を発生させているSQLステートメントとその理由を簡単に確認することができます。

無料で7日間（最大2年）のパフォーマンス履歴を保存でき、とりあえず**有効にするのがおすすめ**です。

https://aws.amazon.com/jp/rds/performance-insights/


# 最後に
いかがだったでしょうか？
今回は障害発生時に最低限確認する項目をまとめさせていただきました。
少しでも障害調査を行う助けになれば幸いです。
最後まで読んでくださりありがとうございました！