GCPの予算アラート設定からBigQuery課金エクスポート+データポータル連携までをOpenTofuで構築してみた

GCPの予算アラート設定からBigQuery課金エクスポート+データポータル連携までをOpenTofuで構築してみた

GCPプロジェクトのコスト管理を、gcloud CLIでの予算アラート設定、BigQueryへの課金データエクスポート、OpenTofuでのビュー作成の3段階で構築しました。予測ベースのしきい値設計やフラットビューによるLooker Studio連携のポイントも紹介します。
2026.08.01

はじめに

GCPプロジェクトを運用していて、「今月いくら使ってるんだろう?」「急にコストが跳ね上がったら気づけるのか?」と不安になったことはありませんか?

Cloud Consoleの課金レポートは便利ですが、しきい値を超えたら通知が欲しい、データポータルで他のダッシュボードと一緒にコストも可視化したい、というニーズが出てきました。

この記事では、以下の3つを実際にやってみました。

  1. gcloud CLIで予算アラートを設定(しきい値の設計含む)
  2. BigQueryへの課金データエクスポートを有効化
  3. OpenTofuでBigQueryビューを作成し、データポータルのデータソースとして利用

gcp-billing-budget-alert-bigquery-looker-studio-opentofu-architecture

前提・環境

  • GCPプロジェクト: 作成済み
  • gcloud CLI: インストール・認証済み
  • OpenTofu: v1.12(brew install opentofuでインストール)
  • 請求先アカウント: 組織管理(Billing Account IDが必要)

予算アラートの設定

現状のコストを把握する

まず、予算額を決めるために現状のコストを確認します。Cloud Console の お支払い → レポート が最も手軽です。

今回のプロジェクトの場合、主なコスト構成は以下でした。

サービス 月額概算 備考
Cloud Run 約¥3,500 min-instances=1で常時起動
Vertex AI 約¥100 RAGクエリ(月100件程度)
Cloud Storage 約¥10 KBファイル保管
その他 約¥50 Cloud Build、Schedulerなど
合計 約¥5,000

Billing Account IDの確認

予算作成にはBilling Account IDが必要です。Cloud Console の お支払い → アカウント管理 から確認できます。

CLIで確認する場合は以下のコマンドです(Billing Account Viewer以上の権限が必要)。

gcloud billing accounts list

権限がない場合はConsoleから確認するか、組織管理者に問い合わせてください。

Billing Budget APIの有効化

予算の作成には Cloud Billing Budget API が必要です。

gcloud services enable billingbudgets.googleapis.com --project=YOUR_PROJECT_ID

しきい値の設計

予算アラートのしきい値は以下のように設計しました。

しきい値 種別 金額目安 目的
50% 実績ベース ¥10,000 月半ばのサニティチェック
90% 実績ベース ¥18,000 予算上限に接近
100% 予測ベース ¥20,000 月末超過の早期警告
120% 実績ベース ¥24,000 異常検知

ポイントは 100%を予測ベース(forecasted-spend にしていること。実績ベースだと超過してから通知が来ますが、予測ベースなら月の途中で「このペースだと超えそう」と警告してくれます。

gcp-billing-budget-alert-bigquery-looker-studio-opentofu-threshold

予算の作成

gcloud billing budgets create \
  --billing-account="YOUR_BILLING_ACCOUNT_ID" \
  --display-name="your-project monthly" \
  --budget-amount=20000JPY \
  --filter-projects="projects/YOUR_PROJECT_ID" \
  --threshold-rule=percent=0.5,basis=current-spend \
  --threshold-rule=percent=0.9,basis=current-spend \
  --threshold-rule=percent=1.0,basis=forecasted-spend \
  --threshold-rule=percent=1.2,basis=current-spend

予算額は現状コストの3〜4倍程度に設定するのがおすすめです。今回は月額約¥5,000に対して¥20,000としました。低すぎると頻繁にアラートが飛んで無視されがちに、高すぎると異常を検知できません。

注意点:

  • 予算アラートは通知のみで、自動的にリソースを停止したりはしません
  • 課金データには数時間のラグがあるため、リアルタイムの監視には向きません
  • 自動停止が必要な場合は、Pub/Sub + Cloud Functionsで対応できます

BigQueryへの課金データエクスポート

なぜエクスポートが必要か

Cloud Consoleの課金レポートでも十分な情報が見られますが、BigQueryにエクスポートすることで以下のメリットがあります。

  • データポータルでの可視化: 他の運用ダッシュボードと統合できる
  • SQLでの分析: SKU別、日別、リージョン別など自由に集計できる
  • 長期保存: Consoleのレポートは期間が限られるが、BigQueryなら好きなだけ保持できる

エクスポート用データセットの作成

bq mk --dataset --location=US YOUR_PROJECT_ID:billing_export

エクスポートの有効化

この手順はCloud Consoleから行います(CLIコマンドは提供されていません)。また、Billing Account Administrator権限が必要です。

  1. Cloud Console → お支払い → レポート → 課金データのエクスポート
  2. 「標準の使用料金」の設定を編集
  3. プロジェクトとデータセット(billing_export)を選択して保存

SCR-20260727-peob (1)

データの到着を確認

エクスポートを有効化すると、当月+前月分のデータがバックフィルされます(最大5日かかる場合があります)。

bq ls YOUR_PROJECT_ID:billing_export

テーブル名は gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXXX のような形式で作成されます。

データが到着したら、簡単なクエリで確認してみましょう。

SELECT
  invoice.month AS month,
  service.description AS service,
  ROUND(SUM(cost), 0) AS total_cost_jpy
FROM `YOUR_PROJECT_ID.billing_export.gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXXX`
GROUP BY 1, 2
HAVING total_cost_jpy != 0
ORDER BY 1 DESC, 3 DESC

OpenTofuでBigQueryビューを作成

なぜIaCでビューを管理するか

データポータルで課金データを可視化する際、生のエクスポートテーブルをそのまま使うこともできますが、ビューを挟むことで以下のメリットがあります。

  • credits(クレジット)を考慮したnet_costを計算できる
  • invoice_monthをDATE型にパースして、データポータルでの時系列チャートが簡単になる
  • 参照期間を制限して、不要な過去データのスキャンコストを抑えられる

Google公式の terraform-google-billing-dashboard モジュールも同様のアプローチを採用しています。

アプローチ: フラットビュー vs プリアグリゲーション

最初はサービス別月次集計、日次トレンドなど、目的別に複数のプリアグリゲーションビューを作ろうとしました。しかし、Google公式テンプレートを参考にしたところ、1つのフラットビューで計算フィールドを追加し、集計はデータポータル側に任せるアプローチの方が良いとわかりました。

アプローチ メリット デメリット
プリアグリゲーション(複数ビュー) クエリが軽い データポータルでの柔軟性が低い
フラットビュー(1つ) データポータルで自由にスライス&ダイス クエリ量はやや増える

データポータルはドラッグ&ドロップでディメンションやメトリクスを自由に変更できるため、フラットビューの方が圧倒的に使いやすいです。

Terraform構成

OpenTofuはTerraformと同じHCL構文を使うため、terraform ブロックやプロバイダ定義はそのまま流用できます。tofu init / tofu plan / tofu apply で実行するだけです。

infra/billing-dashboard/main.tf
terraform {
  required_version = ">= 1.5"

  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 6.0"
    }
  }
}

provider "google" {
  project = var.project_id
}

resource "google_bigquery_dataset" "billing_dashboard" {
  dataset_id = var.dataset_id
  project    = var.project_id
  location   = var.location

  labels = {
    purpose = "billing-dashboard"
  }
}

resource "google_bigquery_table" "billing_view" {
  dataset_id = google_bigquery_dataset.billing_dashboard.dataset_id
  table_id   = "billing_view"
  project    = var.project_id

  view {
    use_legacy_sql = false
    query          = <<-SQL
      SELECT
        *,
        COALESCE((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0) AS credits_sum_amount,
        cost + COALESCE((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0) AS net_cost,
        PARSE_DATE('%Y%m', invoice.month) AS invoice_month
      FROM `${var.billing_export_table}`
      WHERE _PARTITIONDATE > DATE_SUB(CURRENT_DATE(), INTERVAL ${var.lookback_months} MONTH)
        -- 課金エクスポートには請求アカウント配下の全プロジェクトが含まれるため、対象プロジェクトのみに絞る
        AND project.id = '${var.project_id}'
    SQL
  }

  deletion_protection = false
}
infra/billing-dashboard/variables.tf
variable "project_id" {
  description = "GCP project ID"
  type        = string
  default     = "YOUR_PROJECT_ID"

  validation {
    condition     = can(regex("^[a-z][a-z0-9-]{4,28}[a-z0-9]$", var.project_id))
    error_message = "project_id must be a valid GCP project ID (6-30 chars, lowercase, digits, hyphens)."
  }
}

variable "billing_export_table" {
  description = "Fully qualified billing export table ID"
  type        = string
  default     = "YOUR_PROJECT_ID.billing_export.gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXXX"
}

variable "dataset_id" {
  description = "BigQuery dataset for billing dashboard views"
  type        = string
  default     = "billing_dashboard"
}

variable "location" {
  description = "BigQuery dataset location"
  type        = string
  default     = "US"
}

variable "lookback_months" {
  description = "Number of months of billing data to include"
  type        = number
  default     = 12
}

ビューのポイント

  • credits_sum_amount: GCPクレジット(無料トライアル、SUD割引など)の合計額
  • net_cost: クレジット適用後の実質コスト。ダッシュボードではこちらを使う
  • invoice_month: YYYYMM文字列をDATE型にパースし、データポータルの時系列軸で使えるようにする
  • lookback_months: パーティションプルーニングで不要なデータのスキャンを抑制
  • project.idフィルター: 課金エクスポートテーブルには請求アカウント配下の全プロジェクトのデータが含まれるため、project.idでフィルターしないと他プロジェクトのコストが混入する。var.project_idで対象プロジェクトのみに絞っている

.gitignoreの設定

Terraformの生成ファイルをリポジトリに含めないよう、.gitignoreに以下を追加します。

.gitignore
# OpenTofu / Terraform
**/.terraform/
*.tfstate
*.tfstate.backup
*.tfplan

.tfファイル(ソースコード)と.terraform.lock.hcl(プロバイダのバージョンロック)はコミットしてください。tfstateにはリソースIDなどの情報が含まれるため、リポジトリには入れないのが鉄則です。

デプロイ

cd infra/billing-dashboard
tofu init
tofu plan
tofu apply

tofu plan で作成されるリソースを確認してから tofu apply を実行します。

Plan: 2 to add, 0 to change, 0 to destroy.

Outputs:
  dataset_id = "billing_dashboard"
  view_id    = "billing_view"

データポータルでの利用

ビューが作成されたら、既存のデータポータルレポートに新しいデータソースとして追加します。

  1. データポータルでレポートを開く
  2. リソース → 追加済みのデータソースの管理 → データソースを追加
  3. BigQuery → プロジェクト → billing_dashboardbilling_view を選択
  4. 新しいページを追加して、チャートを作成

おすすめのチャート構成:

チャート種類 ディメンション 指標 用途
スコアカード net_cost (SUM) 当月合計コスト
時系列グラフ invoice_month net_cost (SUM) 月次コスト推移
棒/円グラフ service.description net_cost (SUM) サービス別内訳
テーブル sku.description net_cost (SUM) SKU別詳細

まとめ

GCPのコスト管理を3段階で構築しました。

  • 予算アラート: gcloud CLIで¥20,000/月の予算を設定。50%/90%/100%(予測)/120%の4段階で通知
  • 課金データエクスポート: BigQueryにエクスポートし、SQLで自由に分析可能に
  • OpenTofuでビュー管理: Google公式テンプレートを参考に、フラットビューでnet_costinvoice_monthを追加。データポータルで自由にスライス&ダイスできる構成に

予算アラートは通知のみで自動停止はしないこと、課金データには数時間のラグがあること、この2点は忘れずに。自動停止が必要な場合はPub/Sub + Cloud Functionsの追加構築が必要です。

コスト管理は後回しにしがちですが、IaCで管理しておけばプロジェクトが増えても同じ構成を横展開できます。まずは予算アラートの設定から始めてみてはいかがでしょうか。

この記事をシェアする

関連記事