---
title: "TerraformでGCPを構築する手順｜google 7系の認証とGCSバックエンド設計"
url: "https://www.issoh.co.jp/tech/details/16544/"
published: 2026-08-14
updated: 2026-09-27
categories: ["Google Cloud"]
publisher: "株式会社一創"
---

# TerraformでGCPを構築する手順｜google 7系の認証とGCSバックエンド設計

TerraformでGoogle Cloudを触り始めると、最初の30分はだいたい認証で止まります。日本語の入門記事はサービスアカウントのJSONキーを作って`credentials`に渡す手順が主流ですが、Google Cloud公式のIAMベストプラクティスは「We recommend that you avoid using service account keys whenever possible.」と書いている。この記事では、google 7系プロバイダの設定とgoogle-betaの併用条件、キーを配らない認証（ADC・Workload Identity Federation・権限借用）の組み立て、tfstateをGCSへ置く`backend "gcs"`の引数とロック・分割境界、サポートが終了したDeployment Managerからの移行先までを、2026年8月14日時点の一次情報で実測して整理します。

## まとめ：GCPをTerraformで扱うときに先に決める認証・state・境界の3点

結論から書きます。認証はローカルがADC（`gcloud auth application-default login`）＋権限借用、CI/CDはWorkload Identity Federationの2本立てにし、サービスアカウントのJSONキーは組織ポリシーで作成自体を止めるところまで含めて設計してください。キーを配る構成は、監査ログに「誰が使ったか」が残りません。

stateはGCSバケットへ置き、本番と検証は**バケットごと別プロジェクトに分ける**のが実務上の境界です。同一バケット内の`prefix`分割はIAMの境界にならないため、環境分離の手段としては弱い。`prefix`は権限が同じ相手の分割に使います。

プロバイダは`hashicorp/google`の7系（2026年8月14日時点の最新は7.44.0・2026年8月11日公開）を使い、バージョンは`~> 7.0`のようにメジャーで固定する。Deployment Managerは2026年4月1日にサポートが終了しており、新規の選択肢には入りません。

## google 7系プロバイダの設定と、google-betaを併用する条件

Google Cloud向けのTerraformは、プロバイダを1つ書けば動きます。ただしその1つに書く`project`と`region`の扱いを誤解したまま進むと、リソースが意図しないプロジェクトに作られます。

### google providerのproject・region既定とリソース側指定の優先順

`provider "google"`ブロックに書く`project`・`region`・`zone`は、あくまで**既定値**です。各リソースが自分の`project`引数を持っている場合はそちらが優先され、プロバイダ側の値は使われません。マルチプロジェクト構成でこの優先順を忘れると、共有VPCのサブネットだけホストプロジェクト、残りはサービスプロジェクト、といった配置が崩れます。

環境変数`GOOGLE_PROJECT`・`GOOGLE_REGION`でも既定値を与えられます。CI上ではこちらのほうが扱いやすい一方、手元とCIで異なる値が入っていると`terraform plan`の差分が人によって変わる事故が起きます。プロジェクトIDは変数化して`terraform.tfvars`か`-var-file`で明示的に渡し、環境変数は補助にとどめてください。宣言的な構成管理そのものの考え方は[IaCとは？Infrastructure as Codeの仕組み・メリットと導入判断](https://www.issoh.co.jp/column/details/13004/)で扱っています。

### 7.0で厳格化されたimport形式と、6系から上げる前に通す確認手順

7.0.0は2025年8月26日公開で、以降は7.44.0（2026年8月11日）まで週次に近い頻度で更新されています。8系は同日時点でプレリリースも含めて存在しない。今から書き始めるなら7系が唯一の現行メジャーです。

7.0.0で全リソースに効いた変更が、importの入力検証でした。公式アップグレードガイドは「All GCP resource IDs supplied to “terraform import” must match the documentation specified import formats exactly.」と記載しています。6系では入力の一部が正しければ通っていた不正な形式が、7系では弾かれる。既存環境を取り込む予定があるなら、この差が移行作業の見積りに直結します。

個別リソースでは、データソース`google_service_account_key`の`project`が削除され、`google_alloydb_cluster`には`deletion_protection`が既定`true`で追加されました。後者は「In 7.0.0, existing clusters will have deletion\_protection set to true during the next refresh unless otherwise set in configuration.」とあり、次回refreshで既存クラスタにも付きます。公式が示す上げ方は、6系の最終版へ先に上げてガイドの修正を当て、`terraform plan`が想定外の差分と非推奨警告を出さない状態を作ってから7系へ進む順です。バージョン制約の書き方と`.terraform.lock.hcl`の扱いは[terraform providerのバージョン制約とalias設計](https://www.issoh.co.jp/tech/details/16540/)にまとめてあります。

### google-betaを足す判断基準と、同一リソースで併用しない理由

Google Cloudのプロバイダは1.19.0以降、`google`と`google-beta`の2種類があります。公式の説明は「The google-beta provider is distinct from the google provider in that it supports GCP products and features that are in Preview, while google does not.」。ドキュメントは共有され、beta限定のフィールドとリソースには印が付きます。

注意すべきは送信先です。公式は「The google-beta provider sends all requests to the beta endpoint for GCP if one exists for that product, regardless of whether the request contains any beta features.」と明記している。beta機能を1つも使っていなくても、そのリソースの通信はbetaエンドポイントへ流れます。だからリポジトリ全体を切り替えるのではなく、必要なリソースにだけ`provider = google-beta`を書くのが正しい足し方です。

同一のクラウドリソースを両方のプロバイダで宣言するのは避けてください。Terraformから見れば別アドレスの2リソースであり、applyのたびに相手の変更を打ち消し合います。GAへ昇格したらbeta指定を外し、`terraform plan`が無差分になることを確認してから宣言を戻す。なおTerraform側のリソース名と実サービス名がずれる例もあり、[Google Cloud FunctionsとCloud Run functionsへの改称](https://www.issoh.co.jp/tech/details/15538/)はその一例です。

### default\_labelsで統一するタグ設計と属性ラベルの既定挙動

コスト配賦のラベルを全リソースへ手で書く運用は続きません。プロバイダの`default_labels`はトップレベルに`labels`を持つリソースへ一括適用され、リソース側で同じキーを指定するとそちらが勝ちます。共通ラベルを既定に置き、例外だけ上書きする形にしてください。適用結果は`terraform_labels`と`effective_labels`に記録され、planの差分でも追えます。あわせて`add_terraform_attribution_label`の既定値が`true`である点も押さえておくとよい。Terraformが作ったリソースには`goog-terraform-provisioned = true`が自動で付き、コンソールから「コード管理下か、手作業か」を見分けられます。

## サービスアカウントキーを配らない認証設計とWIF・権限借用の使い分け

ここが日本語圏の入門記事と最も食い違う部分です。JSONキーを作る手順は動きますが、Google公式は別の方法を先に検討するよう書いています。

### ローカルはADC、CIはWIF｜キーのJSONを配布しない前提の組み立て

Google Cloud公式のIAMベストプラクティスは「We recommend that you avoid using service account keys whenever possible.」と述べ、理由を「Cloud Audit Logs creates a log when a service account modifies a resource, but if the service account is authenticated with a service account key, there is no reliable way to tell who used the key.」と説明しています。キーが漏れたかどうか以前に、**監査ログから実行者を特定できない**点が問題です。

代替として公式が挙げるのは、Application Default Credentials、外部ワークロード向けのWorkload Identity Federation、ユーザー資格情報からのサービスアカウント権限借用、Google Cloud内リソースへのサービスアカウント添付の4つ。Terraformの文脈では、手元が`gcloud auth application-default login`で得たADC、GitHub ActionsなどのCIはOIDCトークンをWorkload Identity Federationで交換、GCEやCloud Build上ならインスタンスに添付したサービスアカウント、と整理できます。公式はさらに「We recommend preventing the creation of service account keys by applying the Disable service account key creation organization policy constraint.」として組織ポリシーでキー作成自体を塞ぐことまで勧めている。運用開始後にこれを入れると既存の自動化が一斉に止まるため、プロジェクト立ち上げの初日に決める項目です。GitHub Actions側でこの交換を実装する手順は[google-github-actions/authとは？Workload Identity連携の設定と移行判断](https://www.issoh.co.jp/tech/details/16953/)にまとめています。

### impersonate\_service\_accountで権限を借りる構成と必要ロール

権限借用は、ユーザー自身に強い権限を持たせずにTerraformを動かす方法です。プロバイダの`impersonate_service_account`に借用先のサービスアカウントを指定すると、以降のGoogle API呼び出しがそのサービスアカウントとして実行される。公式の記述は「You must have roles/iam.serviceAccountTokenCreator role on that account for the impersonation to succeed.」です。

このロールは付け先を間違える例が多く見られます。付与するのは**借用先サービスアカウントというリソースに対して、借用する側のユーザーへ**。プロジェクトレベルで全員に付けると、そのプロジェクト内の全サービスアカウントを誰でも借りられる状態になります。組織単位の委譲が必要なときは`impersonate_service_account_delegates`でチェーンを明示し、CIでは環境変数`GOOGLE_IMPERSONATE_SERVICE_ACCOUNT`を使うと扱いやすい。

見落としやすいのがbackend側です。`backend "gcs"`はプロバイダの設定を読まないため、stateの読み書きも借用したいなら`backend`ブロック側にも同じ引数が要ります。プロバイダだけ設定してbackendを忘れると、リソース操作は通るのにstateの取得で403になる。

### user\_project\_overrideとbilling\_projectを設定する場面

ADCで進めると、あるタイミングから「quota project」に起因する403が出ます。プロバイダの`user_project_override`は既定`false`で、公式は「Controls the quota project used in requests to GCP APIs for the purpose of preconditions, quota, and billing.」という説明です。`false`のときのquotaプロジェクトはAPI側の判定に委ねられ、資格情報に紐づくプロジェクトになることがあります。

ここで問題になるのが`gcloud`由来の資格情報です。公式には「Credentials that come from the gcloud tool are associated with a project owned by Google. In order to properly use credentials that come from gcloud with Terraform, it is recommended to set this property to true.」との記載があります。つまりローカルのADCで開発するなら`user_project_override = true`が既定の選択で、あわせて`billing_project`に自分のプロジェクトIDを指定する構成です。`true`のとき、リクエストには`X-Goog-User-Project`システムパラメータが付きます。環境変数はそれぞれ`USER_PROJECT_OVERRIDE`と`GOOGLE_BILLING_PROJECT`です。

## tfstateをGCSへ置くbackend gcsの引数とロック・プロジェクト分割

Google公式のTerraformベストプラクティスは、デプロイの推奨として「Store Terraform state in a Cloud Storage bucket」と書いています。ローカルのtfstateは1人で試す段階までです。

### backend “gcs”のbucket・prefixと環境ごとに分ける置き方

必須の引数は`bucket`だけで、グローバルに一意なGCSバケット名を渡します。実務で併せて使う引数は次のとおりです。

- `prefix`：バケット内でstateファイルを置くパス。環境やコンポーネント単位の仕切りに使う
- `impersonate_service_account`：state操作を借用したサービスアカウントで行う
- `credentials`（環境変数`GOOGLE_BACKEND_CREDENTIALS`）：backend専用に資格情報を分けたい場合
- `access_token`：短命のOAuth 2.0トークンを直接渡す。CIでWIFと組み合わせる構成で使う
- `storage_custom_endpoint`：Private Service Connect経由でGCSへ到達させる場合

`backend`ブロックには変数を書けません。環境ごとにバケットを変えるなら、値は`terraform init -backend-config=env/prod.gcs.tfbackend`のように外から渡します。tfstateそのものの構造や、バックエンドを移すときの手順は[Terraform stateとは？tfstateの構造とバックエンド・移動削除の安全手順](https://www.issoh.co.jp/tech/details/16525/)で扱っているので、GCS固有の部分だけこちらで押さえてください。

### stateロックとGCS側の暗号化オプションを決めるときの判断軸

ロックについて、HashiCorpの公式ドキュメントは`gcs`バックエンドに対して「This backend supports state locking.」と明記しています。DynamoDBのような別サービスを用意する必要はなく、バケットさえあれば同時applyの衝突を防げる。ここはS3バックエンドと運用感が違う点です。

暗号化は3択です。何も指定しなければGoogle管理の鍵で保存され、`encryption_key`（環境変数`GOOGLE_ENCRYPTION_KEY`）にbase64エンコードした顧客提供の鍵を渡せばCSEK、`kms_encryption_key`を指定すればCloud KMSの鍵を使います。判断軸は単純で、**鍵のローテーションとアクセス監査を担当できる人がいるならKMS、いないならGoogle管理鍵のまま**にしてください。CSEKは鍵を失うとstateを復号できず、鍵の配布経路がキー配布と同じ問題を抱えます。

暗号化より先に効くのはバケットのバージョニングです。stateは書き込み時に上書きされるため、誤った`terraform state rm`や中断したapplyから戻る手段はバージョニングしかない。バケット作成時に有効化し、古い世代はライフサイクルルールで削除します。

### プロジェクトを分けるか、prefixで分けるか｜state分割の境界

本番と検証を分ける手段として、同一バケットの`prefix`違いで済ませる構成をよく見ます。これは勧めません。Google CloudではIAMと課金の境界がプロジェクトであり、バケット内の`prefix`には権限境界がないためです。検証環境の権限しか持たないはずのメンバーが、バケットの読み取り権限経由で本番のtfstateを読めてしまいます。tfstateには接続文字列や生成された認証情報が平文で入りうる。

実務の境界はこうです。**本番と検証は別プロジェクト・別バケットに分ける。**同一環境内でネットワーク層とアプリケーション層を分けたい、といった権限が同じ相手の分割は`prefix`で足ります。分割単位を細かくするほどapplyの所要時間は短くなりますが、`terraform_remote_state`での参照が増えて依存が絡みます。環境をどの方式で分けるかの比較は[terraform workspaceの使い方と環境分離の判断基準](https://www.issoh.co.jp/tech/details/16529/)に整理しました。workspaceは同一バックエンド内で状態を切り替える仕組みであり、プロジェクトごと分ける本番／検証の分離とは目的が異なります。

## Deployment Manager終了で決まる移行先とInfra Managerの採否

Google Cloudのネイティブなデプロイ機構だったDeployment Managerは、すでにサポート期間の外にあります。既存デプロイを抱えている組織にとっては、移行の期限が明確な日付で決まっています。

### サポート終了2026年4月1日・新規遮断6月30日・停止2027年6月30日

Google Cloud公式の廃止ドキュメントに記載されている日程を整理します。

| 時期         | 状態          | 実務上の意味                   |
| ---------- | ----------- | ------------------------ |
| 2026年4月1日  | サポート終了      | 標準サポート無回答。新機能・重大修正以外停止   |
| 2026年6月30日 | 新規利用の遮断     | 新規はV2 API有効化・初回デプロイ作成不可  |
| 2027年3月31日 | 最大延長サポートの終了 | この期間はブロッカーと移行関連のチケットのみ受付 |
| 2027年6月30日 | サービス停止      | APIと機能が停止する              |

既存ユーザーは自己責任で管理・移行・削除を続けられますが、事実上の作業期限は2027年6月30日です。新規プロジェクトでDeployment Managerを検討する余地はもうありません。逆算すると、既存デプロイの棚卸しと移行計画は2026年度内に着手しておく規模感になります。

### Infra Managerと素のTerraform｜state管理の担当をどちらに置くか

Google公式が移行先として挙げるのはInfrastructure Manager（Infra Manager）です。Deployment ManagerがYAMLとJinja/Pythonテンプレートで構成を書いたのに対し、Infra ManagerはTerraformでインフラのデプロイを作ります。どちらの道を選んでも、書く言語はHCLになる。

分岐点はstateの管理責任です。Infra Managerはstateの保管とTerraformの実行をGoogle Cloud側が持つマネージドサービスで、バケットの設計もCIランナーの用意も要りません。素のTerraformに`backend "gcs"`を組み合わせる構成は、バージョン固定・ロック・実行環境をすべて自前で持つかわりに、他クラウドやSaaSのプロバイダを同じパイプラインへ混ぜられます。**判断基準は明確に置けます。**Google Cloudだけで完結してstateの運用担当を置けないならInfra Manager、CI/CDにIaCを載せて他クラウドやDatadog・GitHubも同じ仕組みで管理するなら素のTerraformです。中間の「とりあえず両方」は実行経路が二重になってstateの真実が分かれるため取りません。移行の設計や既存環境の棚卸しから相談したい場合は、[AWS・Google Cloud・Azureのインフラ構築](https://www.issoh.co.jp/service/system/aws/)で受託の実績があります。

### DM Convertで変換したコードをそのまま運用に載せない理由

Googleは移行支援としてDM Convertを提供しており、Deployment Managerの構成をTerraform形式へ自動変換できます。ただし変換の出力は、既存デプロイに含まれるリソース定義を平坦に書き写したものです。モジュール分割も変数化も命名規約も入っていません。Google公式のTerraformベストプラクティスが求める標準モジュール構造（`main.tf`・`variables.tf`・`outputs.tf`）とはかけ離れた形になります。

安全な進め方は次の順です。

1. DM Convertで変換し、生成されたHCLを`terraform fmt`にかけて読める形にする
2. 既存リソースを`terraform import`でstateへ取り込む（7系のimport形式は厳格なので、公式ドキュメントの形式と完全一致させる）
3. `terraform plan`が差分ゼロになるまで、変換されたコードを実リソースへ寄せる
4. 差分ゼロを確認したうえで、モジュール化と変数化のリファクタリングに入る

3と4を入れ替えると、コードを整理した結果の差分なのか、変換漏れによる差分なのかを切り分けられなくなります。差分ゼロという中間ゴールを必ず1回作ってください。

## GCPでTerraformを見送る条件と、権限設計で詰まる典型パターン

ここまで設計の話をしてきましたが、そもそもTerraformを入れないほうがよい場面もあります。判断を先に書きます。

### Terraformを見送る条件｜単発検証とマネージド前提の小規模構成

次の2つに当てはまるなら、Terraformは入れないでください。1つは数日で捨てる検証環境で、`gcloud`のコマンドを手順書に残すほうが速く、tfstateの管理コストが丸ごと無駄になります。もう1つは、Cloud Run 1サービスとFirestore程度のマネージド構成で、構成変更が月1回未満、触る人が1名という規模。この条件下ではコードの陳腐化のほうが早く、次に触るときには実環境とコードがずれていて、結局コンソールで直すことになります。

採用条件も条件付きで言い切れます。環境が2つ以上ある、構成変更が週次以上で発生する、触る人が2名以上いる。このうち2つを満たしたらTerraformを入れる側に倒してください。分かれ目は構成の複雑さではなく**変更の頻度と関与人数**で、1人が月1回触る複雑な構成より、3人が毎週触る単純な構成のほうがIaCの効果は出ます。

### 権限設計で詰まる入口｜Token Creatorの付け先とquotaプロジェクト

止まる箇所は2種類に収れんします。1つはquotaプロジェクトの未設定で、ADCのまま`user_project_override`を`false`で進めると一部のAPIが403を返す。エラー文面がIAM不足のように見えるためロールを足す方向へ迷い込みがちですが、原因は課金プロジェクトの解決です。

もう1つは、backendとproviderで必要な権限が別物である点です。providerが要求するのは対象リソースの操作権限、backendが要求するのはstateバケットに対するオブジェクトの読み書き権限（`roles/storage.objectAdmin`相当）。CIのサービスアカウントへ前者だけ与えて`terraform init`で止まる、という詰まり方をします。前述のTokenCreatorの付け先違いと合わせ、この3点を先に潰しておけば初期構築で丸一日を失うことはありません。

### マルチクラウドを1リポジトリで扱う条件と、分けたほうがよい場面

Google CloudとAWS、あるいはAzureを併用している場合、リポジトリを分けるか統合するかで迷います。判断はシンプルです。**デプロイの依存関係がクラウドを跨ぐ場合だけ、同一のTerraform構成に置いてください。**AWS側のRoute 53レコードがGoogle Cloud側のロードバランサIPを参照する、といった関係がこれにあたります。1つのstateで`google`と`aws`のプロバイダを併記したほうが順序を保証できる。

跨がないなら分けてください。プロバイダを1つのstateに混ぜると、片方のメジャーアップグレードのたびに無関係なもう一方のリソースまでrefreshの対象になり、`terraform plan`の所要時間も認証失敗の影響範囲も広がります。Azure側の実装は[TerraformでAzureを構築する手順とazurerm 5系の認証・backend設計](https://www.issoh.co.jp/tech/details/16542/)にまとめてあり、認証方式もbackendの引数もGoogle Cloudとは別物。共通化できるのはディレクトリ構成とCIの型までで、認証とstateの設計は各クラウドで作り分けます。

## よくある質問

Google CloudをTerraformで扱い始めた段階で寄せられる質問を、判断の理由まで含めて答えます。

### terraform gcpの学習で最初に作るリソースは何がよいですか？

GCSバケット（`google_storage_bucket`）を勧めます。作成が数秒で終わり、費用がほぼ発生せず、削除も容易で、しかもstateを置く先そのものだからです。バケットを1つ作ってからbackendをローカルからGCSへ移すと、`terraform init -migrate-state`の挙動まで一度に体験できます。逆に最初にGKEクラスタやCloud SQLを選ぶと、作成に10分以上かかり、失敗時のリトライで学習のテンポが落ちます。

### サービスアカウントキーのJSONを使う構成は今も使えますか？

技術的には動きます。プロバイダの`credentials`引数や`GOOGLE_CREDENTIALS`環境変数は現行の7系でも有効です。ただしGoogle Cloud公式のIAMベストプラクティスは「We recommend that you avoid using service account keys whenever possible.」とし、キー認証では監査ログから実行者を特定できない点を理由に挙げています。新規に組むなら、ローカルはADC、CIはWorkload Identity Federationにしてください。既存でキーを使っている場合は、まず組織ポリシーで新規キーの作成を止め、既存キーの棚卸しから始めるのが現実的な移行順です。

### google providerのバージョンはどこまで固定すべきですか？

`required_providers`で`version = "~> 7.0"`のようにメジャーを固定し、パッチとマイナーは`.terraform.lock.hcl`で固定する組み合わせを勧めます。google providerは週次に近い頻度で更新され、2026年8月11日時点の最新は7.44.0です。マイナーまで固定すると新リソースが使えず、無指定だとメジャー更新を意図せず踏みます。lockファイルはリポジトリへコミットし、更新は`terraform init -upgrade`を明示的に実行したときだけ起こす運用にしてください。

### GCSバックエンドのバケットはTerraformで作ってよいですか？

作って構いませんが、そのバケットを管理するstate自体は同じバケットに置かないでください。鶏と卵になり、バケットを消すとstateも消えます。実務では、stateバケットとサービスアカウントだけを扱う小さな構成を1つ用意し、そこはstateをローカル管理かつ変更頻度をほぼゼロにする、という分け方が現実的です。作成時はバージョニングを有効化し、`lifecycle { prevent_destroy = true }`を付けて誤削除を止めておきます。

### Deployment Managerの既存デプロイはいつまでに移せばよいですか？

サービス停止は2027年6月30日で、これが最終期限です。ただしサポートはすでに2026年4月1日に終了しており、標準の問い合わせには回答がありません。2027年3月31日までの最大延長期間も、受け付けられるのはブロッカーと移行関連のチケットに限られます。移行中に問題が起きたときに支援を受けられる期間から逆算すると、2027年3月末までに移行を完了させる計画が現実的です。変換はDM Convertで始め、importでstateへ取り込み、planが差分ゼロになる状態を作ってからリファクタリングへ進んでください。

## 関連記事

- [IaCとは？Infrastructure as Codeの仕組み・メリットと導入判断を解説](https://www.issoh.co.jp/column/details/13004/)：宣言的な構成管理の考え方と導入判断。
- [terraform providerのバージョン制約とalias設計｜lockファイルの運用判断](https://www.issoh.co.jp/tech/details/16540/)：版の固定方針とlockファイルの運用。
- [Terraform stateとは？tfstateの構造とS3バックエンド・移動削除の安全手順](https://www.issoh.co.jp/tech/details/16525/)：stateの構造とバックエンド移行の一般論。
- [terraform workspaceの使い方と環境分離の判断基準｜分割方式の比較](https://www.issoh.co.jp/tech/details/16529/)：環境をどう分けるかの方式比較。
- [Google Cloud Functionsとは？仕組み・料金とCloud Run functionsへの改称・採用判断](https://www.issoh.co.jp/tech/details/15538/)：Terraformで扱うGoogle Cloud側の代表リソース。

---

出典: [TerraformでGCPを構築する手順｜google 7系の認証とGCSバックエンド設計](<https://www.issoh.co.jp/tech/details/16544/>)（株式会社一創）
