Terraform planを正確に読む方法|変更・追加・削除・再作成の差分記号とknown after applyの解説

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Terraform > Terraform planを正確に読む方法|変更・追加・削除・再作成の差分記号とknown after applyの解説
「terraform applyを実行したら、意図しないリソースが削除された」

このような事故は、terraform planの出力を流し読みして実行ボタンを押した時に起きる。planは実行計画を表示してくれるが、差分記号の意味を正確に理解していないと「削除が含まれていた」「リソースが再作成された」ことに気づけない。

この記事では、terraform planが出力する差分記号(~・+・-・-/+)とknown after applyの意味を実機出力で解説する。planを流し読みせず、本当に安全かを判断できるようになる思考手順を身につけることが目標だ。

この記事のポイント

・差分記号(~ ・ + ・ - ・ -/+)は5種類で意味と危険度が異なる
・-/+(再作成)はdestroyカウントに含まれない場合があり最も見落としやすい
・known after applyは正常。依存チェーンの追い方を解説
・想定外の差分は-refresh-onlyでドリフト確認後に対処する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

terraform planを正確に読めるとどう変わるか

terraform planの役割は「変更内容を事前確認する」ことだが、出力を誤読すると計画がセーフガードとして機能しない。

特に次の2つのケースで誤読が起きやすい。

・~(変更)だと思っていたら、実際は-/+(破壊的再作成)だった
・known after applyが含まれるリソースを「確認できた」と判断してapplyした

どちらも、applyが完了するまで本番の変化が見えない状態で判断している。planの読み方を習得することは、Terraformを安全に運用するための最初のステップだ。

差分記号が表す5種類の意味

terraform planの出力は、行頭の記号でリソースに何が起きるかを示す。

以下はRHEL 9.4 / Ubuntu 24.04 LTS環境のTerraform 1.9で実行した、EC2追加とセキュリティグループ変更のplan出力例だ。

$ terraform plan Terraform will perform the following actions: # aws_instance.web_server will be created + resource "aws_instance" "web_server" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t3.micro" + id = (known after apply) + public_ip = (known after apply) + tags = { + "Name" = "web-server-prod" } } # aws_security_group.web will be updated in-place ~ resource "aws_security_group" "web" { id = "sg-0a1b2c3d4e5f67890" ~ ingress = [ - { - from_port = 8080 - to_port = 8080 - protocol = "tcp" }, + { + from_port = 443 + to_port = 443 + protocol = "tcp" }, ] } Plan: 1 to add, 1 to change, 0 to destroy.

末尾の「1 to add, 1 to change, 0 to destroy.」がサマリーだ。destroyが0でも、後述の-/+(再作成)が含まれることがあるため、サマリーだけで判断するのは危険だ。

1. ~(チルダ): インプレース変更

~はリソースを削除せず、属性だけを変更する。セキュリティグループのルール変更、タグの追加など、稼働したまま適用できる変更だ。~の内側にある-と+は属性値の変更前後を示す。

2. +(プラス): 新規作成

+は新しいリソースを作成する。既存リソースには影響しない。

3. -(マイナス): 削除

-はリソースを削除する。Plan: X to destroy.にカウントされる。意図的な削除でない場合は即座に中断して原因を確認する。

4. -/+: 破壊的再作成(最重要)

最も注意が必要な記号だ。-/+は一度削除してから再作成する。サマリーの「X to destroy.」にカウントされない場合があり、見落としやすい。

-/+が発生する典型的なケース:

・RDSのengine_versionを変更した
・EC2のamiを変更した
・セキュリティグループのVPC参照を変更しようとした
・IAMロールのポリシーを特定の方法で差し替えた

plan出力では変更行の末尾に # forces replacement と表示される。

# aws_db_instance.main must be replaced -/+ resource "aws_db_instance" "main" { ~ engine_version = "8.0.32" -> "8.0.36" # forces replacement id = "db-ABCDEF1234567890" instance_class = "db.t3.medium" ... } Plan: 1 to add, 0 to change, 1 to destroy.

本番DBを再作成する変更は、マルチAZ構成のフェイルオーバー確認や事前スナップショット取得とセットで計画する必要がある。

5. <=(less than equal): data sourceの読み込み

<=はdataブロック(data source)で外部リソースを参照する操作を表す。リソースの変更ではないが、apply時にAPIリクエストが発生して最新情報を取得する。

known after applyとは何か

plan時点では確定できず、applyが完了した後に初めて値が決まる属性に(known after apply)が表示される。

idやpublic_ipのようにAWSが採番・割り当てる値は必ずknown after applyになる。この表示自体は正常だ。

問題になるのは、downstream側のリソースがknown after applyの値を参照している場合だ。例えばRoute 53のAレコードにaws_instance.web_server.public_ipを設定していると、EC2が作成されるまでDNSの値が確定しない。

複数リソースが絡む依存チェーンでは、plan出力でknown after applyの伝播範囲を追う必要がある。連鎖的にknown after applyが増える場合は、terraform graphで依存関係を可視化して全体像を把握するのが有効だ。

TerraformのIaC設計やマルチリソース構成のベストプラクティスは、Terraform実践入門講座でまとめて学ぶことができる。

forces replacementに気づくための確認手順

planの出力が長い場合、-/+をスキップしてしまいやすい。applyの前に次の手順で確認する。

1. サマリー行を確認する

Plan: 2 to add, 1 to change, 1 to destroy.

destroyが含まれている場合は、どのリソースかを必ず特定する。ただしdestroyが0でも-/+が含まれる場合があるため、次のステップも省略しない。

2. planをファイルに保存してgrepで絞り込む

planの出力が数百行に及ぶ場合は、ファイルに保存してgrepで確認するのが確実だ。

# planをバイナリ形式で保存 terraform plan -out=plan.tfplan # 人が読めるテキスト形式に変換 terraform show -no-color plan.tfplan > plan.txt # 再作成対象だけを抽出 grep -E 'must be replaced|forces replacement' plan.txt

このgrepが空であれば再作成は含まれていない。

3. 削除対象リソースを本番と照合する

-が付いたリソースのIDやNameタグを確認し、本番の何に対応するかを確かめてから判断する。Terraform stateのIDと本番コンソールのリソースIDを突き合わせることで、意図しない削除を防げる。

planで想定外の差分が出た時のトラブルシュート

1. 差分が多すぎる場合は -refresh-only で手動変更を先に確認する

コンソールやAWS CLIで手動変更が加えられた場合、planが大量の差分を出力することがある。この場合は先に-refresh-onlyで現状を把握する。

terraform plan -refresh-only

この出力にはリソースの「現在の状態」と「stateファイルの記録」の乖離だけが表示される。どこで手動変更されたかを特定できたら、乖離を解消してから通常のterraform applyに進む。

2. 意図しない再作成が含まれる場合は lifecycle ignore_changes を検討する

AutoScalingやECSがAPIで動的に変更する属性(desired_countなど)を毎回differenceとして拾ってしまう場合は、lifecycleブロックのignore_changesで除外する。

resource "aws_ecs_service" "api" { # ... lifecycle { ignore_changes = [desired_count] } }

ただしignore_changesは設定ファイルとstateの乖離を意図的に許容するため、使いどころを絞ること。全属性をallで除外するのは避ける。

3. コードを変えていないのにdestroyが含まれる場合

stateファイルとAWSの実リソースのID対応がズレている可能性がある。次のコマンドで確認する。

# stateが管理しているリソースを一覧確認 terraform state list # 特定リソースのstate詳細を確認 terraform state show aws_instance.web_server

stateには古いリソースIDが残っていて、AWSでは既に削除済みというケースが典型的だ。この場合はterraform state rmでstateから除外してからplanを再実行する。

本記事のまとめ

記号 意味 注意度
+ 新規作成 低(既存リソースへの影響なし)
~(チルダ) インプレース変更 中(変更内容を目視確認する)
- 削除 高(意図的な削除か確認必須)
-/+ 破壊的再作成 最高(本番DBや固定IPは特に注意)
<= data source読み込み 低(変更ではなく参照)
(known after apply) apply後に確定する属性 中(downstream依存を追う)
planを安全に読む原則をまとめる。

・Plan: X to destroy.がゼロでも、-/+がないかgrepで必ず確認する
・known after applyはそれ自体は正常だが、依存チェーンの伝播を追う
・想定外の差分は-refresh-onlyでドリフト確認を先に行う
・大規模なplanはファイルに保存してgrepで絞り込む

terraform planを「おまじない」として流し読みするのをやめ、意思決定の根拠として活用できるようになると、applyによる事故は大幅に減る。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Terraform実践入門講座では、HCL設計の基礎からstateの安全な管理、チーム開発での運用設計まで実機ハンズオンで学べます。terraform planの読み方を起点に、安全なapplyまでの全工程を体系的に習得できます。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。