Terraform

terraform planで変更差分を正確に読む(Associate向け・実務両対応)

2026-04-19
NicheeLab編集部

terraform planは、状態と実際のリソース、そして現在の構成から導かれる“これからの変更”を可視化します。誤解しやすいのは、planはあくまでシミュレーションであり、適用(apply)しない限りインフラは変わらないことです。

この記事では、差分記号の正しい読み方、主要オプションの使いどころ、CI/CDでの自動判定、ドリフト検出のコツまで、試験(Associate)と実務の両軸で整理します。

terraform planの基本と差分記号の読み方

terraform planは、現在の状態(state)と実環境の読み取り(デフォルトでrefresh)を踏まえ、構成(HCL)から導かれる実行計画を出力します。出力は“何がどの順で、なぜ変わるのか”を示すため、レビューとリスク低減の中心的な道具になります。

差分出力では、+が作成、-が削除、~がインプレース更新、-/+や+/-が置換(再作成)を意味します。属性単位でも~が付きますが、リソース行頭が-/+の場合は破壊と再作成が必要な変更であることを示します。

  • planは実際の変更を行わない。適用はterraform applyで行う。
  • デフォルトでrefresh(実リソースの再読み取り)を行う。制御は-refreshフラグで可能。
  • 出力の順序は依存関係に基づく。破壊→作成の順で安全性が考慮される。
  • 保存した計画ファイル(-out)は、同一ワークスペース・同一設定でのみ有効。
記号/表示意味代表例
+新規作成新しいaws_s3_bucketの追加
-削除不要になったaws_security_groupの削除
~設定のインプレース更新タグの値変更、retention_periodの更新
-/+ または +/-置換(破壊→作成)immutable属性変更、インスタンスタイプ変更で再作成が必要な場合

planの位置づけ(構成→計画→適用)

読み取り読み書きHCL (構成)desired stateterraform planシミュレーション出力実リソース (API)現状を取得状態ファイル (state)読み書き (refresh)plan は HCL/state/実リソースから差分を算出するシミュレーション。実変更は apply のみ

最小手順と出力保存

terraform init
terraform plan -out=plan.tfplan
# レビュワーは plan.tfplan を
# terraform show plan.tfplan で確認可能

差分の精度を高める主要オプション

運用では、ドリフト検出や限定的な影響確認のためにオプションを使い分けます。-refresh=falseで外部の再読み取りを抑制すると、ネットワーク不安定時の暫定評価に役立ちますが、最新の実態を反映しないためリスクが上がります。

-refresh-onlyは、実リソースに変更を加えずにstateだけを最新化する計画を作ります。変更の適用はterraform apply -refresh-onlyで行われ、外形的には“差分ゼロ化(state同期)”の動きになります。

  • -replace=アドレス で明示的な置換計画を作成できる(taintの代替)。
  • -destroy で“破壊のみ”の計画を作成(最終撤去の安全確認に有用)。
  • -var-file や -var は計画に使う入力値を固定化し、再現性を高める。
オプション目的注意点
-refresh=false外部読み取りを抑制ドリフトを見落とすリスク。最終判断には不向き
-refresh-onlystateのみ最新化する計画apply -refresh-onlyで適用。リソース自体は変更しない
-replace=addr特定リソースの再作成を強制影響範囲をよく確認。依存リソースへの波及に注意
-destroy破壊計画の作成意図しない削除防止のため、レビューを厳格化
-target=addr限定スコープで計画恒常運用は非推奨。依存解決の抜け漏れを招きやすい

refresh-onlyのイメージ

実リソースAPI から現状を取得読み取り変更は加えないstate同期のみ更新refresh-only は実リソースから state を同期するだけで、リソース自体は変更しない

代表的な組み合わせ例

# ドリフト確認を厳密に
terraform plan

# ネットワーク不調時の暫定差分確認(最終判断は避ける)
terraform plan -refresh=false

# stateを最新化するだけの計画
terraform plan -refresh-only

# 特定リソースの置換
terraform plan -replace=aws_instance.web

CI/CDでの自動判定と計画の共有

CIでは-detailed-exitcodeで差分の有無を機械判定します。0は差分なし、2は差分あり、1はエラーです。PRにplan出力をコメント化する運用も一般的です。

計画の再現性を高めるため、-outでバイナリ計画ファイルを生成し、terraform show -jsonで機械可読化します。計画ファイルはTerraformのバージョン・バックエンド・ワークスペースに依存するため、別環境への持ち回りは避けます。

  • plan → レビュー → 承認 → apply の分離で権限最小化を実現。
  • 保存済みplanをapplyすると承認プロンプトは表示されない(無人適用に適合)。
  • JSON化により差分の可視化ダッシュボードを作成可能。
ユースケースコマンド戻り値/出力
PRで差分有無を判定terraform plan -detailed-exitcode0:なし / 2:あり / 1:失敗
計画の固定と共有terraform plan -out=plan.tfplanapply時に承認なしで適用
機械可読なレビューterraform show -json plan.tfplanJSONで差分詳細を抽出可能

CIパイプラインの典型

CommitPR pushterraform plan -detailed-exitcode0: 変更なし / 2: 変更あり / 1: 失敗レビュー/承認exit 2 の場合のみterraform apply plan.tfplan保存された計画を無人で適用exit 2 (差分あり) はレビュー/承認を挟んで apply、exit 0 は終了

Bash例: 差分ありのみ失敗させる

set -euo pipefail
terraform init
if terraform plan -detailed-exitcode -out=plan.tfplan; then
  echo "No changes"
else
  code=$?
  if [ "$code" -eq 2 ]; then
    echo "Changes detected" >&2
    terraform show -json plan.tfplan > plan.json
    exit 2
  else
    echo "Plan failed" >&2
    exit $code
  fi
fi

実務のパターンと落とし穴(ドリフト、インポート、未知値)

既存リソースが手作業で変更されている場合、planは~または-/+としてドリフトを示します。既存資産の取り込みはterraform importでstateに紐付けてから行うのが安全です。

データソースや未確定の値(apply時決定値)はplanでunknownとして扱われることがあります。unknownが置換要件を引き起こさないか、注意深く読みます。

  • ドリフトの常時監視には、定期的なplan実行が有効。
  • import前の構成は既存と一致させる(名前・タグ・重要属性)。
  • unknownが多い場合は依存関係やlifecycleの設定を見直す。
状況planの症状対処
手作業変更あり~ または -/+ が多数terraform planで差分確認→構成を修正 or import
既存資産を管理下へリソース新規作成提案terraform importでstateに取り込み
未確定値が多いunknown値が散見depends_onやoutput/variable設計の見直し

ドリフト検出の流れ

実リソース (現状)手作業変更を含むstaterefresh で最新化plan差分の可視化applystate/実体を同期refresh で state を最新化 → plan で差分を可視化 → apply で同期

インポートと最小差分の作り方

# 既存S3バケットをstateへ取り込み
# 事前にHCLを既存設定に合わせておく
terraform import aws_s3_bucket.logs my-existing-logs-bucket
terraform plan  # ドリフトが解消されていることを確認

Associate試験で問われやすい論点

planは提案であり、applyのみが変更を実行すること。-detailed-exitcodeの意味、-outで保存した計画をapplyすると承認なしで適用されることは頻出です。

-targetは恒常運用の推奨ではない、-destroyは破壊計画を作る、-refresh-onlyはstate同期のための計画を作る、といった“意図の違い”が問われます。

  • exit code: 0=変更なし, 2=変更あり, 1=失敗。
  • 保存計画の適用ではプロンプトが出ない(無人化できる)。
  • planのJSONはterraform show -jsonで取得する(plan自体はJSON直接出力しない)。
トピック正答要点よくある誤答/混同
planの役割変更のシミュレーションplanが変更を実行する
-detailed-exitcode0/2/1の三値で判定0と2の違いを混同
保存計画の適用apply plan.tfplanは承認なし-auto-approveが必須と誤解
JSON出力show -json plan.tfplanplanに直接 -json があると誤解

試験での意思決定チャート(簡略)

はいいいえはいいいえ差分を機械判定したい?CI での自動判定plan -detailed-exitcodeexit 0/2/1 で判定通常の plan対話的レビュー保存して適用したい?無人適用の要否plan -out && apply plan.tfplan再計算なし・承認なしapply再計算あり目的別に plan オプションを選択する意思決定チャート

試験頻出コマンドサマリ

# 差分の有無だけ知る
terraform plan -detailed-exitcode

# 破壊計画
terraform plan -destroy

# 保存→適用
terraform plan -out=plan.tfplan
terraform apply plan.tfplan

# JSONでレビュー
terraform show -json plan.tfplan > plan.json

トラブルシュート:置換・移動・ロック・権限

planで“forces replacement”が出たら、immutable属性が変わっていないか確認します。仕様上の再作成が必要な場合は、-replaceで明示的に意図を示すと安全です。

リソース名の変更やモジュール再編ではmovedブロックを使うと、destroy/createを避けてstateを自動移行できます。バックエンドのロック競合や認可エラーはplan以前の問題として検出されるため、まずは資格情報とロック状態を確認します。

  • movedブロックで安全な改名。state mvの代替として推奨。
  • バックエンドのロックは解放を待つ。強制解放は最終手段。
  • プロバイダの権限不足はplanのrefresh段階で失敗しがち。
事象原因対策
forces replacementimmutable属性変更/仕様-replaceで意図を明示、メンテナンス計画
destroy提案(改名時)state未移行movedブロックで自動移行
Lock情報で失敗他のプロセスがロック完了待ち/CIジョブの直列化
認可エラークレデンシャル不足プロバイダ認証を見直し

改名時のmovedブロック適用イメージ

plan は moved を表示aws_instance.old_namebefore (旧アドレス)moved { from, to }宣言で state を移行aws_instance.new_nameafter (新アドレス)Terraform state紐付けのみ更新 / 実体は維持moved ブロックで state の紐付けを切り替え、破壊/再作成を回避

movedブロックと置換の明示

# main.tf(Terraform 1.x系)
moved {
  from = aws_instance.old_name
  to   = aws_instance.new_name
}

# 不可避の再作成を明示
# terraform plan -replace=aws_instance.web

問題で確認

Associate

問題 1

CIでterraform planを実行し、差分がある場合だけPRを失敗させたい。最小限の実装として適切なのはどれか?

  1. terraform plan -detailed-exitcodeを使い、終了コード2を検出して失敗させる
  2. terraform planの標準出力をgrepし、+や~があれば失敗させる
  3. terraform plan -out後にterraform apply plan.tfplanを実行し、変更があれば失敗させる
  4. terraform plan -refresh=falseを使い、毎回同じ出力にして比較する

正解: A

公式にサポートされる方法は-detailed-exitcodeでの機械判定。終了コード0は変更なし、2は変更あり、1は失敗。出力のgrepは不安定で非推奨。applyは計画の実行でありCIで失敗検知目的に使うべきではない。-refresh=falseは差分の正確性を損なう。

よくある質問

terraform planは本当に何も変更しませんか?

はい。planは実行計画の算出と表示のみです。実リソースが変更されるのはterraform apply(またはdestroy)を実行したときだけです。

保存した計画ファイル(plan.tfplan)は別の環境で再利用できますか?

推奨されません。計画ファイルはTerraformのバージョン、バックエンド、ワークスペース、変数に依存します。生成したのと同じ環境で速やかに適用する前提で使います。

JSONで差分を取りたいのですが、terraform planに-jsonはありますか?

plan自体には-jsonはありません。terraform plan -outで計画を保存し、terraform show -json plan.tfplanでJSONを取得します。

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

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の記事一覧 (101件)
© 2026 NicheeLab All rights reserved.