Terraform で複数人・複数環境を安全に運用するには、状態(tfstate)をリモートで一元管理し、並行実行を防ぐロックと堅牢な認証が欠かせません。本稿では Azure Blob Storage を用いる azurerm バックエンドの実務運用ポイントを、試験(Associate / Pro)で問われやすい観点とあわせて整理します。
公式仕様に基づき、作成コマンド、認証パターン、ワークスペース分離、ロック動作、CI/CD での落とし穴と対処を具体化します。
Terraform のバックエンドは状態ファイルの保存先とロック方式を決めます。Azure 環境なら azurerm バックエンドで Blob Storage に保存するのが定番です。Blob のリース機能を利用した排他ロックにより、apply の二重実行を防げます。
ストレージ側は既定でサーバー側暗号化が有効、Azure AD ベースの RBAC によるきめ細かなデータプレーン権限付与が可能です。Terraform 側は terraform init によってバックエンドと接続し、以後の plan/apply はリモート状態を参照・更新します。
| バックエンド | ロック方式 | 既定の暗号化 | 主な認証 |
|---|---|---|---|
| local | なし(並行実行で破損リスク) | なし | ローカル権限のみ |
| azurerm (Azure Blob) | Blob Lease による排他 | サーバー側暗号化(Microsoft 管理キー) | Azure AD(RBAC) / Managed Identity / サービスプリンシパル / (代替)アクセスキー・SAS |
| s3 (参考) | DynamoDB テーブルでロック(任意) | サーバー側暗号化(SSE-S3 既定) | AWS IAM(ロール/ユーザー) |
Azure Blob バックエンドの流れ(ロック含む)
最小構成の backend ブロック(認証は環境側で供給)
terraform {
backend "azurerm" {
resource_group_name = "rg-tfstate"
storage_account_name = "sttfstate1234"
container_name = "tfstate"
key = "network/terraform.tfstate"
# 認証情報は Azure AD / CLI / Managed Identity / SP の環境から取得
}
}
状態保存用の専用ストレージアカウントを用意します。命名は小文字・数字で 3〜24 文字。Blob コンテナは環境ごとに分けるか、キーで論理分離します。パブリックアクセスは無効を推奨、バージョニングとソフトデリートを有効化すると復旧が容易です。
terraform init に先立ち、リソースグループ、ストレージ、コンテナを作成します。認証を Azure AD で行う場合、コンテナ作成は CLI の login 認証を使うと安全です。
Azure CLI による作成例と推奨プロパティ設定
# 1) リソースグループ
az group create -n rg-tfstate -l japaneast
# 2) ストレージアカウント(パブリックアクセス無効)
az storage account create \
-n sttfstate1234 \
-g rg-tfstate \
-l japaneast \
--sku Standard_LRS \
--kind StorageV2 \
--allow-blob-public-access false
# 3) Blob バージョニングとソフトデリート(例: 30日)
az storage account blob-service-properties update \
--account-name sttfstate1234 \
--enable-versioning true
az storage blob service-properties delete-policy update \
--account-name sttfstate1234 \
--enable true --days-retained 30
# 4) コンテナ作成(Azure AD ログインを使用)
az storage container create \
--name tfstate \
--account-name sttfstate1234 \
--auth-mode login
バックエンドの認証は Azure AD を推奨します。サービスプリンシパル、Managed Identity、ローカルの Azure CLI ログイン、ワークロード ID(OIDC) などが利用できます。ストレージ データプレーン権限として、少なくとも Storage Blob Data Contributor を付与します(コンテナ単位のスコープ最小化が望ましい)。
環境変数経由のサービスプリンシパル認証では ARM_CLIENT_ID/ARM_CLIENT_SECRET/ARM_TENANT_ID/ARM_SUBSCRIPTION_ID を設定します。ワークロード ID フェデレーション(GitHub Actions など)ではクライアントID/テナントID/サブスクリプションIDを設定し、OIDC トークンはログインアクションが提供するファイル/環境から取得されます。アクセスキーや SAS トークンも使えますが、運用上は鍵のローテーションや秘匿管理の複雑さから Azure AD 優先が無難です。
RBAC 付与と環境変数の例(SP 認証)
# サービスプリンシパル(appId)に Blob データ貢献者ロールを付与
az role assignment create \
--assignee <APP_ID> \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/<SUB_ID>/resourceGroups/rg-tfstate/providers/Microsoft.Storage/storageAccounts/sttfstate1234"
# Terraform 用の環境変数(SP シークレット認証)
export ARM_CLIENT_ID=<APP_ID>
export ARM_CLIENT_SECRET=<CLIENT_SECRET>
export ARM_TENANT_ID=<TENANT_ID>
export ARM_SUBSCRIPTION_ID=<SUB_ID>
# (ワークロードID/OIDC の場合は認証アクションがトークンを供給。CLIENT_SECRET は不要)backend ブロックは静的で、変数補間は基本的に使えません。環境ごとに状態を分けるには、キー(key)を切り替えるか、コンテナを分けます。チーム運用では「プロジェクト/環境/コンポーネント.tfstate」の命名を徹底し、誤参照を防ぎます。
terraform init 時に -backend-config を渡して部分設定を埋めるパターンが実務的です。ワークスペース名をキーに反映する場合は、スクリプトで現在のワークスペースを取得し、init -reconfigure でキーを上書きします。
-backend-config とワークスペース連動の例
# 例) 各環境に応じて key を切替
RG=rg-tfstate
ST=sttfstate1234
CT=tfstate
WS=$(terraform workspace show)
KEY="projectA/${WS}/network.tfstate"
terraform init -reconfigure \
-backend-config="resource_group_name=${RG}" \
-backend-config="storage_account_name=${ST}" \
-backend-config="container_name=${CT}" \
-backend-config="key=${KEY}"
ロックは Blob のリースで実現され、並行 apply は拒否されます。プロセス異常終了でロックが残る場合、terraform force-unlock で解除します(ロックIDはエラーメッセージに表示)。
暗号化は既定で有効です。要件によりストレージ側で顧客管理キー(CMK)に切替可能です。状態のバージョニング/ソフトデリートを有効化しておくと、誤操作時のロールバックが容易です(旧バージョンを復元)。
ロック解除とバージョニングの確認
# ロック解除(メッセージに表示された LOCK_ID を使用)
terraform force-unlock -force 01234567-89ab-cdef-0123-456789abcdef
# バージョニング有効化はセクション2参照。復元は Portal/CLI で対象 Blob の過去版を復元
CI では非対話実行(-input=false)と確実な認証供給が鍵です。バックエンドの再設定が入る場合は -reconfigure を明示します。状態は機密情報を含み得るため、Plan ファイルの保管やログ出力に注意します。
よくあるエラーと対処: 403(AuthorizationPermissionMismatch) は RBAC 不足、コンテナ未作成や名前誤り、テナント/サブスクリプション不一致、並行ジョブによるロック競合が代表例です。
GitHub Actions の例(OIDC + Azure AD)
name: tf-apply
on: [workflow_dispatch]
jobs:
apply:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.6.6
- name: Init backend
run: |
terraform init -reconfigure \
-backend-config="resource_group_name=rg-tfstate" \
-backend-config="storage_account_name=sttfstate1234" \
-backend-config="container_name=tfstate" \
-backend-config="key=projectA/prod/app.tfstate"
- name: Plan
run: terraform plan -input=false -out=plan.tfplan
- name: Apply
run: terraform apply -input=false -auto-approve plan.tfplan
Associate / Pro
問題 1
Terraform の azurerm バックエンドで状態の同時更新を防ぐ仕組みとして正しいものはどれか。
正解: A
azurerm バックエンドは Azure Blob のリース機能で排他ロックを実現します。Queue の可視性タイムアウトや SMB ロックは本件に不適、Terraform Cloud 連携も必須ではありません。
ストレージ アクセスキーではなく Azure AD で認証できますか?
可能です。サービスプリンシパル、Managed Identity、Azure CLI ログイン、ワークロード ID(OIDC) を利用できます。RBAC として少なくとも Storage Blob Data Contributor を付与してください。
環境ごとに状態を分けるベストプラクティスは?
本番は専用コンテナまたは専用ストレージで分離し、非本番はキー命名(project/env/component.tfstate)で分けるのが一般的です。backend は静的のため、init 時の -backend-config で key を切替えます。
ロックが解除されず apply できません。どうすれば?
他の実行が残っていないか確認し、必要なら terraform force-unlock -force <LOCK_ID> を実行してください。頻発する場合は CI 側の直列化、タイムアウト設定、ジョブの排他制御を見直します。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...