一定額超えたら、Slack に通知するように設定します。
マイ請求ダッシュボードの AWS Budgets から『予算を作成』をクリックします。
『予算タイプの選択』を『コスト予算』にします。
AWS チャットボットのアラートというのを設定しないと、Slack 通知ができないので、次はそちらを設定します。
AWS Chatbot にアクセスします。
チャットクライアントを Slack に設定し、自身の作成した Slack のワークスペースと連携します。
連携が終わると、以下の画面に遷移します。
新しいチャンネルを設定するためには既に作成されたSNSが必要なので、次はSNSを設定します。
Amazon Simple Notification Service にアクセスします。
sns/v3/home?region=ap-northeast-1#/homepage
トピック名を適当に作成し、次のステップに移ります。
SNS は AWS Budgets から実行したいので、アクセスポリシーを修正します。
デフォルトでは以下のようになってます (メソッドを『高度な』に変えると JSON エディタが開きます)。
1{2"Version": "2008-10-17",3"Id": "__default_policy_ID",4"Statement":5[6{7"Sid": "__default_statement_ID",8"Effect": "Allow",9"Principal": { "AWS": "*" },10"Action":11[12"SNS:Publish",13"SNS:RemovePermission",14"SNS:SetTopicAttributes",15"SNS:DeleteTopic",16"SNS:ListSubscriptionsByTopic",17"SNS:GetTopicAttributes",18"SNS:Receive",19"SNS:AddPermission",20"SNS:Subscribe",21],22"Resource": "arn:aws:sns:ap-northeast-1:<マイアカウントの番号>:<トピック名>",23"Condition":24{ "StringEquals": { "AWS:SourceOwner": "<マイアカウントの番号>" } },25},26],27}
AWS Budgets から SNS を push するように、これを Statement に追加します。
1{2"Sid": "AWSBudgets-notification-1",3"Effect": "Allow",4"Principal": { "Service": "budgets.amazonaws.com" },5"Action": "SNS:Publish",6"Resource": "arn:aws:sns:ap-northeast-1:<マイアカウントの番号>:<トピック名>",7}
最終的にこうなります。
1{2"Version": "2008-10-17",3"Id": "__default_policy_ID",4"Statement":5[6{7"Sid": "AWSBudgets-notification-1",8"Effect": "Allow",9"Principal": { "Service": "budgets.amazonaws.com" },10"Action": "SNS:Publish",11"Resource": "arn:aws:sns:ap-northeast-1:<マイアカウントの番号>:<トピック名>",12},13{14"Sid": "__default_statement_ID",15"Effect": "Allow",16"Principal": { "AWS": "*" },17"Action":18[19"SNS:Publish",20"SNS:RemovePermission",21"SNS:SetTopicAttributes",22"SNS:DeleteTopic",23"SNS:ListSubscriptionsByTopic",24"SNS:GetTopicAttributes",25"SNS:Receive",26"SNS:AddPermission",27"SNS:Subscribe",28],29"Resource": "arn:aws:sns:ap-northeast-1:<マイアカウントの番号>:<トピック名>",30"Condition":31{ "StringEquals": { "AWS:SourceOwner": "<マイアカウントの番号>" } },32},33],34}
トピックを作成したら、ARN をコピーしておきます。
1arn:aws:sns:ap-northeast-1:<アカウント番号>:<SNSトピック名>
CloudWatch のログを有効化しておきます。
Slack チャンネルはパブリックにしておきます。
アクセス権限も適当に選択しておきます。
通知オプションは SNS で作成したものを使います。
SNS の設定で、作成した ARN を貼り付けます。
予算を 1$にし、アラート通知を 1%にすれば、通知のテストができます。
こんな感じで Slack に通知がきます (AWS は自動でメンバーに追加されます)。
これで、AWS Chatbot が SNS の push を検知して、Slack に通知を送るようになります。
先に Lambda を作ります。
Node.jsで作成します。
SNS でトリガーして、Lambda が動くようにします。
Lambda に何が来るかわからないので、console.log で確認してみます。
index.js1exports.handler = async event => {2console.log("AWS Budgets Test")3console.log(event)4console.log(JSON.stringify(event))5// TODO implement6const response = {7statusCode: 200,8body: JSON.stringify("Hello from Lambda!"),9}10return response11}
CloudWatch では以下が返ってきました。
大雑把な値を知りたい場合は、AWS Budgets で設定する予算名に値段を入れておくと良さそうです (Sns の Subject で取れます)。
詳細を取り出したい場合は、Message を使います。/n とか入ってますが、LINE がいい感じに整形するので、そのまま投げても大丈夫です。
1{2"Records":3[4{5"EventSource": "aws:sns",6"EventVersion": "1.0",7"EventSubscriptionArn": "xxx",8"Sns":9{10"Type": "Notification",11"MessageId": "xxx",12"TopicArn": "xxxx",13"Subject": "AWS Budgets: <AWS Budgetsで設定した予算名> has exceeded your alert threshold",14"Message": "xxxxxxxx",15"Timestamp": "2020-11-02T15:43:38.009Z",16"SignatureVersion": "1",17"Signature": "xxxxx",18"SigningCertUrl": "xxxx",19"UnsubscribeUrl": "xxxx",20"MessageAttributes": {},21},22},23],24}
どちらにせよ、以下で Subject と Message が取れることがわかります。
index.js1exports.handler = async event => {2console.log("AWS Budgets Subject")3console.log(event.Records[0].Sns.Subject)4console.log("AWS Budgets Contents")5console.log(event.Records[0].Sns.Message)6// TODO implement7const response = {8statusCode: 200,9body: JSON.stringify("Hello from Lambda!"),10}11return response12}
上記の CloudWatch の結果をコピーし、テストをクリックします (SNS のテンプレートを選んで使っても大丈夫です!)。
新しいテストイベントを作成し、先ほどの CloudWatch の結果を貼り付けます。
再度テストをクリックすると、テストが実行され、結果が見れます。
developer コンソールにログインします。
https://developers.line.biz/console/
ログインして、Provider を作成します。
LINE Bot に予算アラートを喋らせるので、Messaging API を選びます。
カテゴリなどを適当に設定しておきます。
設定が終わると、この画面になります。
Basic Setting の一番下にシークレットアクセスキーとユーザー ID、Messaging API にアクセスキーがあるので、控えておきます。
ローカルの適当なディレクトリで、以下のコマンドを実行します。
1$ touch index.js2$ yarn init3$ yarn add @line/bot-sdk
ディレクトリ構成はこんな感じです。
1lambda_test2├── apis3| └── line.js4├── index.js5├── package.json6├── node_modules/7└── yarn.lock
line.js は次のようにします。
apis/line.js1"use strict"23const line = require("@line/bot-sdk")4const configs = {}56if (process.env.LINE_CHANNEL_TOKEN && process.env.LINE_CHANNEL_SECRET) {7configs.channelAccessToken = process.env.LINE_CHANNEL_TOKEN8configs.channelSecret = process.env.LINE_CHANNEL_SECRET9} else {10console.warn("LINE Channel Token or Secret Token is missing...")11}1213module.exports = new line.Client(configs)
index.js はこうします。
index.js1"use strict"23exports.handler = async event => {4const lineClient = require("../images/apis/line")5console.log("AWS Budgets Subject")6await lineClient.pushMessage(process.env.USER_ID, {7type: "text",8text: event.Records[0].Sns.Subject,9})10console.log("AWS Budgets Contents")11await lineClient.pushMessage(process.env.USER_ID, {12type: "text",13text: event.Records[0].Sns.Message,14})1516const response = {17statusCode: 200,18body: JSON.stringify("Hello from Lambda!"),19}20return response21}
作成した以下のファイルを zip 化し、Lambda にデプロイします。
1lambda_test2├── apis3| └── line.js4├── index.js5├── package.json6├── node_modules/7└── yarn.lock
先ほどのように Lambda でテストをしたり、適当な予算を作ってみたりすると、LINE にもアラートが飛ぶようになります。
これで、設定した予算よりも利用料が超えそうになると、Slack と LINE にメッセージが飛ぶようになりました。