Help us understand the problem. What is going on with this article?

AWS Lambdaをつかって、CloudWatchが監視した値を超えたら、slackに通知する仕組みをつくろう on Python

More than 3 years have passed since last update.

はじめに

社内で「らむだが〜らむだが」と話していて、元C#の僕からするとプログラミング言語の何かかな?と思っていましたが、違いましたね。(C#にはラムダ式というのがある。)

社内では、AWS Lambda上にnode.jsランタイムを配置して、slack通知していましたが、nodeのversionが古くてそろそろサポートやめるよ、と言われたので、Pythonに切り替えることにしました。(nodeより、Pythonのほうが知っている人が社内にいたので)

AWS Lambdaでは、よくあるような処理はテンプレートとして用意されているので、結構簡単にできます。手順をまとめてみます。

設定手順

おおまかに下記の手順でやります。

  1. Lambda関数作成
  2. SNSの作成とLambdaとの連携
  3. EC2とSNSの連携
  4. コーディング
  5. テスト

構成図

最終的にこんな感じになります。

aws.png

※ 構成図はdraw.ioを使って書いてみました

手順

1. Lambda関数の作成

今回のメインとなるLambda関数を作成しておきます。指示に従っていけば簡単に作れます。
作り直しや削除も簡単にできるのでご安心を。

サービス一覧から、Lambdaを選択。

①.png

Lambda関数の作成を開始します。

②.png

フィルターに、slackと入力するとslackの雛形ができますが、今回はブランクで作成します。

③.png

トリガーはあとで設定するので、からのままにしておきます。

④.png

2. SNSの作成とLambdaとの連携

SNS = Simple Notification Service。何らかの処理や状態変更を受取、メッセージにして通知してくれるサービスです。
メールや今回のようなLamdaへメッセージを通知できます。
サービス自体は、2017/04/06現在翻訳はされていませんが、簡単な英語なので問題ないと思います。

SNSを作成し、subscriptionをくっつけます。

Subscriptionsを作成する。

AWS_SNS.png

先程作成したLambda関数を選択します

AWS_SNS.png

3. EC2(Cloud Watch)とSNSの連携

EC2の画面から、アラームを設定します。

EC2_Management_Console.png

4. コーディング

各種設定を行います

設定するものは下記です。
* Lambda関数名
* コード
* 環境変数
* 関数ハンドラーとロール
etc

今回は下記のように設定してみました。

Lambda_Management_Console.png

@コード

lambda_handler.py
from __future__ import print_function

import boto3
import json
import logging
import os

from urllib2 import Request, urlopen, URLError, HTTPError

# slackの設定
SLACK_CHANNEL = os.environ['SLACK_CHANNEL']
HOOK_URL      = os.environ['HOOK_URL']

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def lambda_handler(event, context):
    logger.info("Event: " + str(event))
    message = json.loads(event['Records'][0]['Sns']['Message'])
    logger.info("Message: " + str(message))

    alarm_name  = message['AlarmName']
    description = message['AlarmDescription']
    new_state   = message['NewStateValue']
    reason      = message['NewStateReason']

    if new_state == 'OK':
        emoji = ":+1:"
    elif new_state == 'ALARM':
        emoji = ":exclamation:"

    slack_message = {
        'channel': SLACK_CHANNEL,
        'text': "*%s %s: %s*\n %s\n %s" % (emoji, new_state, alarm_name, description, reason)
    }

    req = Request(HOOK_URL, json.dumps(slack_message))
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted to %s", slack_message['channel'])
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)

@環境変数+あるふぁ

Lambda_Management_Console_1.png

5. テスト

Lambdaの画面から、下記を実施します。

  1. アクション→テストイベントの設定→テストイベント入力
  2. 保存してテスト

手前味噌ですが、テストデータはこちらを参考にしていただければと。
* 参考:AWS Lambdaをつかった、CloudWatch監視 -> slack通知の際のテストデータ

実行結果

sandboxチャンネルに無事通知が飛びました。絵文字も入っていますね。

Slack_-_eversense.png

おわりに

簡単なプログラムでslack通知が実現できました。適切にメトリクス設定して、快適なAWSライフを。(通知しても、見をとしてしまったりしたら意味ないけれど…)

なお、Lambdaからは同一リージョンで作成したSNSしか設定できないようなので、リージョンをまたぐ場合は各リージョンのSNSをからLambdaを選択してあげます。

当初、Lambdaの環境変数を利用しようと思いましたが、base64周りでエラーが出てしまったので使えていません。これ使えると、Lambda関数が簡単に使いまわせるので次の機会にはきちんと対応しようと思います。

TanakanoAnchan
ベンチャーでITエンジニアをしています。 メインはWebエンジニア、たまにアプリエンジニア。 - フロントエンド - サーバーサイド - インフラ 昔使っていたVisual Studioの良さが忘れられない(VSCodeの方じゃない)。 C# .NETとPythonが好き。
eversense
家族を幸せにすることで、笑顔溢れる社会をつくる。
https://eversense.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away