In team-based Terraform workflows, the state file must be stored remotely. On GCP, using a GCS bucket as the backend is the simplest, easiest-to-operate option.
This article explains the GCS backend from a practical perspective: the basics, security design, initialization and migration, authentication and CI/CD, operations and troubleshooting, and an exam-prep checklist.
Terraform's GCS backend stores the state file in Google Cloud Storage and uses locks to prevent concurrent edits by your team. GCS object versioning and strong consistency enable safe reads and writes.
The backend itself is simple: all you need is a bucket name, an optional prefix, and authentication. To improve recoverability, always enable object versioning on the bucket.
| Backend | Locking mechanism | Versioning / recovery | Encryption |
|---|---|---|---|
| gcs | Lock via object generation preconditions | Recovery via GCS object versioning | Bucket default encryption (CMEK supported) |
| s3 | Lock via DynamoDB table | S3 Versioning | SSE-S3 / SSE-KMS |
| azurerm | Lock via Blob lease | Snapshot / version | Storage encryption + CMK |
| local | Process-local only (no shared lock) | None | OS dependent |
GCS backend data flow (including locking)
Minimal backend configuration example (static definition)
terraform {
backend "gcs" {
bucket = "my-tfstate-bucket"
prefix = "envs/prod"
# credentials は省略可(ADC を利用)。鍵ファイルを使うなら以下:
# credentials = "/secure/path/sa-key.json"
}
}
State is one of your most sensitive assets. Align bucket design with environment and project boundaries and clearly separate access boundaries. A common pattern is to split buckets per environment (prod/stg/dev) and organize the contents with prefix and workspace like directories.
Security is enforced at the bucket level. Enable Uniform bucket-level access and Public Access Prevention. Configure object versioning and a default CMEK to combine recoverability with encryption. Apply least privilege via IAM, granting the Terraform service account roles that allow reading and writing objects plus the create/delete operations required for locks.
Baseline bucket configuration (gsutil / gcloud examples)
# バケット作成(リージョンはチームの実行場所に近いものを)
gsutil mb -p ${PROJECT_ID} -l ${REGION} gs://${BUCKET}
# Uniform bucket-level access を有効化
gsutil uniformbucketlevelaccess set on gs://${BUCKET}
# Public Access Prevention を有効化
gcloud storage buckets update gs://${BUCKET} --public-access-prevention
# オブジェクトバージョニングを有効化
gsutil versioning set on gs://${BUCKET}
# デフォルト CMEK を設定(事前に KMS キーを用意しておく)
# projects/PRJ/locations/LOC/keyRings/RING/cryptoKeys/KEY を指定
gcloud storage buckets update gs://${BUCKET} \
--default-encryption-key=${KMS_KEY_RESOURCE}
# IAM 付与(例: 実行 SA にオブジェクト管理権限を付与)
gsutil iam ch serviceAccount:${TF_SA}:roles/storage.objectAdmin gs://${BUCKET}
By Terraform syntax, the backend block cannot use variables or references. Substitute values via terraform init's -backend-config. The pragmatic pattern is to hardcode most of it and inject only secrets or per-environment differences via -backend-config.
Migration from existing local state can be performed safely with terraform init -migrate-state. On the first init, if existing state is present, you will be prompted to confirm the copy.
Partial backend definition and init command examples
# main.tf(部分的に固定)
terraform {
backend "gcs" {
bucket = "my-tfstate-bucket"
prefix = "team1/appA"
# credentials は CLI 側で渡す想定(ADC 利用なら不要)
}
}
# CLI で環境差分を注入して初期化(ADC を使わない場合の例)
terraform init \
-backend-config="credentials=/secure/path/sa-key.json"
# 既存ローカル state からの移行
terraform init -migrate-state
# backend.hcl を使う場合(CI 向け)
# backend.hcl
# bucket = "my-tfstate-bucket"
# prefix = "team1/appA"
# credentials = "/secure/path/sa-key.json"
terraform init -backend-config=backend.hcl
ADC (Application Default Credentials) is recommended. Locally, use gcloud auth application-default login. On GCE/Cloud Run/Cloud Build, grant least-privilege roles to the runtime service account, and you can omit credentials from the backend block.
Avoid embedding key files in CI/CD; use Workload Identity Federation or run directly as a service account. If you absolutely must use a key file, store it in Secret Manager or similar and have a rotation plan in place.
Representative authentication examples for local and CI
# ローカル(ADC)
# ブラウザで認証し ADC を設定
gcloud auth application-default login
# credentials を省略して init
terraform init
# サービスアカウント鍵ファイルを使う場合(非推奨だが例示)
export GOOGLE_APPLICATION_CREDENTIALS=/secure/path/sa-key.json
terraform init -backend-config="credentials=${GOOGLE_APPLICATION_CREDENTIALS}"
# Cloud Build(サービスアカウントに権限付与済み / ADC 利用)
# cloudbuild.yaml のステップ内でそのまま実行可能
- name: hashicorp/terraform:light
entrypoint: bash
args:
- -c
- |
terraform init -backend-config=backend.hcl
terraform plan -input=false
Locks are normally released automatically, but they can linger after abnormal process termination. The error message includes the lock ID; once you have verified it is safe to clear, run force-unlock.
If you accidentally update state, you can recover via GCS object versioning by fetching a previous version. Rather than overwriting directly, copy to a different name first, then consider terraform state push/pull (push is usually disabled, so handle recovery carefully).
Unlocking and version recovery examples
# ロック解除(エラーメッセージにある ID を使用)
terraform force-unlock 12345678-90ab-cdef-1234-567890abcdef
# 既存 state の取得
terraform state pull > current.tfstate
# オブジェクトの全バージョンを確認(-a オプション)
gsutil ls -a gs://${BUCKET}/${PREFIX}/default.tfstate
# 特定世代(#NUM)を別名へコピーして比較
gsutil cp gs://${BUCKET}/${PREFIX}/default.tfstate#NUM ./recovered.tfstate
# 差分を目視確認後、慎重に復旧手順を選択(例: 手動で必要エントリを移植)
Questions concentrate on the basics: backend immutability, locking, recovery, and authentication. For design-choice questions, the key is whether you pick versioning, least privilege, and keyless operation (ADC / Workload Identity).
Common topics include the correct use of migration and reinitialization flags (-migrate-state vs -reconfigure), the fact that variables cannot be used in the backend block, and the relationship between workspaces and prefix.
Reinitialization and backend config swap (frequently tested)
# backend 設定を変更した場合(例: prefix 変更)は再初期化を明示
terraform init -reconfigure -backend-config=backend.hcl
# 既存ローカル state を GCS に移行
terraform init -migrate-state
Associate / Pro
問題 1
Which of the following is a correct statement about Terraform's GCS backend?
正解: A
A is correct. The GCS backend supports locking, and GCS object versioning is effective for recovery; the backend block is static and cannot use variables. B is wrong (KMS is set via bucket default encryption). C is wrong (ADC / Workload Identity is recommended; a key file is not required). D is wrong (terraform init -migrate-state migrates safely).
Should I split buckets per environment, or separate them by prefix/workspace?
From a confidentiality and blast-radius standpoint, it is safer to split prod from non-prod into separate buckets. Within a bucket, organize further with prefix and workspace. A single bucket is fine if you can cleanly enforce access boundaries via IAM, but per-environment buckets are easier to manage given the risk of misconfigured permissions.
Can I run from CI without a service account key file?
Yes. On Cloud Build/Run/GCE and similar runtimes, grant the runtime service account least-privilege roles and authenticate via ADC (Application Default Credentials); no key file is needed. For stricter setups, keyless operation via Workload Identity Federation is recommended.
Is it OK to use a multi-region bucket?
Yes, it works. Choose based on where your team runs Terraform, latency requirements, and data residency requirements. GCS is strongly consistent so there are basically no feature-level limitations, but cost and latency characteristics change with region selection.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...