この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
吉川@広島です。
掲題の通りです。早速いきましょう。
下記が大変参考になりました。
- 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' # 期間単位(月毎、日毎など)