はじめに
株式会社フォトラクションのSREをしている河野です。 フォトラクションのSREグループではAWS管理を任されているので、コスト監視を導入してみました。
やりたいこと
やること
- AWSのマネコンでChatbotを開きSlackにアクセス権限をリクエストして承認する(この記事では省略します。マネコンからChatbotのページを開けばわかると思います)
- terraform apply
- SlackからAWSリソースを参照してみる
- 利用料金が超えるまで待つ
terraformのawsccというproviderを使用します。 terraformの内容と手順はこちらの記事を参考に、弊社の状況に合わせて修正を加えています。 AWS Budget notifications with AWS Chatbot, Slack and Terraform
Terraform
provider.tf
providerはawsに加えてAWS Cloud Control APIを使用するためのproviderであるawsccも追加します。chatbotのリソースはこちらのproviderを使用して作成します。
provider "aws" {
region = var.region
}
provider "awscc" {
region = var.region
}
resources.tf
locals {
account_alias = data.aws_iam_account_alias.current.account_alias
}
resource "aws_sns_topic" "aws_budget_alerts" {
name = "${local.account_alias}-aws-budget-alerts"
}
resource "aws_sns_topic_policy" "default" {
arn = aws_sns_topic.aws_budget_alerts.arn
policy = data.aws_iam_policy_document.sns_topic_policy.json
}
# AWS Budgetsで予算とSNSへの通知設定
resource "aws_budgets_budget" "monthly" {
name = "budget-monthly"
budget_type = "COST"
limit_amount = var.limit_amount
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = var.threshold
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_sns_topic_arns = [aws_sns_topic.aws_budget_alerts.arn]
}
}
resource "aws_iam_policy" "chatbot_role_policy" {
name = "chatbot-policy"
policy = data.aws_iam_policy_document.chatbot_policy.json
}
resource "aws_iam_role" "chatbot_role" {
name = "chatbot-role"
assume_role_policy = data.aws_iam_policy_document.chatbot_assume_role.json
}
resource "aws_iam_role_policy_attachment" "chatbot_policy_attach" {
role = aws_iam_role.chatbot_role.name
policy_arn = aws_iam_policy.chatbot_role_policy.arn
}
resource "aws_iam_role_policy_attachment" "chatbot_policy_attach_read_only" {
role = aws_iam_role.chatbot_role.name
policy_arn = data.aws_iam_policy.read_only_access.arn
}
# chatbotとSlackの連携の設定とSNSのサブスクライブ設定
resource "awscc_chatbot_slack_channel_configuration" "aws_budget_alerts_slack" {
configuration_name = "slack_aws_budget_alerts"
iam_role_arn = aws_iam_role.chatbot_role.arn
slack_channel_id = var.slack_channel_id
slack_workspace_id = var.slack_workspace_id
sns_topic_arns = [aws_sns_topic.aws_budget_alerts.arn]
logging_level = "ERROR"
}
awscc_chatbot_slack_channel_configurationでいろいろしてますので、やっぱり公式を参照するといいと思います。 awscc_chatbot_slack_channel_configuration
こちらのterraformでは、chatbot-roleに対して後述するdata.tfで取得したReadOnlyAccessのポリシーを付与しています。 slackからChatOpsするために権限を広く付与しているため、実際には適切な権限を付与するようにご注意ください。 (参考)SlackとAWS ChatbotでChatOpsをやってみよう
data.tf
data "aws_iam_account_alias" "current" {}
data "aws_iam_policy" "read_only_access" {
name = "ReadOnlyAccess"
}
data "aws_iam_policy_document" "chatbot_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["chatbot.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "chatbot_policy" {
statement {
actions = [
"sns:Subscribe"
]
resources = [
"*"
]
}
}
data "aws_iam_policy_document" "sns_topic_policy" {
statement {
actions = [
"sns:Publish"
]
principals {
type = "Service"
identifiers = ["budgets.amazonaws.com"]
}
resources = [
aws_sns_topic.aws_budget_alerts.arn
]
}
}
複数のAWSアカウントからの通知を想定してアカウントのエイリアスを取得しています。
variables.tf
variable "region" {
type = string
}
variable "slack_channel_id" {
type = string
}
variable "slack_workspace_id" {
type = string
}
variable "threshold" {
description = "予算に対して何%で通知するか"
type = number
}
variable "limit_amount" {
description = "利用料金($)の予算、なぜかstringらしい"
type = string
}
SlackからAWSリソースを参照してみる
awsをChannelに追加してから@awsでawsに話しかけるとコマンドが実行できます。
# 例 @aws sns list-topics
取れました。ARNにAWSが主張しているのはご愛嬌。(:aws:でEmojiが登録されているためです)

予算アラート通知
少ない予算ですぐに通知が来るようにして通知結果を確認しました。

まとめ
terraformで予算アラートを設定してみました。マネコンからの操作があるのはどうしようもなかったですが、割と簡単に予算通知を入れることができました。 AWSアカウントが増えすぎると結局管理が大変になるのでAWS Organizationsなどのサービスも検討していこうと思います。