ぽっちゃすぶろぐ

かまってちゃんの繰り広げる壮大で心温まる人生の冒険記

CloudWatchを使ってec2インスタンスの状況に合わせてSlackに通知する。その2

前回の続き。CloudWatchでステータスの変化を検知したらslackに通知する事ができました。指定したインスタンスだけだったり微妙に不便なのでもう少し使い勝手を改善してみます。またAWS Cloud9でLambda関数を作成すると自動実行ロールが作成されて便利な反面、よくわからないという・・・。今回は自分で実行ロールを作成してlambdaへの理解を深めたいなと思います。あとあと、テストの為にインスタンスを起動と停止を繰り返すのも面倒なので、作成したLambda関数のテストもやってみました。

やりたい事

前回の続き。

pottyasublog.hatenablog.jp

前回は、特定のインスタンスを監視して変化があったらSlackに通知を行いました。

微妙に不便なので、全てのインスタンスを監視対象にして、Ec2インスタンスを起動と停止があったらインスタンスIDと共にSlackに通知するようにします。テキストだとさみしいのでSlackのメッセージも少し豪華にしました。そして、作ったlambda関数のテストも行う。

使ったもの

・AWS Lambda
・AWS CloudWatch
・Slack Incomeing Webhook

Slackの設定

あらかじめSlackで Incomeing Webhookの設定を行っておきましょう。

Lambda関数の作成

まずはLambda関数を作り直す事にしました。以下のようになりました。前回より多少はスマートになった気がします。

import json
from urllib.request import Request, urlopen

def lambda_handler(event, context):
    
    #作成したwebhookurlを指定する
    webhookurl = "自分のwebhookURLをここに"
    
    # ec2のステータスをイベントから取得する
    detail = event['detail']
    instance_id = detail['instance-id']
    instance_state = detail['state']
    
    # メッセージ本文 (attachmentを使ってリッチなメッセージを送る)
    slack_message = { 
        "attachments": [
            {
                "color" : "good",
                "title" : "EC2 State Notice",
                "pretext" : "ec2インスタンスに変化があったわよ:heart:",
                # メッセージ本文
                'text': "ID: %s \n State: %s" % (instance_id, instance_state)
            }
        ]
    }
    
    req = Request(webhookurl, json.dumps(slack_message).encode('utf-8'))
    responce = urlopen(req)
    responce.read()

はまりポイントとしてはモジュールがなかったりして困りました。とりあえず上記の奴はlambdaで使えました。今回はAWS上でオンラインで作成しています。pipしたい時とかはローカルで作成してモジュールごとzipに固めてアップロードする必要があるみたい。

qiita.com
また、Slackのリッチなメッセージについては以下を参考にしました。

api.slack.com

Lambda関数の実行ロール

前回はcloud9で作成すると自動で実行ロールが作成されました。今回は自分で作成してみます。

IAMからロールの作成を行います。

f:id:rokusasu2001:20180302211031p:plain
AWSサービス→Lambdaと選択していきます。付与する権限については「CloudWacth Event Read Only Access」を割り当てました。権限は最小限であるほうが望ましいのでこの点については今後も勉強が必要そう・・・。

AWS Lambdaのテスト

テストもできるちょーべんりー♡って事で。作成したlambda関数のテストもやってみました。lambdaのメニューからテストの作成を行います。

f:id:rokusasu2001:20180302205042p:plain

作成した関数はCloud Watchのイベントを受け取って動作します。サポートされているサービスごとにどのようなイベントが渡されるのかは公式情報があるので参考にします。

docs.aws.amazon.com

ec2のイベントを参考にテストデータは以下のようにしました。

{
   "id":"7bf73129-1428-4cd3-a780-95db273d1602",
   "detail-type":"EC2 Instance State-change Notification",
   "source":"aws.ec2",
   "account":"123456789012",
   "time":"2015-11-11T21:29:54Z",
   "region":"us-east-1",
   "resources":[
      "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111"
   ],
   "detail":{
      "instance-id":"i-abcd1111",
      "state":"stopped"
   }
}

これでテストを実行すると無事にslackに通知が届きました。

CloudWatchの準備

前回は特定のインスタンスIDを監視していましたが、今回はec2インスタンス全体を監視することにしました。

f:id:rokusasu2001:20180302205946p:plain

任意のインスタンスを選択肢、ターゲットを作成した新たなLmbda関数に設定して完了。

完成!

インスタンスが起動・停止されるたらインスタンスIDと一緒にコートニーちゃんがお知らせしてくれました。(コートニーちゃんの出演するキングオブエジプトが明日地上波で放送されます。みんなでみよう!。映画自体は微妙です。)

f:id:rokusasu2001:20180302211758p:plain

今後

もうすこしロールについては理解を深めたいところ。

あと起動された時に通知はくるけど、利用するインスタンスが増えてくると新規作成とかがわからなくなってしまう・・・。なのでインスタンスの作成・削除があったときにも通知を出すのが次の目標かな。

BlueprintとかをみるとAWS SNSを使っているモノがチラホラ。CloudWatchからlambda自体は呼び出せるけど、AWS SNSのTopicを用いる方法とかのメリットを調べておきますかね。