CloudWatchアラーム + SNSトピックでメール飛ばす時の件名を変更したい。ということで、過去記事 AWS EventBridge + SNSからのメール件名をカスタマイズする でイベントからのメール通知でやったことを、アラームに変えてやってみた。アラームのトリガーはEC2インスタンスCPU使用率閾値超えとする。
ベースの参照は以下クラメソさんネタ。ただしこちらは本文のカスタマイズであり、件名は変えていない。またLambdaも使用していない。これに先の過去記事パターンを合体させてやってみた。
CloudWatch アラームの通知メールを少しでも読みやすくしたい
処理概要
- CloudWatchアラームのステータスがALARMに変わる。
- Lambda関数起動
- SNSに連携される
- メール通知
作業概要
- SNSトピック作成〜サブスクライブ
- CloudWatchアラーム作成
- Lambda関数作成(Lambda用IAMロールは既存流用)
- EventBridgeルール作成
- EventBridgeルールのターゲットに3.のLambda関数を設定する
- 対象EC2インスタンスのCPU負荷を上げてアラームステータスにする
- メール通知確認
検証に使用したアイテム
アイテム | 名称 |
---|---|
SNSトピック | alarm-notification-topic |
CloudWatchアラーム | CPU_Utilization_Test |
Lambda関数 | cw-alarm-sns-function |
EventBridgeルール | cw-alarm-rule |
やったこと
SNSトピック作成、Lambda関数作成は冒頭のリンク過去記事でもやったので省略。Lambda関数の環境変数でSNSトピック、メール件名を指定している。一応後半にスクショあり。
CLIよりCloudWatchアラーム作成。少ない負荷でもアラームステータスになるように閾値は10%にしてある。
$ aws cloudwatch put-metric-alarm --alarm-name "CPU_Utilization_Test" \
--metric-name "CPUUtilization" \
--namespace "AWS/EC2" \
--statistic "Maximum" \
--period 60 \
--evaluation-periods 1 \
--datapoints-to-alarm 1 \
--threshold 10 \
--comparison-operator "GreaterThanThreshold" \
--dimensions "Name=InstanceId,Value=i-0xxxxxxxxxxx9"
EventBridgeルールの作成。以下の場合、“CPU_Utilization_“を含むアラームと関連付けられる
$ AWSREGION=ap-northeast-1
$ AWSACCOUNT=my-account-id
$ aws events put-rule --name "cw-alarm-rule" \
--event-pattern "{\"source\": [\"aws.cloudwatch\"],\"detail-type\": [\"CloudWatch Alarm State Change\"],\"resources\": [{\"prefix\": \"arn:aws:cloudwatch:${AWSREGION}:${AWSACCOUNT}:alarm:CPU_Utilization_\"}],\"detail\": {\"state\": {\"value\": [\"ALARM\"]}}}"
以下の様にルールが作成された。
{
"source": ["aws.cloudwatch"],
"detail-type": ["CloudWatch Alarm State Change"],
"resources": [{
"prefix": "arn:aws:cloudwatch:ap-northeast-1:0123456789102:alarm:CPU_Utilization_"
}],
"detail": {
"state": {
"value": ["ALARM"]
}
}
}
しかしこの段階ではまだターゲットが存在しない。前回はコマンドでターゲット指定したが、今回はマネコンからやった。対象のルールを選択して「Edit」ー> 「Select targets」で作成済みのLambda関数を指定して、「Update」
すると、以下の様にLambda側のトリガーとして、セットしたルールが設定される。
ここまでやったら、以下の流れでメール通知される、はず。
① EC2インスタンスのCPU使用率を上げてアラーム発行させる ② EventBridgeルールでターゲットに指定したLambdaに渡される ③ Lambdaで設定したSNSに渡される
ちなみにCPU使用率UP時はこんなのをshellにしてバックグラウンドで複数実行させた。アラームの設定で閾値10%にしたが、これをt3.microマシン上で3回くらい同時に回せば軽く90%くらいになる。
CNT=0; while [ $CNT -lt 100000 ]; do CNT=$(( CNT + 1 ));done
少し経つとアラームのステータスが変わって、カスタム件名のメールが届いた!しかし本文がひどい…
サンプルコードではMessage=json.dumps(event)
としているから、JSONデータをそのまま吐き出しているだけ。本文をカスタマイズする場合はこのeventをいじる必要がある。冒頭のクラメソさんの事例もはっきりいって面倒くさそうだったが、コードでやるのも面倒だなぁ、何せサンデープログラマだから。
eventに相当するJSONデータ
{"version": "0", "id": "86fa8a3f-7470-8c16-ef56-aaba9821771e", "detail-type": "CloudWatch Alarm State Change", "source": "aws.cloudwatch", "account": "123456789101", "time": "2021-11-03T10:17:51Z", "region": "ap-northeast-1", "resources": ["arn:aws:cloudwatch:ap-northeast-1:123456789101:alarm:CPU_Utilization_Test"], "detail": {"alarmName": "CPU_Utilization_Test", "state": {"value": "ALARM", "reason": "Threshold Crossed: 1 out of the last 1 datapoints [100.0 (03/11/21 10:11:00)] was greater than the threshold (10.0) (minimum 1 datapoint for OK -> ALARM transition).", "reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2021-11-03T10:17:51.018+0000\",\"startDate\":\"2021-11-03T10:11:00.000+0000\",\"statistic\":\"Maximum\",\"period\":60,\"recentDatapoints\":[100.0],\"threshold\":10.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2021-11-03T10:11:00.000+0000\",\"sampleCount\":5.0,\"value\":100.0}]}", "timestamp": "2021-11-03T10:17:51.020+0000"}, "previousState": {"value": "INSUFFICIENT_DATA", "reason": "Insufficient Data: 1 datapoint was unknown.", "reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2021-11-03T10:13:51.019+0000\",\"statistic\":\"Maximum\",\"period\":60,\"recentDatapoints\":[],\"threshold\":10.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2021-11-03T10:13:00.000+0000\"}]}", "timestamp": "2021-11-03T10:13:51.023+0000"}, "configuration": {"metrics": [{"id": "4cbe7286-d70f-fcb9-4a0a-758612d568db", "metricStat": {"metric": {"namespace": "AWS/EC2", "name": "CPUUtilization", "dimensions": {"InstanceId": "i-0b22a89b0bb3faf49"}}, "period": 60, "stat": "Maximum"}, "returnData": true}]}}}
と、ここで別途最近実施した、特別カスタマイズをしないアラーム + SNS送信検証時のメールを見たら、英語のみとはいえこっちの方がまだ全然見やすい。そりゃわかりにくいけど、JSON生データよりマシ。もう本文はこれでいいんじゃね?という気もするんだが。件名も、アラーム名が件名に入るんだから識別・フィルタしやすいアラーム名にすればどうにかなりそうな気もする。…と、減速気味になってきた。
…が!以下の補足事項を思い出した。アラーム単体では無効化・有効化の制御ができない。となると、やはりEventBridgに組み込む方がいいんだよな。うーむ…。頭痛いから明日考えよう。明後日かもしれない。
補足 アラームを一時無効化したい場合は、Rule側で制御する。マネコンで対象のルールを選択して、「Distable/無効にする」ボタンを押下。(アラーム単体ではこの機能がない)