CloudWatchアラームをSlackに通知する方法:ステップバイステップガイド

今さらながら、CloudWatchのアラームをSlackに連携する手順を記載します。
今回は、AWSのアプリケーションロードバランサーの「UnHealthyHostCount」 が1以上のときにSlackに通知されるようにします。具体的にはロードバランサー配下にEC2が2台配置されており、そのEC2のどちらかがエラーでアクセス出来ない場合にその状態を検知するイメージです。
Slackへ連携する方法としては、「AWS Chatbot」を使用する方法と「AWS Lambda」を使用する方法がありますが、今回は「AWS Lambda」を使用してみます。

AWS CloudWatchアラームをSNSトピック経由でLambda関数に連携し、Lambda関数がSlackのWebhookに通知を送信することで、リアルタイムでアラートを受信します。
AWS SNSのトピックを作成
SNS(Simple Notification Service) でトピックの新規作成をします。

a.トピックの作成をします。
- タイプで[スタンダード]を選択する。
- 名前を記入する。
- 表示名を記入する。

[トピックの作成]をクリックし、トピックの作成が一旦完了です。
CloudWatchアラームの設定
CloudWatchで新しいアラームを作成し、作成したSNSトピックを通知先として設定します。

CloudWatchでアラームの新規作成をします。

ステップ1:メトリクスと条件の指定
メトリクスと条件の指定で [メトリクスの選択] をクリックします。

メトリクスで「UnHealthyHostCount」を検索し、[ApplicationELB > AppELB 別、TG 別メトリクス] をクリックします。

引き続き、メトリクスと条件の指定を行います。
- 名前空間は「AWS/ApplicationELB」が設定される。
- メトリクス名を入力する。
- TargetGroupを選択する。
- LoadBalancerを選択する。
- 統計は「最大」を選択する。
- 期間は「1分」を選択する。

条件を設定します。
- しきい値の種類は「静的」を選択する。
- UnHealthyHostCount が次の時…は「以上」を選択する。
- …よりも「1」を入力する。
[次へ]をクリックします。

ステップ2:アクションの設定
通知を設定します。
- アラーム状態トリガーは「アラーム状態」を選択する。
- 次のSNSトピックに通知を送信は「既存のSNSトピックを選択」を選択する。
- 通知の送信先を選択する。(先ほど作成したSNSトピック)
[次へ]をクリックします。

ステップ3:名前と説明を追加
名前と説明を設定します。
- アラーム名を入力する。
[次へ]をクリックします。

ステップ4:プレビューと作成
プレビューを確認し、設定内容に問題無ければ、[アラームの作成]をクリックします。
SlackのIncoming Webhookの作成
Slackの「Incoming Webhooks」アプリをインストールし、Webhook URLを取得します。
Slackの[ ツールと設定 > アプリを管理する ]をクリックします。

Slack側の画面に遷移するので、[カスタムインテグレーション]を選択します。

[Incoming Webhook]を選択します。

[Salckに追加]をクリックします。

Slackチャンネルを選択し[Incoming Webhook インテグレーションの追加]をクリックします。

「Webhook URL」の確認をします。

「Webhook URL」は、後ほどLambda関数で使用します。
Lambda関数の作成
AWS Lambda関数を作成し、SNSトピックからの通知を受信してSlack Webhookに送信するロジックを実装します。

[関数の作成]をクリックします。
関数を作成します。
- 「一から作成」を選択する。
- 関数名を入力する。
- ランタイムは「Node.js 20.x」を選択する。
- アーキテクチャは「x86_64」を選択する。

上記設定後、[関数の作成]をクリックします。
コードを書きます。

コードは下記で動きます。
※ /services/YOUR/SLACK/WEBHOOK
は「Webhook URL」で置き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import https from 'https' ; export const handler = async (event) => { const message = JSON.parse(event.Records[0].Sns.Message); const postData = JSON.stringify({ text: `CloudWatch Alert: ${message.AlarmName}\n${message.NewStateReason}` }); const options = { hostname: 'hooks.slack.com' , path: '/services/YOUR/SLACK/WEBHOOK' , method: 'POST' , headers: { 'Content-Type' : 'application/json' , 'Content-Length' : postData.length } }; return new Promise((resolve, reject) => { const req = https.request(options, (res) => { res.on( 'data' , (d) => process.stdout.write(d)); res.on( 'end' , resolve); }); req.on( 'error' , (e) => reject(e)); req.write(postData); req.end(); }); }; |
Lambdaのテストイベント作成
ここまでの設定が正しいかどうか、テストイベントを作成して動作確認します。

テストを作成します。
- イベントアクションをテストで「新しいイベントを作成」を選択する。
- イベント名を入力する。
- イベント共有の設定は「プライベート」を選択する。
- イベントJSONの内容は下記に記します。

下記がテストイベント用JSONです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | { "Records": [ { "EventSource": "aws:sns", "EventVersion": "1.0", "EventSubscriptionArn": "arn:aws:sns:us-west-2:123456789012:example-topic", "Sns": { "Type": "Notification", "MessageId": "11112222-3333-4444-5555-666677778888", "TopicArn": "arn:aws:sns:us-west-2:123456789012:example-topic", "Subject": "Test SNS Notification", "Message": "{\"AlarmName\":\"ExampleAlarm\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: 1 datapoint (5.0) was greater than or equal to the threshold (5.0).\"}", "Timestamp": "2024-05-23T12:34:56.789Z", "SignatureVersion": "1", "Signature": "EXAMPLE", "SigningCertUrl": "EXAMPLE", "UnsubscribeUrl": "EXAMPLE", "MessageAttributes": { "key": { "Type": "String", "Value": "value" } } } } ] } |
上記で保存し、テスト実行すると、下記のようにSlackに通知されました。

SNSトピックをトリガーとしてLambda関数に追加
作成済のSNS「UnHealthyHostCount」にサブスクリプションを作成しするため[サブスクリプションの作成]をクリックします。

サブスクリプションを作成します。
詳細
- トピックARNは既存のSNSのものが設定する。
- プロトコルで[AWS Lambda]を選択する。
- エンドポイントは先ほど作成した関数のARNを入力する。
上記を設定し、[サブスクリプションの作成]をクリックします。

以上で設定完了です。