[アップデート] 複数のリソースのメトリクスに対してまとめてアラーム設定ができるAmazon CloudWatch Metrics Insightsアラームが使えるようになりました
複数のリソースのメトリクスに対してまとめてCloudWatchアラームの設定をしたいな
こんにちは、のんピ(@non____97)です。
皆さんは複数のリソースのメトリクスに対してまとめてCloudWatchアラームの設定をしたいなと思ったことはありますか? 私はあります。
CloudWatchアラームはトリガーする基準となるメトリクスを複数選択することはできません。
そのため、EC2インスタンスが大量にあるとEC2インスタンス毎にCPU使用率監視用CloudWatchアラーム、メモリ使用率監視用CloudWatchアラーム、ディスク使用率監視用CloudWatchアラーム... と「EC2インスタンスの数 × メトリクスの数」分設定・管理することになり、かなり大変です。
そんな折、Amazon CloudWatch Metrics Insightsアラームなる機能が発表されました。
CloudWatch Metrics Insightsの説明は以下記事をご覧ください。
これにより、「メモリ使用率が閾値超えているEC2インスタンスが1つでもあったら通知する」といったことができそうです。
早速試してみたので紹介します。
いきなりまとめ
- 複数のリソースのメトリクスに対してまとめてアラーム設定ができる
- 各リソースのメトリクス毎にCloudWatchアラームを設定する必要がなくなる
- CloudWatch Metrics InsightsのSQLの
WHERE
句で対象リソースを絞り込んだり、除外することも可能 - 1つのリソースでもメトリクスが閾値を超えたらアラーム状態になる
- アラーム状態を検知したら、
GROUP BY
で対象リソースを絞り込む運用になりそう
やってみた
CloudWatchアラームの作成
複数あるEC2インスタンスのいずれかのCPU使用率が30%を超過したら、SNSトピックに通知するようなCloudWatchアラームを設定します。
CloudWatchのコンソールからすべてのアラーム
-アラームの作成
をクリックします。
メトリクスの選択
をクリックします。
インスタンス別のCPU使用率の最大値を取得するようにCloudWatch Metrics Insightsでクエリを定義します。その後、実行
をして意図したグラフが表示されることを確認してメトリクスの選択
をクリックします。
こちらのクエリは以下の通りです。
SELECT MAX(CPUUtilization) FROM SCHEMA("AWS/EC2", InstanceId)
なお、GROUP BY
を付与したアラームを作成しようとすると以下のメッセージと共に怒られます。「複数のメトリクスのいずれかが閾値を超えたら」ということはできないようです。
GROUP BY ステートメントを含むメトリックスクエリではアラームを作成できません。アラームの詳細はこちらを参照ください。 To produce a single time series, you can try using one of these math functions: AVG, MIN, MAX, FIRST, LAST. Learn more about math functions.
メトリクスの選択をしたら、次に条件を設定します。今回はCPU使用率が30%以上とします。
次にアクションの設定です。アラーム状態になったら事前に作成していたSNSトピックに通知するよう設定します。
名前と説明を適当に入力して次へ
をクリックします。
作成されるCloudWatchアラームを確認してアラームの作成
をクリックします。
作成したCloudWatchアラームを確認します。状態はOK
となっていますね。
こちらのCloudWatchアラームのCloudFormationの定義は以下のようになります。
Type: AWS::CloudWatch::Alarm Properties: AlarmName: cpu-alarm AlarmDescription: |- # 説明 これは us-east-1 のいずれかのEC2インスタンスのCPU使用率が閾値を超えたときに通知するアラームです。 ActionsEnabled: true OKActions: [] AlarmActions: - arn:aws:sns:us-east-1:<AWSアカウントID>:LaunchWizardStack-TopicBFC7AF6E-QH7HCZW0RHO4 InsufficientDataActions: [] Dimensions: [] EvaluationPeriods: 1 DatapointsToAlarm: 1 Threshold: 30 ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: missing Metrics: - Id: q1 Label: "[max: ${MAX}] " ReturnData: true Expression: SELECT MAX(CPUUtilization) FROM SCHEMA("AWS/EC2", InstanceId) Period: 60
AWS CLIで作成する場合は以下の通りです。
aws cloudwatch put-metric-alarm \ --alarm-name 'cpu-alarm' \ --alarm-description '# 説明 これは us-east-1 のいずれかのEC2インスタンスのCPU使用率が閾値を超えたときに通知するアラームです。' \ --actions-enabled \ --alarm-actions 'arn:aws:sns:us-east-1:<AWSアカウントID>:LaunchWizardStack-TopicBFC7AF6E-QH7HCZW0RHO4' \ --evaluation-periods 1 \ --datapoints-to-alarm 1 \ --threshold 30 \ --comparison-operator 'GreaterThanOrEqualToThreshold' \ --treat-missing-data 'missing' \ --metrics '[{"Id":"q1","Label":"[max: ${MAX}] ","ReturnData":true,"Expression":"SELECT MAX(CPUUtilization) FROM SCHEMA(\"AWS/EC2\", InstanceId)","Period":60}]'
1台だけEC2インスタンスのCPU使用率を100%にして通知されるか確認
それではEC2インスタンスを1台だけCPU使用率を100%にしてみます。
すると状態がアラーム状態
になりました。CloudWatchアラームを1つしか設定していないのに、これは嬉しい。
アラーム状態になったため、以下メールも通知されました。メールのフォーマットがなんだか進化している気がします。
You are receiving this email because your Amazon CloudWatch Alarm "cpu-alarm" in the US East (N. Virginia) region has entered the ALARM state, because "Threshold Crossed: 1 out of the last 1 datapoints [70.43450724178736 (15/12/22 02:18:00)] was greater than or equal to the threshold (30.0) (minimum 1 datapoint for OK -> ALARM transition)." at "Thursday 15 December, 2022 02:19:16 UTC". View this alarm in the AWS Management Console: https://us-east-1.console.aws.amazon.com/cloudwatch/deeplink.js?region=us-east-1#alarmsV2:alarm/cpu-alarm Alarm Details: - Name: cpu-alarm - Description: # 説明 これは us-east-1 のいずれかのEC2インスタンスのCPU使用率が閾値を超えたときに通知するアラームです。 - State Change: OK -> ALARM - Reason for State Change: Threshold Crossed: 1 out of the last 1 datapoints [70.43450724178736 (15/12/22 02:18:00)] was greater than or equal to the threshold (30.0) (minimum 1 datapoint for OK -> ALARM transition). - Timestamp: Thursday 15 December, 2022 02:19:16 UTC - AWS Account: <AWSアカウントID> - Alarm Arn: arn:aws:cloudwatch:us-east-1:<AWSアカウントID>:alarm:cpu-alarm Threshold: - The alarm is in the ALARM state when the metric is GreaterThanOrEqualToThreshold 30.0 for at least 1 of the last 1 period(s) of 60 seconds. Monitored Metrics: - MetricExpression: SELECT MAX(CPUUtilization) FROM SCHEMA("AWS/EC2", InstanceId) - MetricLabel: [max: ${MAX}] State Change Actions: - OK: - ALARM: [arn:aws:sns:us-east-1:<AWSアカウントID>:LaunchWizardStack-TopicBFC7AF6E-QH7HCZW0RHO4] - INSUFFICIENT_DATA:
そのまましばらく待つと、状態がOK
になり、その1分後にアラーム状態
になっていました。表示されるメトリクスを見ても常に閾値は超えているので不思議です。
そのままさらに待つと、また状態がOK
になり、その1分後にアラーム状態
になっていました。不思議です。
メトリクスで表示
をクリックして、GROUP BY
にInstanceId
を指定しても、対象のEC2インスタンスのCPU使用率は常に閾値を超えているようです。
これは謎ですね。
アラーム状態中に2台目のEC2インスタンスのCPU使用率も100%にした場合通知されるか
アラーム状態中に2台目のEC2インスタンスのCPU使用率も100%にした場合に通知されるか確認してみます。
既にアラーム状態なので状態遷移は発生せず、通知は行われないとは思いますが念の為確認です。
2台目のEC2インスタンスのCPU使用率を100%にしてみます。
この時のCloudWatchアラームを確認します。
アラーム状態のままで追加のアクションも発生していないようです。
当然ですが通知メールも届いていませんでした。
一度全EC2インスタンスのCPU使用率を閾値以下にしてから再度100%にした場合
メトリクスが常に閾値を超えているのにも関わらず状態がOK
に遷移するのがどうしても解せないので、一度全EC2インスタンスのCPU使用率を閾値以下にしてから再度100%にして、状態がどのように遷移するのか確認します。
一度全EC2インスタンスのCPU使用率を閾値以下にしてから再度CPU使用率を100%にしてみました。
1時間ほど放置すると、常に閾値を超えているのにも関わらず状態がアラーム状態
からOK
へ4回遷移していました。
該当時間帯のメトリクスの最小値を確認しましたが、CPU使用率を100%にしているEC2インスタンスの最小のCPU使用率は92.15
でした。不思議です。
EBSボリュームへの書き込み操作数のCloudWatchアラームで再チャレンジ
CPU使用率のみ、このような事象が発生するのかな?と思い他のメトリクスでも試してみます。
EC2インスタンスに接続された全EBSボリュームからの完了した書き込み操作のメトリクスであるEBSWriteOps
で試します。
EBSWriteOps
の1分間の最大値が300以上になった場合にアラーム状態になるように、CloudWatchアラームを設定します。
CloudWatchアラームの設定後、以下スクリプトでEBSボリュームに大量に書き込みしてみます。
while sleep 1; do sudo dd if=/dev/urandom of=/home/ssm-user/testfile_1 bs=1K count=1048576 done
書き込みをして程なくして、状態がアラーム状態
になりました。そのまま30分程放置しましたが、状態がOK
になることはありませんでした。
各EC2インスタンスのEBSWriteOps
は以下の通りです。1台のみ閾値超えていることが分かりますね。
OK
に遷移してしまう事象が発生するのはCPU使用率(CPUUtilization
)のみなのでしょうか。謎が謎を呼びます。
2022/12/30 : 追記ここから
色々調べていると原因はCloudWatchアラームの評価タイミングにCloudWatchメトリクスのデータポイントの反映が遅れていたということが分かりました。
CloudWatchアラームの評価は、当然ですが参照可能なデータポイントを使用してアラームの状態の評価を行います。また、データポイントの反映が遅れていたとしても、そのデータポイントの反映を待たずに評価を行います。
今回の場合はCPU使用率を100%にしてEC2インスタンスの負荷が高い状態になっています。加えて、アラームを実行するデータポイントはを1/1
としています。そのため、CPU使用率の高いEC2インスタンスのデータポイントの反映がCloudWatchアラームの評価タイミングに一瞬でも遅れてしまうと、今回の事象のようにCPU使用率を高負荷にしていないEC2インスタンスのCPU使用率(CPUUtilization
)が最大値となってしまい、条件を満たしていないと判定されて一時的にOK
になってしまいます。
このようなデータポイントの反映遅延によるアラームの意図しない状態変化の回避策は、アラームを実行するデータポイントを「1/2」や「2/3」など分母と分子の数が一致しないようにすることが挙げられます。
アラームを実行するデータポイントの分母と分子の数が一致しているような定義だと、アラーム状態
になるにはデータポイントが分母の数分連続して条件を満たす必要があります。裏を返せば1データポイントでも条件を満たさなければ状態がOK
となってしまいます。いわゆるフォールスネガティブにはなりにくいですが、フォールスポジティブとなりやすい状態でもあります。
アラームを実行するデータポイントを「1/2」や「1/3」、「2/3」など分母と分子の数が一致しないようにすることで、複数のデータポイント(分母)のうち、データポイントが一定数(分子)条件を満たすときにアラーム状態
になります。逆にOK
になるには条件を満たさないようなデータポイントが一定数必要になります。
例) アラームを実行するデータポイント毎のOK
になるために必要な条件を満たさないデータポイントの数
- 「1/2」 : 2データポイントの内2データポイント
- 「1/3」 : 3データポイントの内3データポイント
- 「2/3」 : 3データポイントの内2データポイント
2022/12/30 : 追記ここまで
リソースだけ異なるCloudWatchアラームを大量に作成することがなくなりそう
複数のリソースのメトリクスに対してまとめてアラーム設定ができるAmazon CloudWatch Metrics Insightsアラームが使えるようになったアップデートを紹介しました。
これにより、リソースだけ異なるCloudWatchアラームを大量に作成することがなくなりそうです。
対象のリソースを絞り込み/除外したい場合は、CloudWatch Metrics InsightsのSQLのWHERE
句でコントロールすることができます。個人的にはIDのみではなく、タグを使って絞り込みができると嬉しいです。
運用としては、アラーム状態を検知したら、GROUP BY
で対象リソースを絞り込んで対応をするといったことになりそうです。なお、実際に検証しましたが既にアラーム状態になると他のリソースのメトリクスが閾値を超えても通知されません。そのため、アラーム状態を放置していると新規アラームに気づくことができません。アラーム状態を放置しないように運用しましょう。
この記事が誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!