GCPのコスト(予算)アラートをCloudfunctionsを使って、Slackに通知してみた(Terraform)
記事の内容
GCPのコストアラート(予算設定)をSlackに通知する方法を紹介します。(Terraformを利用します。)
記事を読むと得られるもの
- GCPのコストアラートの実装方法
- TerraformでCloudFunctionsを作成する方法
対象読者
- GCP利用者
記事の長さ
2分で読めます
Cost Alertを設定する
main.tf
resource "google_billing_budget" "this" {
billing_account = var.billing_account
display_name = "Monthly Cost"
budget_filter {
credit_types_treatment = "INCLUDE_ALL_CREDITS"
projects = ["projects/${var.project_number}"]
}
amount {
specified_amount {
units = "100"
}
}
threshold_rules {
threshold_percent = 0.5
}
threshold_rules {
threshold_percent = 1.0
}
}
上記Terraformファイルにて、予算アラートを作成できます。
Pub/Subを予算アラートに設定する
次に、アラートの上限に使用額が達した際にトリガーされるPub/Subを作成して、それを予算アラートに紐づけます。
先ほど作成したmain.tf
ファイルを以下のように変更して、Terraform applyを実行してください。
main.tf
resource "google_billing_budget" "this" {
billing_account = var.billing_account
display_name = "Monthly Cost"
budget_filter {
credit_types_treatment = "INCLUDE_ALL_CREDITS"
projects = ["projects/${var.project_number}"]
}
amount {
specified_amount {
units = "100"
}
}
threshold_rules {
threshold_percent = 0.5
}
threshold_rules {
threshold_percent = 1.0
}
all_updates_rule {
pubsub_topic = "projects/${var.project_id}/topics/${google_pubsub_topic.this.name}"
}
depends_on = [
google_pubsub_topic.this
]
}
resource "google_pubsub_topic" "this" {
project = var.project_id
name = "billing-alerts"
}
Slack Appを作成する
次に、Slackに対して、通知を行うためにSlack Appを作成します。
こちらのURLにアクセスして、Create New App
から、Slack通知を行いたいWorkspaceに対して、Slack Appを作成してください。
Slack上で、Slack Appを追加する
Slack Appの作成が完了したら、通知を行いたいSlackチャンネルをSlackのアプリケーションで開き、Integrations
タブから、今作成してSlack AppをSlackチャンネルに追加してください。
OAuthにチャット書き込みの権限を付与する
Slack Appの作成とSlackチャンネルへの追加が完了したら、そのSlack Appの管理画面のサイドバーからOAuth & Permissions
を選択し、Add an OAuth Scope
ボタンをクリックし、chat:write
を選択します。
これで、OAuth Tokenを使った外部アプリケーションからSlackへの書き込みが可能になります。
Oauth Tokenを取得する
Slack Appの作成とSlackチャンネルへの追加が完了したら、そのSlack Appの管理画面のサイドバーからOAuth & Permissions
を選択し、Bot User OAuth Token
の値をコピーします。(xoxb-から始まる文字列です)
このTokenを利用して、CloudFunctionsからSlackに通知を行うため、どこかにメモしておいてください。
Cloud Functionsを作成する
Pub/Subから通知を受け取り、Slackにメッセージを送るCloudFunctionsを作成します。
CloudFunctions上で動作するnode.jsのファイルを作成する
Cloud Functionsでは、PythonやNodejsなど、さまざまなプログラミング言語が動作します。
今回は、node.jsを使って、Cost Alertの通知をSlackにPOSTするプログラムを書きます。
index.js
const slack = require('slack');
const BOT_ACCESS_TOKEN = process.env.BOT_ACCESS_TOKEN || '';
const CHANNEL = process.env.SLACK_CHANNEL || '';
exports.notifySlack = async pubsubEvent => {
const pubsubAttrs = pubsubEvent.attributes;
const pubsubData = Buffer.from(pubsubEvent.data, 'base64').toString();
if (pubsubData.costAmount > pubsubData.budgetAmount) {
await slack.chat.postMessage({
token: BOT_ACCESS_TOKEN,
channel: CHANNEL,
text: `The cost of ${pubsubData.budgetDisplayName} has exceeded the budget`,
});
return 'Slack notification sent successfully';
} else {
return 'The cost is within the budget range';
}
};
package.json
{
"name": "cloud-functions-billing",
"private": "true",
"version": "0.0.1",
"description": "Examples of integrating Cloud Functions with billing",
"main": "index.js",
"engines": {
"node": ">=16.0.0"
},
"dependencies": {
"slack": "^11.0.1"
}
}
※参考 ( https://cloud.google.com/billing/docs/how-to/notify#write-a-cloud-function )
TerraformでCloud Functionsを作成する
先ほど作成したnode.jsのファイルが動作するCloudFucntionsをTerraformで作成します。
cf.tf
data "archive_file" "this" {
type = "zip"
source_dir = "./sources"
output_path = "./sources/functions.zip"
}
resource "google_storage_bucket" "this" {
project = var.project_id
name = "my-bucket-for-test-cost-alert"
location = "ASIA"
storage_class = "STANDARD"
}
resource "google_storage_bucket_object" "this" {
name = "packages/functions.${data.archive_file.this.output_md5}.zip"
bucket = google_storage_bucket.this.name
source = data.archive_file.this.output_path
}
resource "google_cloudfunctions_function" "this" {
project = var.project_id
name = "cost-alert"
runtime = "nodejs18"
source_archive_bucket = google_storage_bucket.this.name
source_archive_object = google_storage_bucket_object.this.name
available_memory_mb = 256
event_trigger {
event_type = "providers/cloud.pubsub/eventTypes/topic.publish"
resource = google_pubsub_topic.this.name
}
entry_point = "notifySlack"
environment_variables = {
BOT_ACCESS_TOKEN = "<BOT Tokenを入力>"
SLACK_CHANNEL = "<通知したいチャンネル名を入力>"
}
}
※BOT TOEKNとSLACK CHANNELを、編集してください(SecretManager等を使った方がいいのですが、今回は割愛します。)
上記、Terraformファイルを実行すると、sources
ディレクトリ配下に配置したnode.jsが稼働するCloudFunctionsが作成されます。
完成
以上でCostAlertをSlackに通知する、Pub/SubとCloudFunctionsが作成できました。
note
勉強法やキャリア構築法など、エンジニアに役立つ記事をnoteで配信しています。
Discussion