以前の記事の、CloudWatchアラーム通知をSlackにする のSAM(Serverless Application Model)で実装した版になります。
SAMを使うことでローカル環境でもテスト実施ができる点とアラームの設定をGit管理できる点がメリットと思います。
0.環境
- Docker
- Python3.7
- aws-cli
- aws-sam-cli
aws configureでcredentialが設定してある前提で進めます。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html#cli-quick-configuration
1. 実装
サンプルは以下に作ってしまいました。
https://github.com/hf7777hi/aws-cloudwatch-alarm-to-slack
ディレクトリ構成は以下の通り。
.
├── README.md
├── event.json <-- SNS event. Lamdaのテストイベントに使うものと同等です。
├── src
│ ├── __init__.py
│ ├── app.py <-- Lambdaのコードはここに書きます。
└── template.yaml <-- SAM Template
ソースは、Lambdaの「設計図の使用」の「cloudwatch-alarm-to-slack-python」のサンプルコードから、slsckの絵文字を使ったメッセージを返すように改造しました。
app.pyの中身を良しなに改造していただくとOKです。もちろん、このままでも動作します。
template.yaml 基本設定
テスト実行する前に環境に合わせて以下を設定してください(yamlでのCloudwatchアラームの設定は後述します)。
SLACK_CHANNEL: cloudwatch-alarm ←通知したいSlackのチャンネル
ENCRYPTED_INCOMING_URL: hogehoge ←暗号化したIncoming Webhook URL
OK: ":ok:" ←OKアラートのSlack絵文字
ALARM: ":ng:" ←NGアラートのSlack絵文字
INSUFFICIENT_DATA: ":question:" ←不足アラートのSlack絵文字
EXCEPTION: ":rotating_light:" ←コードの例外時に通知するSlack絵文字
まず、通知先のSlackの準備と「Incoming Webhooks」の「Webhook URL」の暗号化を行います。
以前投稿した、CloudWatchアラーム通知をSlackにする の Slackの準備 と [IAMのKMSで暗号キーでWebhookURLを暗号化] (https://qiita.com/hf7777hi/items/e0f43f0fb7e2effa0af8#iam%E3%81%AEkms%E3%81%A7%E6%9A%97%E5%8F%B7%E3%82%AD%E3%83%BC%E3%81%A7webhookurl%E3%82%92%E6%9A%97%E5%8F%B7%E5%8C%96) を参考に行ってください。
お金かけたくないので暗号化しないよって方は、暗号キーの作成を飛ばして、src/app.py l.51を以下のように変更して、ENCRYPTED_INCOMING_URLにhttps://以下の平文を設定してください。
token = boto3.client('kms').decrypt(CiphertextBlob=b64decode(os.getenv("ENCRYPTED_INCOMING_URL")))['Plaintext'].decode('utf-8')
↓
token = os.getenv("ENCRYPTED_INCOMING_URL")
2. Lambdaコードのテスト
以下コマンドを実行することで、lambci/lambda:python3.7 イメージのDockerを起動し、コードを実行してくれます。
$ sam local invoke -e event.json
イベント
'Message': '{"AlarmName":"[アラーム名]","AlarmDescription":null,"AWSAccountId":"0000000","NewStateValue":"ALARM","NewStateReason":"Threshold Crossed: 1 datapoint [0.4667407613208132 (16/05/19 13:19:00)] was greater than or equal to the threshold (0.0).",
NewStateValueの値がアラート状態によって以下のように変わります。
- アラート時 : ALARM
- OK時 : OK
- 不足時 : INSUFFICIENT_DATA
これらをevent.jsonのMessageにすればそれぞれのアラートの状態のテストが可能です。
実際にやってみました。(OK, ALARM, INSUFFICIENT_DATA, EXCEPTIONの順です)
こんな感じでSlackに通知されます。
ここまでローカルでLambdaのテスト実行ができたので、src/app.pyの内容をそのまま、LambdaFunctionにコピペして、Lambdaを設定すれば出来上がりにすることも可能です。
3. yamlによるアラームの設定
ここからがメインです。
各設定項目の詳細は公式を確認してください。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html
サンプルとして、ApiGatewayのアラームを設定してみました。
ApiCountAlarm:
Type: AWS::CloudWatch::Alarmproperties-cw-alarm.html
Properties:
Namespace: AWS/ApiGateway
MetricName: Count
Dimensions:
- Name: ApiName
Value: SampleApi
Period: 300
Statistic: Average
AlarmName: Sample
AlarmDescription: Sample
ComparisonOperator: GreaterThanOrEqualToThreshold
Threshold: 0
EvaluationPeriods: 1
TreatMissingData: notBreaching
OKActions:
- !Ref CloudwatchAlarmTopic
AlarmActions:
- !Ref CloudwatchAlarmTopic
InsufficientDataActions:
- !Ref CloudwatchAlarmTopic
適宜設定したいアラームがあればtemplete.yamlに追記してください。
ちなみに、AWSコンソール上からアラームを設定後、アラームの履歴をみるとAWS CloudFormation テンプレートの設定内容がJSONで確認できるのでyaml記載の参考になります。
参考:CloudWatchの再起動アクションをCloudFormationから作成してみた
4. デプロイ
$ aws s3 mb s3://BUCKET_NAME
$ sam package \
--output-template-file packaged.yaml \
--s3-bucket REPLACE_THIS_WITH_YOUR_S3_BUCKET_NAME
$ sam deploy \
--template-file packaged.yaml \
--stack-name cloudwatch-alarm-to-slack \
--capabilities CAPABILITY_IAM
これでCloudFormationが立ち上がり、Lambda、Cloudwatch、SNSが作成されていると思います。
念のため、Lambdaのテストをしておくといいと思います。
テストイベントは、ローカルのテストに使用したものでOKです。
SlackのURLを暗号化した場合は、KMSのキーユーザーにCloudFormationで作成されたロールを許可してください。
以上です。