AWS Budgetsの請求アラートをAWS ChatbotでSlackに通知する構成をCDKで作る
吉川@広島です。
掲題の通りです。早速いきましょう。
下記が大変参考になりました。
- CloudFormation一撃で予算アラート(Budgets)を作成してみた | DevelopersIO
- CloudWatch AlarmをAWS ChatbotからSlack通知する仕組みをCDKで作ってみた | DevelopersIO
環境
- npm 7.23.0
- typescript 4.4.3
- aws-cdk 1.122.0
Chatbotの下準備
CloudWatch AlarmをAWS ChatbotからSlack通知する仕組みをCDKで作ってみた | DevelopersIO
こちらの「AWS Chatbot の Workspace Configuration を GUI から作成」の手順を実施します。
CDKプロジェクトを構築
aws-cdk cliで雛形を作ります。
mkdir billing-alarm cd billing-alarm npx aws-cdk init -l typescript
コード
// lib/billing-alarm-stack.ts import * as cdk from '@aws-cdk/core' import * as sns from '@aws-cdk/aws-sns' import * as iam from '@aws-cdk/aws-iam' import * as subscriptions from '@aws-cdk/aws-sns-subscriptions' import * as chatbot from '@aws-cdk/aws-chatbot' import * as budgets from '@aws-cdk/aws-budgets' export interface MyProps { readonly slackChannelId: string readonly slackWorkspaceId: string readonly unit: string readonly amount: number readonly threshold: number readonly thresholdType: string readonly timeUnit: string } export class BillingAlarmStack extends cdk.Stack { constructor( scope: cdk.Construct, id: string, props?: cdk.StackProps & MyProps ) { super(scope, id, props) /** * SNS */ const topic = new sns.Topic(this, 'billing-alarm-topic') topic.addToResourcePolicy( new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['SNS:Publish'], principals: [new iam.ServicePrincipal('budgets.amazonaws.com')], resources: [topic.topicArn], }) ) /** * Chatbot */ const chatbotRole = new iam.Role(this, 'billing-alarm-chatbot-role', { assumedBy: new iam.ServicePrincipal('sns.amazonaws.com'), }) chatbotRole.addToPolicy( new iam.PolicyStatement({ resources: ['*'], actions: ['cloudwatch:*'], }) ) new chatbot.CfnSlackChannelConfiguration( this, 'billing-alarm-slack-channel-config', { configurationName: 'billing-alarm-slack-channel-config', iamRoleArn: chatbotRole.roleArn, slackChannelId: props!.slackChannelId, slackWorkspaceId: props!.slackWorkspaceId, snsTopicArns: [topic.topicArn], loggingLevel: 'ERROR', } ) /** * Budgets */ new budgets.CfnBudget(this, 'billing-alarm-budget', { budget: { budgetType: 'COST', timeUnit: props!.timeUnit, budgetLimit: { unit: props!.unit, amount: props!.amount, }, }, notificationsWithSubscribers: [ { notification: { comparisonOperator: 'GREATER_THAN', notificationType: 'ACTUAL', threshold: props!.threshold, thresholdType: props!.thresholdType, }, subscribers: [ { // SNSに通知する subscriptionType: 'SNS', address: topic.topicArn, }, ], }, ], }) } }
// bin/billing-alarm.ts #!/usr/bin/env node import 'source-map-support/register' import * as cdk from '@aws-cdk/core' import { BillingAlarmStack } from '../lib/billing-alarm-stack' const app = new cdk.App() new BillingAlarmStack(app, 'billing-alarm-stack', { slackWorkspaceId: process.env.SLACK_WORKSPACE_ID!, slackChannelId: process.env.SLACK_CHANNEL_ID!, unit: process.env.UNIT ?? 'USD', amount: process.env.AMOUNT != null ? Number(process.env.AMOUNT) : 10, threshold: process.env.THRESHOLD != null ? Number(process.env.THRESHOLD) : 100, thresholdType: process.env.THRESHOLD_TYPE ?? 'PERCENTAGE', timeUnit: process.env.TIME_UNIT ?? 'MONTHLY', })
環境変数の設定
環境変数から設定値を注入するようにしています。
例えば次のようにすると
- 月額課金が10ドルを超えるとアラート発生
となります。
# .env SLACK_WORKSPACE_ID: 'xxxxxxxx' # SlackワークスペースIDを設定 SLACK_CHANNEL_ID: 'xxxxxxxx' # SlackチャンネルIDを設定 UNIT: 'USD' # 通貨単位 AMOUNT: 10 # 課金額 THRESHOLD: 100 # しきい値 THRESHOLD_TYPE: 'PERCENTAGE' # しきい値の単位 TIME_UNIT: 'MONTHLY' # 期間単位(月毎、日毎など)