AWS : 時間が経ってもCloudWatch Alarmがアラーム状態から戻らない理由

# Zennに移行しました
https://zenn.dev/wakaka23/articles/050de08a454031

# はじめに
最近CloudWatch Alarmの検証をしていたのですが、CloudWatch Alarmがアラーム状態になった後、次の評価期間が来てもOK状態に回復しないことに気づきました。この理由について色々調べたので備忘録として残しておきます。誰かの助けになれば幸いです。

# 状況整理
構成図は以下に示す通りです。CloudTrailで取得したAPIコールログをCloudWatch Logsに格納した後に、メトリクスフィルタで特定のログを拾ってアラームを発砲するというようなシンプルな構成です。詳細な設定は以下の記事にまとめていますので、そちらをご確認ください。

https://qiita.com/Ak_ki/items/1593f6bf2657c2078d84

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746031/334e38e6-ffbb-2e96-d836-400e73b12fe2.png)

複数のアラームを設定したのですが、説明の都合上、以下に示すようなNACLの作成などをトリガーとして発砲するアラームに絞って話を進めていきます。
期間を1分、アラームを実行するデータポイントを1/1と設定しているため、評価期間の1分の間にNACL作成などのAPIコールが一回でも呼び出されるとアラーム状態に遷移します。NACL作成時以外の時には、データポイントが欠落するような設計となっております。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746031/d543c649-8fb9-6a9b-41d9-6cfc2415137b.png)

実際にNACLを作成してみると、想定通りOK状態からアラーム状態に遷移しました（下画像では6:15と6:28の2回検証しております）。今回は「欠落データを適正として処理」する設定としているため、次の評価期間である1分後には欠落データが適正として認識され、OK状態に戻ると想定していました。しかし、実際に履歴を見てみると、アラーム状態からOK状態に回復したのは6分後のことでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746031/3fd0468a-297b-ae5f-c62e-99e66db2f202.png)

# 結論
この理由を一言で言えば**CloudWatchは「評価期間」ではなく「評価範囲」に基づいてアラームの状態遷移を判断しているから**です。以下の公式レファレンスに説明がありました。少し噛み砕いて説明します。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-evaluating-missing-data

CloudWatchにはアラームの作成時に設定する評価期間（Evaluation Period）という概念のほかに、評価範囲（Evaluation Range）という概念が存在します。公式レファレンスでは "The time frame of the data points that it attempts to retrieve is the evaluation range." と定義されています。少しイメージしにくいですが「CloudWatchがアラーム状態の遷移を評価する際の時間枠」と自分は解釈しています。**CloudWatchは評価範囲という時間枠の間にあるデータポイントを基にアラーム状態かOK状態かを決めている**ということですね。（この「時間枠」ですが、正確な値は決まっておらず、評価期間の長さやメトリクスの種類に応じて変化するようです）

じゃあこの評価範囲内のデータポイントがどういう状態ならアラーム状態に遷移するのかという疑問が湧いてくるのが自然だと思います。これは状況に応じて以下の3通りに分かれます。
1. 評価範囲のデータポイントが欠落していない場合
→CloudWatchは収集された最新のデータポイントに基づいて状態を評価する
2. 評価範囲のデータポイントの一部が欠落しているが、「評価範囲において正常に取得されたデータポイントの合計数」≧「アラームの評価期間」である場合
→ CloudWatchは正常に取得された最新のデータポイントに基づいて状態を評価する
3. 評価範囲のデータポイントの一部が欠落しており、「取得されたデータポイントの合計数」 < 「アラームの評価期間」である場合
→ CloudWatchは欠落データを「欠落データの処理」で指定したように認識して状態を評価する

具体例を見ていきましょう。以下に6:27-6:34のアラームの状態遷移を図示しました。緑の部分が評価範囲、★がchanges-in-NACLの発生を表しています。検証の結果、今回の評価範囲は6分間（6データポイント分）と予想されたため、そのように図では表しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746031/8a46a67f-4f79-8920-6c7f-f664d0d32848.png)

まず、6:27（一段目）はまだchanges-in-NACLが発生しておらず、評価範囲の中のデータポイントは０個です。つまり全てのデータポイントが欠落しています。ここでは「取得されたデータポイントの合計数(0)」 < 「アラームの評価期間(1)」となるので3番目のパターンが該当します。このアラームでは「欠落データを適正として処理する」ため、OK状態と評価されます。

続いて、6:28（二段目）になるとchanges-in-NACLが発生し、評価範囲の中にアラームをトリガーしたデータポイントが存在することとなります。ここでは「評価範囲において正常に取得されたデータポイントの合計数（1）」≧「アラームの評価期間（1）」となるため２番目のパターンが該当します。正常に取得された最新のデータポイントは6:28のものなので、アラーム状態と評価されます。

6:29-6:33まで（三段目）は常に評価範囲の中にアラームをトリガーしたデータポイントが存在するため、6:28の場合と同様に２番目のパターンに該当し、アラーム状態と評価されます。

最後に、6:34（四段目）になると評価範囲内のデータポイントは再び0個になります。よって6:27の場合と同様にして、「取得されたデータポイントの合計数(0)」 < 「アラームの評価期間(1)」となるので3番目のパターンが該当し、OK状態と評価されます。ここでようやく6:28にアラーム状態になったアラームがOK状態に戻ることとなります。

参考ですが、仮に6:29に閾値未満の（適正な）データポイントが出力されている場合には、正常に取得された最新のデータポイントは6:29のデータポイントとなるため、OK状態に遷移することとなります。メトリクスフィルタのデフォルト値を0のように設定しておけば、フィルタに一致しないログの場合に閾値以下のデータポイントを出力させ、次の評価期間でOK状態に遷移させることも可能です。

# 終わりに
CloudWatchは簡単そうで本当に奥が深いサービスですね...
使いこなすためにはまだまだ修行が必要みたいです。