CloudWatchアラームでSlackへ通知を行う。

AWSlambdaCloudWatchpythonSlack

Written by Kohei Yamada Posted on 2017/10/27



はじめに

CloudWatchアラームでモニタリングして、アラームが発生したらslackへ通知させる設定をしたいと思います。
最初はCloudWatchからLambdaを直接実行できるのかなと思ったのですが、直接実行できるのはイベントだけみたいです。アラームから直接Lambdaを実行することはできませんでした。なので、SNS経由で実行する必要があります。
イメージとしては以下のような構成になります。

slack-notification.png


slack への通知設定

図の右側(エンド側)から順番に設定していく必要があります。なのでまずはslackの設定を行います。


・channel の用意

今回は #lambda2slack という名前でchannelを用意します。
とりあえず、 slack への通知は Incoming Webhook という機能が slack API から提供されているのでそれを使って行います。

Incoming Webhook の設定に関しては前にQiitaに書いたのでそちらを参考にしてください。
参考:slackのIncoming Webhookを試してみた。


プログラムの作成

Incoming webhook を使うのに、 python のライブラリで slackweb というのがあるみたいです。今回はこれを使って行うことにしました。

とりあえずインストール。

$ pip install slackweb

インストールできたらコマンドで試してみます。

$ python
Python 3.6.2 (default, Sep 28 2017, 02:02:02) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import slackweb
>>> slack = slackweb.Slack(url="https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX")
>>> slack.notify(text="hello, kohei!!")
'ok'

slack.notify で引数に渡した値(ここでは"hello, kohei!!")が先ほど作成したslackのchannelへ通知されたらOKです。

スクリーンショット 2017-10-19 21.01.37.png

とりあえず、今回はCloudWatch からslackへ通知を行うことを目的としているので、これ以上のプログラミングは行わずに次へ進みます。


プログラムの関数化

Lambdaで実行できるようにするには、プログラムを関数として扱えるようにする必要があります。
先ほどコマンドで実行した内容を以下のように関数化して保存します。

$ vim lambda2slack.py
---
import slackweb

def lambda_handler(ecent, context):
    slack = slackweb.Slack(url="https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX")
    slack.notify(text="hello, kohei!!")

関数として利用できるか確認をしてみます。

$ python
>>> from lambda2slack import lambda_handler
>>> lambda_handler(None, None)

先ほどと同じようにslackへ通知が届いたらOKです。


Lambdaの設定

slackへ通知ができるところまで確認ができたので、Lambdaの設定を行います。


・zip圧縮

今回の場合、slackwebはデフォルトで利用できるライブラリではありません。そのためコードだけアップしてもエラーとなってしまいます。そういう場合はライブラリも一緒にzipファイルとして圧縮してアップロードしてあげることで解決です。
まずは、アップロード用のディレクトリを作成し、そこへ必要なライブラリとプログラムを入れます。

$ mkdir upload
$ cd upload

今回必要となるslackwebのライブラリをアップロード用ディレクトリへダウンロードします。

$ pip install slackweb -t .
Collecting slackweb
  Using cached slackweb-1.0.5.tar.gz
Installing collected packages: slackweb
  Running setup.py install for slackweb ... done
Successfully installed slackweb-1.0.5

先ほど作成した関数化したプログラムファイルも入れます。

$ cp ../lambda2slack.py ./

配置が完了したら以下みたいになってるはずです。

$ ls
lambda2slack.py         slackweb            slackweb-1.0.5-py3.6.egg-info

揃ったらzip圧縮します。

$ zip -r upload.zip *
  adding: lambda2slack.py (deflated 42%)
  adding: slackweb/ (stored 0%)
  adding: slackweb/__init__.py (deflated 4%)
  adding: slackweb/__pycache__/ (stored 0%)
  adding: slackweb/__pycache__/__init__.cpython-36.pyc (deflated 15%)
  adding: slackweb/__pycache__/slackweb.cpython-36.pyc (deflated 41%)
  adding: slackweb/slackweb.py (deflated 60%)
  adding: slackweb-1.0.5-py3.6.egg-info/ (stored 0%)
  adding: slackweb-1.0.5-py3.6.egg-info/dependency_links.txt (stored 0%)
  adding: slackweb-1.0.5-py3.6.egg-info/installed-files.txt (deflated 43%)
  adding: slackweb-1.0.5-py3.6.egg-info/PKG-INFO (deflated 48%)
  adding: slackweb-1.0.5-py3.6.egg-info/SOURCES.txt (deflated 46%)
  adding: slackweb-1.0.5-py3.6.egg-info/top_level.txt (stored 0%)

upload.zipというのが出来上がっているので、あとはこれをLambdaへアップロードすればOKです。

$ ls
lambda2slack.py         slackweb-1.0.5-py3.6.egg-info
slackweb            upload.zip


・Lambdaへアップロード

AWS管理画面から、Lmabdaのサービス画面へ行き、「関数の作成」をクリックします。
スクリーンショット 2017-10-21 14.19.47.png

今回はテンプレなどは使わないので「一から作成」をクリックします。
スクリーンショット 2017-10-26 12.51.21.png

名前を入力し、ロール「カスタムロールの作成」を選択します。
スクリーンショット 2017-10-26 12.53.46.png

するとIAMポリシー作成画面へ移動するのでそこでポリシーを作成します。
今回の場合はデフォルト(ログ出力権限)で十分です。
スクリーンショット 2017-10-26 12.53.21.png

「既存のロール」のところが先ほど作成したロールになっているのを確認して「関数の作成」を行います。
スクリーンショット 2017-10-26 12.53.57.png

「関数コード」ランタイム「python 3.6」コードエントリ タイプ「.zipファイルをアップロード」ハンドラ「lambda2slack.lambda_handler」にして先ほどzipにしたファイルをアップロードします。
アップロードができたら「保存してテスト」をクリックします。
スクリーンショット 2017-10-26 12.56.26.png

「実行結果:成功」となればOKです。
スクリーンショット 2017-10-26 12.57.04.png

ちなみにこの時点でslackへも通知が届いているはずです。


SNSで通知設定

次はCloudWatchからlambdaを実行できるようにするために、SNSトピックを作成し、そこへ作成したLambdaを登録します。
AWS管理画面から、SNSのサービス画面へ行きます。

「Create Topic」をクリックします。
スクリーンショット 2017-10-26 14.04.08.png

Topic nameを入力したら「Create topic」でトピックを作成します。
スクリーンショット 2017-10-26 14.06.41.png

トピックが作成できたら「Create subscription」をクリックします。
スクリーンショット 2017-10-26 14.14.30.png

Protocol「AWS Lambda」Endpointを先ほど作成したLambda関数(lambda2slack)を指定して「Create subscription」で作成します。
スクリーンショット 2017-10-26 14.14.58.png

以上でSNSの設定は完了です。


CloudWatchからの呼び出し

AWS管理画面から、CloudWatchのサービス画面へ行き、アラームから「アラームの作成」を行います。
メトリクスの選択でアラームでチェックしたいメトリクスを指定します。
スクリーンショット 2017-10-26 15.43.19.png

スクリーンショット 2017-10-26 15.44.19.png

今回は通知を確認したかったのでLambdaの呼び出し(Invocations)を指定し閾値を≧1にしました。

アラームの定義で閾値を設定したらアクション通知の送信先を先ほど作成したSNSトピックのlambda2slackを指定してから「アラームの作成」をクリックして作成します。
スクリーンショット 2017-10-26 15.41.02.png

これでCloudWatchの設定も完了し、一連の設定が完了しました。
おそらく先ほどLambdaを登録した際にテストで実行しているので、設定がうまくできているとslackへ通知が届くとお思います。


おわりに

以上が「CloudWatchアラームで検知」→「slackへ通知」を行うための設定です。
本来ならURLなどは変数にして「KMSで暗号化」とかするのが良いみたいですが、まずは最低限のサービスでシンプルに構築してみたほうが仕組みがわかって良いかなと思いました。
ここから徐々に他のサービスを利用したり、プログラムを書いたりして行けたらいいかなと思います。