はじめに

AWS と Terraformをメインに仕事をしていた私が、Google Cloudでの構築案件に入ることになりました。
Google Cloudそのものは多少触ったことがあるものの、IaC(Terraform)でゼロから構築するのはほぼ初めて。

今回はGoogle Cloud Run・Google Cloud NAT・Google Cloud Pub/Subを含む構成をTerraformで構築した経験をもとに、
AWSの経験をベースに、Google CloudをTerraformで構築する際に押さえておきたいポイントを紹介します。

これまでTerraformを書いてきて、これからGoogle Cloudに取り組む方の参考になれば幸いです。

今回の構成概要

外部クライアント
    ↓
Google Cloud Run(サーバーレスコンテナ)
    ↓(VPC経由のアウトバウンド通信)
Google Cloud NAT → インターネット / 外部サービス

+ Google Cloud Pub/Sub(モニタリング連携用)
+ Google Cloud Secret Manager(認証情報の管理)
+ VPC Flow Logs(ネットワーク監査)

構築環境はWSL + VS Code + Claude Code + Terraform v1.13.0です。

最初に押さえておきたい5つの構築ポイント

① サービスを使う前にAPIを有効化する必要がある

Google Cloudは「権限カードを持っていても、使う部屋ごとに受付で鍵を開けてもらう必要があるビル」のイメージ

Google Cloudでは、IAMの権限に加えて、サービスごとにAPIを有効化する必要があります。
これを忘れると「APIが有効化されていません」というエラーで詰まります。

Terraformでは google_project_service で宣言的に管理できます。

resource "google_project_service" "run" {
  service            = "run.googleapis.com"
  disable_on_destroy = false
}

resource "google_project_service" "secretmanager" {
  service            = "secretmanager.googleapis.com"
  disable_on_destroy = false
}

今回使ったサービスで有効化が必要だったもの:

サービス API名
Google Cloud Run run.googleapis.com
Google Cloud Secret Manager secretmanager.googleapis.com
Google Cloud Pub/Sub pubsub.googleapis.com
Google Cloud NAT compute.googleapis.com
VPC Flow Logs logging.googleapis.com

disable_on_destroy = false にしておくのがポイントです。
true(デフォルト)のままだと terraform destroy 時にAPIが無効化され、
他のリソースが依存していた場合に影響が出ます。


② Google CloudのVPC仕様(グローバルスコープ)のポイント

日本全体に1棟のビルを建てて、大阪フロア・東京フロアに分けるイメージ

Google CloudのVPCはグローバルスコープです。
VPC自体はリージョンをまたいで1つで運用でき、サブネットはリージョン単位で作成します。

# Google CloudのVPCはリージョンを指定しない
resource "google_compute_network" "main" {
  name                    = "main-vpc"
  auto_create_subnetworks = false
}

# サブネットはリージョンを指定する
resource "google_compute_subnetwork" "main" {
  name          = "main-subnet"
  region        = "asia-northeast1"
  network       = google_compute_network.main.id
  ip_cidr_range = "10.0.0.0/24"

  log_config {
    aggregation_interval = "INTERVAL_5_SEC"
    flow_sampling        = 0.5
    metadata             = "INCLUDE_ALL_METADATA"
  }
}

Google CloudのVPC/サブネット基本仕様

項目 仕様
VPCのスコープ グローバル(リージョンをまたいで1つで運用できる)
サブネットのスコープ リージョン
VPC Flow Logsの有効化単位 サブネット(log_configで設定)
デフォルトVPC あり(auto mode)。今回は auto_create_subnetworks = false でサブネットを自分で定義

③ Service AccountとIAMバインディングの構成

「社員証を発行する → 入館権限を登録する → 人に持たせる」の3ステップのイメージ

Google Cloudでリソースに権限を持たせるときは、次の3ステップで構成します。

  1. Service Accountを作成する
  2. IAMバインディングで、Service Accountに権限を付与する
  3. Service Accountをリソース(今回はGoogle Cloud Run)に割り当てる
# 1. Service Accountを作る
resource "google_service_account" "cloud_run_sa" {
  account_id   = "cloud-run-sa"
  display_name = "Cloud Run Service Account"
}

# 2. Service AccountにGoogle Cloud Secret Managerへのアクセス権を付与
resource "google_secret_manager_secret_iam_member" "secret_access" {
  secret_id = google_secret_manager_secret.my_secret.secret_id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_service_account.cloud_run_sa.email}"
}

# 3. Google Cloud RunにService Accountを割り当てる
resource "google_cloud_run_v2_service" "main" {
  name     = "my-service"
  location = "asia-northeast1"

  template {
    service_account = google_service_account.cloud_run_sa.email
  }
}

※AWSのIAMロールのアタッチに近いイメージです。

構造を理解すると読みやすいですが、最初は「どのリソースにどのIAMバインディングが必要か」の把握に時間がかかりました。
リソースを追加するたびに、3ステップのどれが必要かを確認すると整理しやすくなります。


④ Google Cloud RunはデフォルトでVPCに接続されていない

Google Cloud Runは「デフォルトではオフィスの外で働く外部スタッフ」のイメージ
社内ネットワーク(VPC)に入るには明示的な手続きが必要。

Google Cloud Runは、デフォルトではVPCに接続されていません。
VPC内のリソースへのアクセスや、Google Cloud NATを経由したアウトバウンド通信には明示的な設定が必要です。

resource "google_cloud_run_v2_service" "main" {
  name     = "my-service"
  location = "asia-northeast1"

  template {
    vpc_access {
      network_interfaces {
        network    = google_compute_network.main.id
        subnetwork = google_compute_subnetwork.main.id
      }
      # PRIVATE_RANGES_ONLY: VPC内通信のみVPC経由
      # ALL_TRAFFIC: 全アウトバウンドをVPC経由(Google Cloud NAT適用)
      egress = "ALL_TRAFFIC"
    }
  }
}

egress = "ALL_TRAFFIC" にすることで、Google Cloud RunからのアウトバウンドがGoogle Cloud NATを経由します。
外部サービスへの通信をNAT経由で行いたい場合はこの設定が必要です。

Google Cloud NATのTerraformはこちら:

resource "google_compute_router" "main" {
  name    = "main-router"
  region  = "asia-northeast1"
  network = google_compute_network.main.id
}

resource "google_compute_router_nat" "main" {
  name                               = "main-nat"
  router                             = google_compute_router.main.name
  region                             = "asia-northeast1"
  nat_ip_allocate_option             = "AUTO_ONLY"
  source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
}

⑤ Google Cloud Runのコールドスタートに注意

「普段誰も来ない部屋の電気は消えている」状態で、最初の来客時だけ「電気を点けるまでの時間」が発生するイメージ。
min_instance_count = 1 は常に電気を点けっぱなしにする設定で、その分コストがかかる。

Google Cloud Runはリクエストがないときはインスタンスがゼロになります。
久しぶりのリクエストでコールドスタートが発生し、応答が遅くなることがあります。

同期的な処理(呼び出し側がレスポンスを待つアーキテクチャ)では特に影響が出やすいです。
Terraformで最小インスタンス数を設定して対応できます。

resource "google_cloud_run_v2_service" "main" {
  template {
    scaling {
      min_instance_count = 1  # 常時1インスタンス起動(コールドスタート回避)
      max_instance_count = 10
    }
  }
}

ただし min_instance_count = 1 にすると常時課金が発生します。
アクセス頻度と応答速度要件を考慮した上で設定しましょう。

まとめ

Google CloudをTerraformで構築する際に、最初に押さえておきたいポイントをまとめます。

# ポイント Terraformでの設定・対応
① サービスごとにAPIの有効化が必要 google_project_serviceで宣言的に管理
② VPCはグローバルスコープ サブネットにリージョンを指定
③ 権限はService AccountとIAMバインディングで構成 SA作成 → 権限付与 → Google Cloud Runへ割当の3ステップ
④ Google Cloud RunはデフォルトでVPC外 vpc_accessとegressを明示的に設定
⑤ コールドスタートが発生する min_instance_countで調整

Terraformの書き方の基本は、これまでの経験がそのまま活かせます。
Google Cloud特有の仕様を最初に把握しておくと、詰まりどころが減ります。
特に「API有効化」と「Google Cloud RunとVPCの関係」は最初に押さえておくと良いと思います。

参考