CloudWatchの監視結果を簡単かつ汎用的にSlackへ通知する環境を用意したく、以下の構成で作成しました。
CloudWatchアラーム -> SNSトピック -> Lambda -> Slack
1. Slack側の設定
監視通知先のSlackチャンネルとIncoming WebhooksまたはWebhooksワークフローを用意し、外部から叩くためのwebhookのURLを発行します。
また、受け取った通知メッセージをチャンネルに表示するためのパラメータ(今回はパラメータ名をmessage
としている)設定を行います。
(作成方法など詳しくは各リンク先のドキュメント参照)
2. SNS (Simple Notification Service)でトピックの作成
-
トピックの作成
- タイプ :
スタンダード
- タイプ :
3. Lambda関数の作成
-
関数の作成
- トリガー : 上記で作成したSNSトピックを選択
- 環境変数 :
SLACK_WEBHOOK_URL
: 発行したwebhookのURL - コード : e.g.
import json
import os
import urllib3
# Slack Webhook URL
SLACK_WEBHOOK_URL = os.getenv("SLACK_WEBHOOK_URL")
def lambda_handler(event, context):
http = urllib3.PoolManager()
# SNSからのメッセージを取得
sns_message = event["Records"][0]["Sns"]["Message"]
# jsonのパース
data = json.loads(sns_message)
# Slackに送るメッセージを作成
message = f"- **Alarm Name** : {data['AlarmName']} \n"
message += f"- **Description** : {data['AlarmDescription']} \n"
message += f"- **Reason** : {data['NewStateReason']} \n"
message += f"- **New State** : {data['NewStateValue']} \n"
message += f"- **Old State** : {data['OldStateValue']} \n"
slack_message = {
"message": f"{message}"
}
# Slackにメッセージを送信
response = http.request(
"POST",
SLACK_WEBHOOK_URL,
body=json.dumps(slack_message),
headers={"Content-Type": "application/json"}
)
return {
"statusCode": response.status,
"body": response.data
}
4. CloudWatchアラームの作成
- CloudWatchコンソールから
アラームの作成
- メトリクスと条件の指定 : 監視したいメトリクスと通知する際の閾値などの条件を決めます
- アクションの設定 :
- アラーム状態トリガー :
アラーム状態
- 次のSNSトピックに通知を送信 :
既存の SNS トピックを選択
- 通知の送信先 : 先ほど作成したSNSトピックを選択
- アラーム状態トリガー :
- 名前と説明
- アラーム名 : Lambdaで
AlarmName
として受け取る値 - アラームの説明 : Lambdaで
AlarmDescription
として受け取る値
- アラーム名 : Lambdaで
これでアラームを作成すると、メトリクス条件に合致した場合にSlackへ通知が飛ぶようになります。
アラームを追加したい場合も同じSNSトピックを使い回しながら同じように作成していくことが可能です。
SNSからLambdaへ通知されるメッセージのjsonは以下のようなフォーマットになっています。
{
"AlarmName": "sample-alarm",
"AlarmDescription": "This is a sample alarm.",
"AWSAccountId": "XXXXXXXXXXXX",
"AlarmConfigurationUpdatedTimestamp": "2025-01-01T00:30:35.137+0000",
"NewStateValue": "ALARM",
"NewStateReason": "Threshold Crossed: 1 out of the last 1 datapoints [2.0 (01/01/25 01:35:45)] was greater than the threshold (1.0) (minimum 1 datapoint for OK -> ALARM transition).",
"StateChangeTime": "2025-01-01T01:35:45.133+0000",
"Region": "US East (N. Virginia)",
"AlarmArn": "arn:aws:cloudwatch:us-east-1:XXXXXXXXXXXX:alarm:sample-alarm",
"OldStateValue": "OK",
"OKActions": [],
"AlarmActions": [
"arn:aws:sns:us-east-1:XXXXXXXXXXXX:sample-sns-topic"
],
"InsufficientDataActions": [],
"Trigger": {
"MetricName": "RequestCount",
"Namespace": "AWS/ApplicationELB",
"StatisticType": "Statistic",
"Statistic": "SUM",
"Unit": null,
"Dimensions": [
{
"value": "app/sample-elb/XXXXXXXXXXXX",
"name": "LoadBalancer"
}
],
"Period": 60,
"EvaluationPeriods": 1,
"DatapointsToAlarm": 1,
"ComparisonOperator": "GreaterThanThreshold",
"Threshold": 1.0,
"TreatMissingData": "missing",
"EvaluateLowSampleCountPercentile": ""
}
}