最近AWSに興味を持ち始めました。
特にLambdaでイベントドリブンな処理を使いこなせるようになりたかったので、
Lambdaを使ってslackに通知をしてみることにしました。
下記を参考にしました。
CloudWatchは直接Lambdaを実行できないので、
Amazon SNS経由でLambdaを実行する必要があるようです。
事前にサービスや用語などを調べたのでメモしておきます。
・Amazon SNS (Simple Notification Service)とは
モバイルデバイスのアプリケーションにプッシュ通知メッセージを直接送信できる、プッシュメッセージングサービスです。
iOSやAndroidのプッシュ通知のほか、AWSのAmazon SQSへ通知をとばすこともできます。
他にもSMSやEメールによる通知にも対応しています。
・Amazon CloudWatch とは
AWSリソースとAWSで実行するアプリケーションのモニタリングサービスです。
AWSサービスのメトリックスやログファイルを収集、モニタリングしてアラームを設定することができます。
対応するAWSサービスを開始すると、データポイントを定期的にCloudWatchに送信するため、
意識せずにメトリックスをグラフィカルな画面で閲覧、分析することができます。
アラーム機能を使うと、SNSを使った通知や、AutoScalingによるEC2インスタンスの追加、EC2インスタンスの復旧も可能です。
・Amazon SNS 通知を使用した Lambda 関数の呼び出し
SNSとLambdaは統合されているため、SNS通知を使用してLambda関数を呼び出すことができます。
Lambda関数がサブスクライブしているSNSトピックにメッセージが発行されると、
発行されたメッセージのペイロードでLambda関数が呼び出されます。
Lambda関数は、メッセージペイロードを入力パラメータとして受け取り、
メッセージの情報の操作、他のSNSトピックへのメッセージの発行、または他のAWSサービスへのメッセージの送信を行うことができます。
・サブスクライブ(Subscribe)とは
特定のトピックについて新しい受信を登録します。これを行うとSNSから確認メッセージが生成されます。
CloudWatchからSNS通知を使ってLambda関数を呼び出し、slackに通知することができるようです。
それではやってみます。
slackのWebhook URL取得
手順は下記を参考にしました。
Webhook URLを取得するため、下記サイトにアクセスします。
https://slack.com/services/new/incoming-webhook
私は通知させるチャンネルを「#general」、カスタマイズ名を「AWS」にしました。
アイコンを絵文字や画像に設定することも可能です。
このページに表示されているWebhook URLの値をあとで使うことになるので控えておきます。
slackに通知するプログラムの実装
slackwebというpythonのライブラリがあったので使わせていただきました。
slackwebをインストールします。
$ pip install slackweb
pythonファイルを作成し、slackに通知する機能を実装します。
urlの値は、先ほど自分が取得したWebhook URLの値を設定します。
textの値は、通知させたいメッセージを入れます。
lambdaToSlack.py
import slackweb
def lambda_handler(ecent, context):
slack = slackweb.Slack(url="{自分のWebhook URLの値}")
slack.notify(text="Merry Christmas!!")
ちなみに、ローカルで実行して動作確認をすることができます。
$ python
>>> from lambdaToSlack import lambda_handler
>>> lambda_handler(None, None)
実行後にslackに通知が届いたら成功です。
Lambdaへアップロード
アップロード用に任意のフォルダを作成します。(今回はuploadとしました)
そのフォルダの中に、slackwebのライブラリと作成したpythonファイルを入れます。
$ cd upload
$ pip install slackweb -t .
$ cp ../lambdaToSlack.py ./
$ ls
lambdaToSlack.py slackweb slackweb-1.0.5.dist-info
zip圧縮します。
$ zip -r upload.zip *
upload.zipが作成されていることを確認します。
SNSの設定
AWSにログインし、サービスからLambdaを選択します。
Lambdaの画面で「関数の作成」ボタンをクリックします。
今回設計図は使わないので「一から作成」を選択します。
名前欄に任意の名前を設定し、ロールで「カスタムロールの作成」を選択するとIAMポリシー作成画面に遷移します。
IAMポリシー作成画面でIAMロールを「新しいIAMロール作成」、
ロール名を「lambdaToSlack」に設定します。(ロール名は任意です)
ポリシーの編集もできますが、今回はデフォルトのままで大丈夫です。
設定できたら右下の「許可」ボタンをクリックします。
Lambdaの画面に戻ってきたら
ロールを「既存のロールを選択」、既存のロールを先ほど作成したロール名に設定して
「関数の作成」ボタンをクリックします。
関数コードの設定をし、zipファイルをアップロードして
画面右上の「保存」ボタンをクリックします。
ハンドラの設定が実装したpythonファイル名と一致しないと関数を呼び出せないので注意してください。
ランタイム :python 3.6
コードエントリ タイプ:.zipファイルをアップロード
ハンドラ :lambdaToSlack.lambda_handler
関数パッケージ :upload.zip
アップロードができたらテストをしてみます。
CloudWatchのテストイベントが既存で作成されていなかったので、新規で作成しました。
下記を参考に作成し、テストを実行して成功することを確認しました。
{
"Records": [
{
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:EXAMPLE",
"EventSource": "aws:sns",
"Sns": {
"SignatureVersion": "1",
"Timestamp": "1970-01-01T00:00:00.000Z",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"Message": "{\"AlarmName\":\"awsrds-app-High-DB-Connections\",\"AlarmDescription\":\"Alarm when CPU exceeds 50 percent\",\"AWSAccountId\":\"123456789123\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: 1 datapoint (10.0) was greater than or equal to the threshold (10.0).\",\"StateChangeTime\":\"2016-07-24T22:05:19.737+0000\",\"Region\":\"US West - Oregon\",\"OldStateValue\":\"OK\",\"Trigger\":{\"MetricName\":\"DatabaseConnections\",\"Namespace\":\"AWS/RDS\",\"Statistic\":\"AVERAGE\",\"Unit\":null,\"Dimensions\":[{\"name\":\"DBInstanceIdentifier\",\"value\":\"app\"}],\"Period\":300,\"EvaluationPeriods\":1,\"ComparisonOperator\":\"GreaterThanOrEqualToThreshold\",\"Threshold\":10.0}}",
"MessageAttributes": {
"Test": {
"Type": "String",
"Value": "TestString"
},
"TestBinary": {
"Type": "Binary",
"Value": "TestBinary"
}
},
"Type": "Notification",
"UnsubscribeUrl": "EXAMPLE",
"TopicArn": "arn:aws:sns:EXAMPLE",
"Subject": "TestInvoke"
}
}
]
}
SNSの設定
CloudWatchからLambdaを実行できるようにするためには、
SNSトピックを作成して、そのトピックに作成したLambda関数を登録する必要があります。
・トピックとは
メッセージを送信し通知を受信する通信チャネルです。
通知を送りたいクライアント(Publisher)と通知を受け取りたいクライアント(Subscriber)の間に入る概念をトピックといいます。
Publisherはトピックに対してメッセージを送信します。Subscriberはトピックを購読(Subscription)します。
AWSのサービスからSNSを選択し、SNSダッシュボードで「トピックの作成」をクリックします。
トピック名を入力して作成ボタンをクリックします。
��今回はトピック名を「lambdaToSlack」にしました)
トピックが作成できたら、次はサブスクリプションを作成します。
下記に設定したら「サブスクリプションを作成」ボタンをクリックします。
CloudWatchのアラームを作成
AWSのサービスからCloudWatchを選択し、CloudWatchのアラームの画面で「アラームの作成」ボタンをクリックします。
メトリクスの選択で、Lambdaメトリクスから「呼び出し(Invocations)」を選択し、次へボタンをクリックします。
アラーム名に適当な名前を入れ、アラーム定義で閾値を「≧ 1」、
アクションの通知の送信先を作成したSNSトピック名に設定して「アラームの作成」ボタンをクリックします。
今回、メトリクスやアラームの定義で細かい設定はしていないのですが、
細かく設定することでより高度な監視ができるようになるようです。
下記のサイトに詳しく書いてありました。
CloudWatchのアラーム作成後、slackに通知がきました。
やってみた感想
Lambdaでハンドラの設定値がpythonのファイル名と合っていなくて関数が実行できず、少しハマりました。
大文字小文字の誤りだったのですが、今後はよく注意しようと思います。
テストイベントの作成方法がよくわからず、ネットの情報をそのままコピペをしてしまいましたが、
果たして合っているのか疑問が残りました。調べるか有識者に聞くかして、疑問を解消したいと思います。
CloudWatchは細かい設定ができそうだったので、色々なケースに対応できるようもっとよく理解したいと思いました。
AWS全般にいえることかもしれませんが、SNSのトピックの設定や実行権限など必要な設定が多いので、
実行できないときは設定の見直しをしたほうがよさそうだと思いました。
本当はAWSの料金を通知させたかったので、slack通知のアイコンをお金の絵文字にしています。
Lambdaを使ったslackの通知はできたので、次は定期的に実行させたり、AWSの料金を通知させるといったことをやってみたいと思います。
Thank you for reading.
返信削除I'm very happy to serve you!
I will keep updating my blog in the future.