こういう状況に陥ることは珍しくない。AWSとGCPではプロバイダーの構造や認証方法が異なるため、同じHCLの感覚でそのまま移行しようとするとつまずく箇所が必ず出てくる。
この記事では、TerraformのGoogle Cloudプロバイダー(google provider)を使ってVPC・サブネット・ファイアウォール・Compute Engineインスタンスを一から定義し、terraform apply で実際にリソースを作成する手順を解説する。認証設定の落とし穴、AWSとの設計の違い、よくあるエラーの切り分けまでカバーする。
この記事のポイント
・google providerの認証はService Accountキーファイルで行う
・VPCはAWSと違いリージョンを持たず、サブネットがリージョン単位になる
・Compute Engineはゾーン指定が必須でrequired_providers設定と一緒に確認する
・APIの有効化忘れと権限不足が最頻出エラーの2大原因
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
GCPとTerraform(google provider)の基礎知識
TerraformでGCPを操作するには、HashiCorp公式パートナーのgoogle providerを使う。2024年以降のバージョン(5.x系)が安定しており、ほぼすべてのGCPリソースに対応している。GCPとAWSのTerraformプロバイダーで最初に戸惑う違いはプロジェクトの概念だ。AWSではアカウント単位でリソースが管理されるが、GCPではアカウントの下に「プロジェクト」という単位があり、リソースは必ずどこかのプロジェクトに属する。Terraformのリソース定義でも `project` 引数が頻出するため、最初にプロジェクトIDを変数化しておくと後が楽になる。
また、GCPはサービスごとにAPIを有効化する必要がある。Compute EngineのVPCやインスタンスを作成するには、まず `compute.googleapis.com` を有効化しておくことが必須だ。これを忘れると apply 実行時に403エラーが返ってきて初心者は首をかしげることになる。
google providerの認証設定
1. GCPプロジェクトの準備とgcloudの設定
作業前に以下が必要だ。・GCPプロジェクトが作成済みであること
・Google Cloud SDK(gcloud CLI)がPCにインストール済みであること
・請求アカウントがプロジェクトに紐付けられていること(Compute Engineの作成には請求設定が必要)
gcloudの初期設定はこのコマンドで行う。
# gcloudへのログインとプロジェクト設定 gcloud auth login gcloud config set project [プロジェクトID] # 設定確認 gcloud config get-value project # Compute Engine APIを有効化(必須) gcloud services enable compute.googleapis.com \ --project=[プロジェクトID]
2. Terraform用サービスアカウントの作成
Terraformが使用する認証情報はサービスアカウントのキーファイルで管理する。個人のgcloudセッションをそのまま使う「Application Default Credentials(ADC)」方式もあるが、CI/CDパイプラインへの展開を見据えてサービスアカウントを最初から用意しておくのが実務上の正解だ。# サービスアカウントの作成 gcloud iam service-accounts create terraform-sa \ --display-name="Terraform Service Account" \ --project=[プロジェクトID] # Compute管理者ロールを付与 gcloud projects add-iam-policy-binding [プロジェクトID] \ --member="serviceAccount:terraform-sa@[プロジェクトID].iam.gserviceaccount.com" \ --role="roles/compute.admin" # サービスアカウントを使った操作に必要なロールも付与 gcloud projects add-iam-policy-binding [プロジェクトID] \ --member="serviceAccount:terraform-sa@[プロジェクトID].iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountUser" # JSONキーの発行 gcloud iam service-accounts keys create terraform-key.json \ --iam-account=terraform-sa@[プロジェクトID].iam.gserviceaccount.com
3. required_providersの設定
プロジェクトディレクトリにHCLファイルを作成する。# versions.tf terraform { required_version = ">= 1.5" required_providers { google = { source = "hashicorp/google" version = "~> 5.0" } } }
# provider.tf provider "google" { credentials = file("terraform-key.json") project = var.project_id region = var.region }
# variables.tf variable "project_id" { type = string description = "GCPプロジェクトID" } variable "region" { type = string default = "asia-northeast1" } variable "zone" { type = string default = "asia-northeast1-b" }
$ terraform init Initializing the backend... Initializing provider plugins... - Finding hashicorp/google versions matching "~> 5.0"... - Installing hashicorp/google v5.40.0... Terraform has been successfully initialized!
VPC・サブネット・ファイアウォールのリソース定義
1. google_compute_networkでVPCを定義する
AWSとGCPのVPCには構造上の大きな違いがある。GCPのVPCはリージョンを持たず、グローバルリソースとして存在する。サブネットが各リージョンに紐付く設計だ。# network.tf resource "google_compute_network" "main" { name = "terraform-vpc" auto_create_subnetworks = false # カスタムサブネットモードを使う project = var.project_id }
2. google_compute_subnetworkでサブネットを設計する
resource "google_compute_subnetwork" "main" { name = "terraform-subnet" network = google_compute_network.main.id region = var.region ip_cidr_range = "10.0.1.0/24" project = var.project_id # 外部IPなしのインスタンスからGCPマネージドサービスへのアクセスを許可 private_ip_google_access = true }
3. google_compute_firewallでSSHを許可する
GCPのファイアウォールルールはVPCに紐付くリソースとして別途定義する。AWSのセキュリティグループと異なり、インスタンスに直接付与するのではなくネットワークタグで対象インスタンスを絞り込む設計になっている。resource "google_compute_firewall" "allow_ssh" { name = "allow-ssh" network = google_compute_network.main.name project = var.project_id allow { protocol = "tcp" ports = ["22"] } source_ranges = ["0.0.0.0/0"] # 本番では管理IPに限定すること target_tags = ["allow-ssh"] # このタグを持つインスタンスにのみ適用 }
>> Terraform実践セミナーの詳細はこちら
Compute EngineインスタンスのIaC定義
1. google_compute_instanceの基本構成
Compute EngineインスタンスはAWSのEC2に相当するリソースだ。ゾーン(zone)指定が必須な点がEC2との設計上の差異としてよく出てくる。# compute.tf resource "google_compute_instance" "web" { name = "terraform-web" machine_type = "e2-medium" # vCPU 2 / メモリ4GB zone = var.zone project = var.project_id # ファイアウォールのtarget_tagsと一致させる tags = ["allow-ssh"] boot_disk { initialize_params { image = "debian-cloud/debian-12" size = 20 # ディスクサイズ(GB) type = "pd-standard" } } network_interface { network = google_compute_network.main.id subnetwork = google_compute_subnetwork.main.id access_config { # このブロックを空にすることで外部IPが自動割り当てされる } } }
`access_config {}` のブロックを置かない場合はインスタンスに外部IPが割り当てられない(プライベートのみ)。外部からSSHで直接アクセスしたい場合は `access_config {}` ブロックが必要だ。
2. metadata_startup_scriptで初期化処理を組み込む
インスタンス起動時に初期設定を実行するには `metadata_startup_script` を使う。AWSの `user_data` に相当する機能だ。resource "google_compute_instance" "web" { # ...前述の設定... metadata_startup_script = <<-EOF #!/bin/bash apt-get update -y apt-get install -y nginx systemctl enable nginx systemctl start nginx EOF }
metadata_startup_script = file("scripts/startup.sh")
terraform plan・apply・destroyの実践フロー
`terraform.tfvars` でプロジェクトIDを渡す構成にしておくとコマンドがシンプルになる。# terraform.tfvars project_id = "my-gcp-project-123456"
# planで差分確認 $ terraform plan Terraform will perform the following actions: # google_compute_firewall.allow_ssh will be created + resource "google_compute_firewall" "allow_ssh" { + name = "allow-ssh" + network = "terraform-vpc" ... } # google_compute_instance.web will be created + resource "google_compute_instance" "web" { + machine_type = "e2-medium" + name = "terraform-web" + zone = "asia-northeast1-b" ... } # google_compute_network.main will be created # google_compute_subnetwork.main will be created Plan: 4 to add, 0 to change, 0 to destroy.
# applyで実際にリソースを作成 $ terraform apply -auto-approve google_compute_network.main: Creating... google_compute_network.main: Still creating... [10s elapsed] google_compute_network.main: Creation complete after 16s google_compute_subnetwork.main: Creating... google_compute_subnetwork.main: Creation complete after 14s google_compute_firewall.allow_ssh: Creating... google_compute_instance.web: Creating... google_compute_firewall.allow_ssh: Creation complete after 8s google_compute_instance.web: Creation complete after 22s Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
# gcloudでSSH接続 $ gcloud compute ssh terraform-web \ --zone=asia-northeast1-b \ --project=my-gcp-project-123456 # 不要になったら全リソースを削除 $ terraform destroy -auto-approve Destroy complete! Resources: 4 destroyed.
AWSとGCPの設計上の違い(Terraform視点)
AWSに慣れているエンジニアがGCPのTerraform設計に移行するときに混乱しやすい点を整理する。| 設計項目 | AWS(Terraform) | GCP(Terraform) |
|---|---|---|
| ネットワーク | aws_vpc(リージョン単位) | google_compute_network(グローバル) |
| サブネット | aws_subnet(AZを指定) | google_compute_subnetwork(リージョンを指定) |
| ファイアウォール | aws_security_group(インスタンスに付与) | google_compute_firewall(タグで対象を絞る) |
| 仮想マシン | aws_instance(AZを指定) | google_compute_instance(ゾーンを指定) |
| マシンスペック | instance_type(例: t3.medium) | machine_type(例: e2-medium) |
| 認証方式 | AWS Profile / IAM Role / 環境変数 | Service Account JSON / ADC / 環境変数 |
| OSイメージ指定 | ami(例: ami-0abcdef1234567) | image(例: debian-cloud/debian-12) |
| 起動スクリプト | user_data | metadata_startup_script |
最も重要な違いはファイアウォールの適用方式だ。AWSではセキュリティグループをネットワークインターフェースに直接付与するが、GCPではVPCレベルのファイアウォールルールにネットワークタグで対象を絞り込む。
この設計の違いを理解しないと、インスタンスのタグとファイアウォールの `target_tags` が一致せず「ファイアウォールを設定したはずなのにSSHが繋がらない」というトラブルに直面する。
トラブルシュート
1. Compute Engine APIが有効化されていないエラー
apply 実行時に以下のようなエラーが出る場合、GCPプロジェクトでAPIが有効になっていない。Error: Error creating Network: googleapi: Error 403: Compute Engine API has not been used in project [PROJECT_ID] before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview
gcloud services enable compute.googleapis.com --project=[プロジェクトID]
2. サービスアカウント権限エラー
Error: Error creating Instance: googleapi: Error 403: Required 'compute.instances.create' permission for 'projects/[PROJECT_ID]/zones/asia-northeast1-b', forbidden
# 現在の権限を確認 gcloud projects get-iam-policy [プロジェクトID] \ --filter="bindings.members:terraform-sa@[プロジェクトID].iam.gserviceaccount.com" \ --format="json" # roles/compute.admin を付与 gcloud projects add-iam-policy-binding [プロジェクトID] \ --member="serviceAccount:terraform-sa@[プロジェクトID].iam.gserviceaccount.com" \ --role="roles/compute.admin"
3. リージョン・ゾーン指定の混同
Error: Invalid value for field 'resource.zone': 'asia-northeast1'. Zones must be in the format: 'zone-name' (e.g., 'us-central1-a')
東京リージョン(asia-northeast1)で使えるゾーンは `-a`・`-b`・`-c` の3種類だ。
本記事のまとめ
TerraformでGCPのVPCとCompute Engineを定義する際のポイントを整理する。| やりたいこと | リソース・設定 |
|---|---|
| VPCを作成する(カスタムサブネット) | google_compute_network(auto_create_subnetworks=false) |
| サブネットを作成する | google_compute_subnetwork(regionとip_cidr_rangeを指定) |
| SSHを許可するファイアウォールを設定する | google_compute_firewall(target_tagsでインスタンスを絞る) |
| Compute Engineインスタンスを起動する | google_compute_instance(machine_typeとzoneを指定) |
| 起動スクリプトを実行する | google_compute_instance + metadata_startup_script |
| Terraform用の認証を設定する | Service AccountキーJSONをcredentials引数で指定 |
AWSとGCPの最大の設計上の違いは「ファイアウォールのネットワークタグ方式」と「VPCのグローバル設計」の2点だ。この2点を最初に理解しておくと、apply時のトラブルを大幅に減らせる。
認証情報(terraform-key.json)をGitにコミットしないことと、APIの事前有効化は実務で必ず引っかかるポイントなので、チームのチェックリストに組み込んでおくことを推奨する。
>> Terraform実践セミナーの詳細はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:TerraformのHCL組み込み関数実践ガイド|templatefile・jsonencode・try・mergeでリソース設定を動的に組み立てる方法
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます