Amazon SNS + Slack Workflowを使って、CloudWatch Alarmの通知をSlackチャンネルへ投稿する

AWSリソースに対する異常検知として、CloudWatch Metricsに対して設定したしきい値を超過した場合、CloudWatch Alarmで通知を飛ばすことができます。

日頃Slackをよく見ている身としては、何かあったらSlackチャンネルへ通知されると嬉しいことから、仕組みを考えました。

Slackへ通知する仕組みとして思い浮かぶのはLambdaやChatBotです。

ただ、監視対象が異常となることは稀なものについては、Lambdaよりメンテナンス不要、かつ、ChatBotよりもカスタマイズ可能なものを採用したくなりました。

調べてみたところ、以下のStack OverflowにあるSam氏の回答 Amazon SNS + Slack Workflow 構成で設定・運用できそうでした。

amazon web services - Confirming AWS SNS Topic Subscription for Slack Webhook - Stack Overflow

ここでは、実際に構成してみた時の内容を記載します。

設定が必要な各リソースについて

今回設定が必要な各リソースは以下となります。

  • AWS

    • CloudWatch Alarm

    • Amazon SNS (以降、SNSと表記)

      • 今回はSlack通知のみ行い、Eメール通知は行わない

  • Slack

    • Slack Workflow

では、実際に各サービスを設定していきます。

Eメール通知不要なSNSトピックを作成

CloudWatch Alarmを設定する際のウィザードではSNSトピックを作成可能です。 ただ、そのときに作るSNSトピックではEメール通知が必須となってしまいます。

そこで、今回は事前にEメール通知が不要なSNSトピックを作成します。その後、CloudWatch Alarmへ割り当てることにします。

今回のSNSトピックの設定は以下の通りです。 なお、残りの項目はデフォルトのままにします。要件に応じて変更してください。

項目

タイプ

スタンダード

名前

hello_alarm_topic

CloudWatch Alarmを設定

続いて、CloudWatch Alarmを設定します。

なお、今回は通知さえ飛ばせればどんなメトリクスでも構いません。AWSドキュメントで紹介されているチュートリアルを参考にメトリクスを設定しても良いでしょう。 アラームのユースケースと例 - Amazon CloudWatch

今回必要なCloudWatch Alarmの設定は以下の通りです。

項目

アラーム状態トリガー

アラーム状態

次のSNSトピックに通知を送信

既存のSNSトピックを選択

通知の送信先

hello_alarm_topic (上記で作成したSNSトピック)

アラーム名

hello_world_alarm

なお、設定する途中にあるEメールエンドポイントにて トピックにエンドポイントがありません と表示されますが、Eメール通知を行わない設定の場合はこのままで問題ありません。

ここまででAWS側の準備ができました。次はSlack Workflowの設定になります。

Slack WorkflowでSNSトピックのサブスクリプションを確認できるよう設定

Slack Workflowでは、SNSトピックのサブスクリプションを受け取れるように設定します。

ただ、AWSのSNSトピックのサブスクリプションを受け取るには、受け取る側で事前に SNSトピックのサブスクリプションの確認 (以降 サブスクリプション確認 と表記)を済ませておく必要があります。

そこで、Slack Workflowでサブスクリプションの確認ができるよう設定します。

まず、Slackチャンネルの詳細にある Integrations タブから Add Automation > New Workflow > Build Workflow の順にクリックします。

新しいSlackウィンドウが開きます。 右側に表示されているメニューから From a webhook をクリックします。

Choose how to start the workflow ダイアログが表示されます。 ここでは何も入力せず、 Continue をクリックします。

Slackウィンドウの表示が変わります。次は Starts with a webhook をクリックします。

Change how this workflow starts ダイアログが表示されます。 ここでは Set Up Variables をクリックします。

KeyとData Typeの入力が求められるので、それぞれ次の値を設定し、 Done をクリックします。

項目名

Key

SubscribeURL

Data Type

Text

ここで SubscribeURL というキー名は、サブスクリプション確認をするときに、AWSから渡されてくる項目を指しています。

ステップ 3: サブスクリプションを確認する - Amazon Simple Notification Service

そのため、 SubscribeURL というキー名以外で設定した場合はサブスクリプション確認ができなくなるため、注意してください。

次に、Web request URLにある Copy Link をクリックし、URLをコピーします。 このURLは、AWSの設定でSNSトピックをサブスクライブするときに使います。

これで Change how this workflow starts ダイアログでの設定は完了するため、 Save をクリックします。

続いて、 Then, do these things の設定を行います。

まず、右側のStepsの検索窓に send と入力します(①)。

次に Send a message to a channel をクリックします(②)。

Send a message to a channel ダイアログが表示されるため、設定を行います。

サブスクリプション確認用のメッセージを設定するため、右下にある {} Insert a variable をクリックし、先ほど作成した SubscribeURL を選択します。

すると、 Add a message の中に、 SubscribeURL が指定されます。 これにより、Slackチャンネルへ投稿する際に、Slack Workflowへ通知された時にキー SubscribeURL の値が展開されます。

あとはこのまま Save をクリックします。

設定が終わったので、右上の Finish Up をクリックします。

Finish Up ダイアログにて、 Name に任意の名前(今回は hello_world_slack )を設定した上で、 Publish をクリックします。

以上で、Slack Workflowでサブスクリプション確認を可能にする設定は完了です。

SNSトピックにサブスクリプションを作成

再びAWSの設定へと戻り、SNSトピックにSlack Workflow向けのサブスクリプションを作成します。

上記で作成したSNSトピック hello_alarm_topic を表示し、 サブスクリプションの作成 をクリックします。

続いて、以下の設定を持つサブスクリプションを作成します。

項目

トピックARN

hello_alarm_topic のARN

プロトコル

HTTPS

エンドポイント

Slackでコピーした Web request URL の値

rawメッセージ配信の有効化

チェックしない(デフォルトのまま)

なお、 rawメッセージ配信の有効化 をチェックしないことで、CloudWatch Alarmの情報はSNSの Message キーへと設定されます。一方、rawメッセージ配信を有効化してしまうと Message キーがなくなってしまうので、注意してください。

Amazon SNS raw メッセージの配信 - Amazon Simple Notification Service

Slackチャンネルでサブスクリプション確認を行う

ここまででサブスクリプション確認向けの設定が完了したため、実際にサブスクリプション確認を行います。

今回の場合、SNSにサブスクリプションを作成した時点で、Slackチャンネルにサブスクリプション確認用URLが投稿されます。

投稿されたURLをクリックすると、ブラウザが開き、 ConfirmSubscriptionResponse のXMLが表示されます。

続いて、AWSのサブスクリプションページをリロードすると、ステータスが 確認済 になります。

これでサブスクリプション確認は完了です。

正式版にSlackへ投稿するメッセージを修正

サブスクリプションの確認ができたので、Slackへ投稿するメッセージを正式版へと修正します。

今回は、

  • SNSから受け取った Message キーの値

  • 独自メッセージ

を投稿します。

最初に、先ほど作成したWorkflowを開きます。

続いて、 Starts with a webhook をクリックし、 Data Variables を編集します。

Key SubscribeURL をKey Message へと変更します。

続いて、 Then, do these thingsAdd a message を編集します。

  • 独自メッセージを テストアラートが届きました へと変更

  • Insert a variableMessage を挿入

最終的には、以下のスクリーンショットのような設定になります。

以上で設定は終わりです。 Save をクリックした後、右上の Publish Changes をクリックし、変更後のWorkflowを公開します。

AWS CLIによる動作確認

以上で全体の仕組みが完成したため、動作確認を行います。

動作確認をするためには CloudWatch Alarmのステータスを アラーム状態 にする必要があります。

メトリクス対象を操作して アラーム状態 とすることもできますが、手間がかかります。そこで今回はCloudWatch AlarmのステータスをAWS CLIで強制的に変更することで、動作確認とします。

まずは適切なAWS環境を使えるよう、AWS Vaultを使って適切なシェルに入ります。

なお、AWS Vaultについての詳細は、AWS Vaultを使ったスイッチロール設定手順 | Precena Tech Bookを参照してください。

% aws-vault exec some-profile

続いてAWS CLIを使ってアラーム状態にします。 set-alarm-state — AWS CLI 1.34.10 Command Reference

% aws cloudwatch set-alarm-state --alarm-name hello_world_alarm --state-value ALARM --state-reason "test" --region ap-northeast-1

CloudWatch Alarmを見ると、ステータスが アラーム状態 へと変化しています。

Slackのチャンネルを見ると、CloudWatch Alarmからの情報が投稿されていました。 動作は良さそうです。

確認が終わったので、CloudWatch Alarmのステータスを OK へと戻しておきます。

% aws cloudwatch set-alarm-state --alarm-name hello_world_alarm --state-value OK --state-reason "test" --region ap-northeast-1

もし、今回作成したCloudWatch Alarmを無効化しておきたい場合は、以下の手順で行えます。

アクション > アラームアクション > 無効化

おわりに

以上で、Amazon SNS + Slack Workflowを使って、CloudWatch Alarmの通知をSlackチャンネルへ投稿することができました。

CloudWatch AlarmからSlackチャンネルへの投稿する方法について、Lambdaよりメンテナンス不要、かつ、ChatBotよりもカスタマイズ可能としたい場合の参考となれば幸いです。

最終更新