Terraform

Terraform State の基礎: 状態管理の中心概念を正しく押さえる

2026-04-19
NicheeLab編集部

Terraform は実行結果を State として保存し、次回以降の計画・適用の基準にします。State を正しく設計・保護できないと、差分が壊れたり、並行実行で競合が発生します。

本稿では公式ドキュメントの挙動に基づき、Associate で問われやすい安定概念を中心に、試験対策と現場運用に共通するベストプラクティスをまとめます。

Terraform State とは何か

State は、Terraform が「構成で宣言したリソース」と「実際のクラウド上のリソース」を対応付けるためのデータです。各リソースのアドレス、属性値、依存関係、出力値などを保持し、次回 plan/apply の差分計算の土台になります。

State がなければ、Terraform は毎回“ゼロから”現況を解析する必要があり、リネームやリファクタでの安全なマッピングも困難です。State は単なるキャッシュではなく、実行の整合性を支える中核データです。

デフォルトでは terraform.tfstate(ローカル)に保存されますが、実務では並行実行・バックアップ・権限制御のためにリモートバックエンド(S3、AzureRM、Terraform Cloud など)を用いるのが一般的です。

  • State は差分計算とリソースの同一性維持に必須
  • ローカル保存は学習・個人検証向け、チーム運用はリモート推奨
  • State を編集するのは最終手段。通常は state サブコマンドで操作

Terraform 実行時の State の位置づけ

plan/applyreads/writeslockreads real infraTerraform ConfigProviders (AWS/GCP/..)Backend (State)local/S3/AzureRM/TFCLock storeDynamoDB/Blob/TFC

バックエンドの選択: ローカル vs リモート

バックエンドは State の保存先とロック手段を決めます。チーム運用では、同時実行の競合を避け、履歴とアクセス制御を確保できるリモートバックエンドを選ぶのが基本です。

代表的な選択肢の特徴は以下の通りです。S3 は DynamoDB と組み合わせることでロックを提供。AzureRM は Blob のリースでロック。GCS はロック未対応のため単一実行を徹底。Terraform Cloud/Enterprise はロック・履歴・RBAC を包括的に提供します。

  • チーム運用は“ロックと履歴”が鍵
  • S3 は DynamoDB テーブルでロックを有効化
  • GCS はロック未対応のため CI の同時実行制御で回避
  • Terraform Cloud は最小設定でロック・履歴・権限を一括提供
バックエンドロック暗号化(At Rest)バージョニング/履歴
localなしOS 権限のみ手動バックアップ
S3 (+DynamoDB)あり(DynamoDB Lock)SSE-S3 / SSE-KMSS3 バージョニング
AzureRM (Blob)あり(Blob リース)Storage 既定暗号化Blob バージョニング/Soft delete
GCSなしGoogle 管理鍵 or CMEKObject Versioning
Terraform Cloud/Enterpriseありサービス側で管理状態履歴・Run ログ

S3 バックエンド(ロック有効)の例

terraform {
  backend "s3" {
    bucket         = "my-tf-state"
    key            = "envs/prod/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "tf-state-lock"
    encrypt        = true
  }
}

状態の更新と操作コマンド

plan と apply の過程で Terraform は実インフラの現況を読み直し、State を最新化します。過去の手動変更(ドリフト)があれば差分として検出します。現況の再取得だけを行いたい場合は、refresh-only の適用が使えます。

State の直接編集は避け、terraform state サブコマンドでアドレス変更(mv)や切り離し(rm)などを行います。push/pull は復旧などの特殊な用途に限定しましょう。

  • 差分は plan、反映は apply で実施
  • 現況のみ再取得: terraform apply -refresh-only
  • アドレス変更は terraform state mv を使う
  • 孤児の切り離しは terraform state rm(削除はしない)

よく使う状態操作コマンド

terraform init
terraform plan

# 状態に登録済みリソースの一覧
terraform state list

# リファクタ時のアドレス変更(計画なしで State を更新)
terraform state mv aws_instance.web[0] aws_instance.app[0]

# 孤児化したエントリの切り離し(実インフラは削除しない)
terraform state rm aws_security_group.legacy

# 現況の再取得のみ(構成は変更せず State を更新)
terraform apply -refresh-only

ロックと並行実行の制御

State ロックは、複数の実行が同時に State を更新して破損するのを防ぐ仕組みです。ローカルバックエンドはロックがないため、チーム運用には不向きです。S3 は DynamoDB のロックレコード、AzureRM は Blob リース、Terraform Cloud はサービス側でロックを提供します。

CI/CD では、バックエンドのロックに加え、同一ワークスペースの実行を直列化する設定が有効です。GCS のようにロック未対応のバックエンドでは特に必須です。

  • ローカルはロックなし。チームでは使用を避ける
  • S3 は DynamoDB テーブル作成が前提(LockID パーティションキー)
  • AzureRM は Blob リースで排他
  • CI で同一ワークスペースの直列化を徹底(例: 一度に 1 job)

DynamoDB ロックテーブル作成例(S3 バックエンド用)

aws dynamodb create-table \
  --table-name tf-state-lock \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

状態ファイルの中身とセキュリティ

State には、作成したリソースの属性や依存だけでなく、出力値や一部の機密情報が含まれる場合があります。変数や出力に sensitive フラグを付けても、State 自体には値が保持され得るため、State は機密情報として扱うのが前提です。

リモートバックエンドでは暗号化(SSE-KMS、Storage 既定暗号化など)と厳格な IAM/RBAC を設定し、バケット/コンテナのバージョニングや削除保護を有効化して誤消去や破損に備えます。State を VCS にコミットしないのは鉄則です。

  • State は機密データを含み得るため閲覧権限を最小化
  • バージョニングとサーバーサイド暗号化を有効化
  • State を Git 等にコミットしない
  • remote_state(data ソース)での共有は必要最小限に

機密値の扱い例(State には依然含まれ得る)

variable "db_password" {
  type      = string
  sensitive = true
}

output "db_password" {
  value     = var.db_password
  sensitive = true
}
# 注: sensitive は UI/ログ表示を抑制するフラグ。State から値が完全に排除されるわけではない。

インポートとドリフト対応

既存リソースを Terraform 管理下に置くには、State に取り込む必要があります。従来の terraform import コマンドで State に登録し、HCL を手で整える方法が一般的です。最近のバージョンでは import ブロックを構成に記述する方法も利用できます(利用可否は使用バージョンに依存)。

ドリフトが発生した場合は、まず plan で差分を確認し、構成を正として apply で収束させるか、必要に応じて state サブコマンドで整合を取り戻します。State の手編集は最後の手段です。

  • import 後は HCL を構成の真実に合わせて整える
  • plan で差分を可視化、apply で収束
  • state mv/rm は“構成どおりに戻す”ための手段
  • 手編集は復旧時の最終手段として限定

インポートの例(CLI と import ブロック)

# 既存の S3 バケットを State に取り込む(従来の CLI)
terraform import aws_s3_bucket.logs my-logs-bucket

# 設定ファイルに import ブロックを記述する方法(対応バージョンのみ)
import {
  id = "my-logs-bucket"
  to = aws_s3_bucket.logs
}

resource "aws_s3_bucket" "logs" {
  bucket = "my-logs-bucket"
}

問題で確認

Associate

問題 1

チームでの本番運用において、State の破損や並行実行の競合を最も確実に防ぐバックエンド構成はどれですか?

  1. S3 バックエンドを使用し、DynamoDB テーブルでロックを有効化する
  2. GCS バックエンドを使用し、バケットのバージョニングのみを有効化する
  3. ローカルバックエンドを使用し、OS のファイルロックに任せる
  4. どのバックエンドも使わず、毎回 plan のみを実行する

正解: A

S3 バックエンドは DynamoDB のロックと組み合わせることで State の排他制御を提供します。GCS はロック未対応、ローカルはロックがなく、plan のみでは競合を防げません。

よくある質問

バックエンドを変更する際、既存の State はどう移行すべきですか?

terraform init 実行時に -migrate-state を使用して安全に移行します。事前に新旧バックエンドのアクセス権限と暗号化・バージョニング設定を確認し、移行後に plan で差分がないことを検証してください。

terraform.tfstate を Git などの VCS にコミットしても良いですか?

推奨されません。State には機密情報が含まれ得ます。リモートバックエンドを使用し、アクセス制御・暗号化・履歴で保護するのがベストプラクティスです。

ワークスペースで本番・開発を分離しても安全ですか?

小規模では有効な場合もありますが、権限や監査の分離には不十分です。環境ごとにバックエンドやステートパスを分け、IAM/RBAC を独立させる方が安全です。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Terraform

Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける

Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...

Terraform

Terraform Authoring & Ops Pro: 上位資格の範囲と対策

上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...

Terraform

Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす

Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...

Terraform

Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義

Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...

Terraform

Terraform Data Source徹底理解:既存リソースの参照で壊さず足す

Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...

Terraformの記事一覧 (102件)
© 2026 NicheeLab All rights reserved.