AWSとSlackを連携し、EC2インスタンスのステータス検知を通知してみた
AWSとSlackを連携する方法として、2020年4月に正式リリースされたAWS Chatbotがありますが連携できる機能に限りがあり、私がやろうとしていたことはChatbotでは対応できなかったので、Lambdaを用いてSlackへ通知する従来の方法で通知できるようにします。
やりたいこと
時折会社で運用している開発用のEC2インスタンスがいつの間にか落ちていることがあり、開発者からの指摘で気づくことがありましたのでもっと早く気づくようにするために、EC2インスタンスのステータスがstoppedになったら、Slackのチャンネルへ通知できるような仕組みを作る。
使う機能
・CloudWatch Event
一般的にはCloudWatchAlarmからLambdaへ通知を送り、そのままSlackへ送ることが多く、AWS Slackと検索するとそういった記事がたくさん出てきました。
ですが、EC2インスタンスのステータスを検知するにはCloudWatch Alarmではなく、CloudWatch Eventでなければならないようです。
・Lambda
CloudWatch Eventで作成したイベント結果をLambdaへ渡します。
受け取ったLambdaはSlackのチャンネルへイベント結果を通知するようにします。
手順
①SlackアプリからWebhookを追加する
Slackの公式サイトによりますと、Webhookを活用することで、データの受信をSlackのチャンネルに指定することができます。
追加後のページからWebhook URLを取得する。こちらは後でLambda関数内にて使用します。
②新規Lambda関数を作成する。
新規でLambda関数を作成し、設定などは以下のようします。
〇一から作成
〇関数名は適当な名前
〇ランタイムはPythonの最新バージョン
関数コードは以下の通りです。
from __future__ import print_function
import os, json, urllib.request
def lambda_handler(event,context):
print(event) #CloudWatch Eventの結果がjson形式で表示されます。
print(context)
region = 'ap-southeast-1'
message = {
'text': "EC2 Instance stopped from %s" % (event)
}
data = json.dumps(message).encode('ascii')
req = urllib.request.Request(os.environ['slackUrl'], data )
try:
response = urllib.request.urlopen(req)
response.read()
print("Message posted: %s" % message )
except Exception as e:
print(e)
変数'slackUrl'は先ほど取得したWebhook URLを入れ込みます。
③CloudWatch Eventでルールを作成する
CloudWatchからイベントページを選択し、今すぐ始めるをクリックします。
ルールの作成では、設定などは以下のようにします。
イベントパターン
サービス名:EC2
イベントタイプ: EC2 Instance State-change Notification
特定の状態:stoppedターゲット:Lambda関数を選択し、作成したLambda関数名をsターゲット:Lambda関数を選択し、作成したLambda関数名を選択します。
テスト
準備ができましたので、EC2インスタンスを停止します。
停止したEC2インスタンスの情報がSlackへ通知されるようになりました。
課題
Slackで表示されたメッセージはCloudWatch Eventの内容をjson形式でLambdaへ渡し、特に整形などをせずにそのままSlackへ渡したものになっています。
そのため人の目には可読性が悪く、やや使いにくいものになっています。
Pythonの知識がある人なら、json形式のeventからインスタンスIDとインスタンスステータスの部分だけを抽出できると思うのですが、残念ながら方法が分からずこのように不格好な形になりました。
もしPythonに詳しい人がいましたらLambdaコードのどの部分を修正すればいいか教えてくださると幸いです。
追記:2020年5月27日
CloudWatch Eventの設定でjsonの中身を抽出してくれる設定がありましたので、それを用いることで変更することができました。
※念の為インスタンスIDを隠しています。
他にも停止したインスタンスを自動的に再起動したり、@hereをつけて全体へ通知できるようにするなど、色々と機能の改修を行えましたので、そちらの部分も追記で述べようと思います。
反省点
冒頭に述べた通りCloudWatch Alarm→Lambda→Slackの方法はたくさん記事がありましたが、CloudWatch Event→Lambda→Slackの方法はあまり見つからず、最終的に海外のYoutube動画を参考にしました。
AWS Chatbotを使えたらだいぶ楽に構築できるのですが、残念ながらCloudWatch Event未対応でかつ日本語情報も少ないことから見送ることになりました。機能アップデートで追加されることをお待ちしています。