そう思って使い始めたところ、次の全体適用でサービス断が発生した——現場でよく聞くインシデントです。
`terraform apply -target` は、Terraform のオプションのなかでも「正しく使えば有効、乱用すると危険」の差が最も大きい機能の一つです。公式ドキュメントでも「通常運用での使用は推奨しない(escape hatch)」と明記されているにもかかわらず、日常的に使ってしまっているチームが後を絶ちません。
この記事では、`-target` の仕組みと正当な使い道、危険な乱用パターン、そして `-target` に頼らなくて済む設計への移行方法を実務目線で解説します。Terraform 1.8系 / RHEL 9.4 環境で動作確認しています。
この記事のポイント
・terraform apply -targetは「緊急避難のオプション」であり通常運用向けではない
・乱用するとtfstateの整合性が崩れ、次の全体applyで予期しない変更が発生する
・正当な用途は「壊れたリソースのピンポイント再作成」「ドリフトした単一リソースの修正」の2つ
・-targetに頼る設計はモジュール分割やdepends_onで根本解決できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
terraform apply -targetとは何か
`terraform apply -target` は、Terraform の変更適用を特定のリソース(またはモジュール)のみに絞り込むオプションです。通常の `terraform apply` はステートファイル全体を参照してすべての差分を適用しますが、`-target` を使うと指定したリソースだけを操作対象にできます。
# 特定リソースのみ適用 terraform apply -target="aws_instance.web" # モジュール全体を対象にすることもできる terraform apply -target="module.vpc" # 複数指定も可能 terraform apply -target="aws_instance.web" -target="aws_security_group.app"
$ terraform plan -target="aws_instance.web" Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_instance.web will be updated in-place ~ resource "aws_instance" "web" { ~ instance_type = "t3.micro" -> "t3.small" id = "i-0a1b2c3d4e5f67890" tags = { "Name" = "web-prod-01" "Env" = "production" } # (28 unchanged attributes hidden) } Plan: 0 to add, 1 to change, 0 to destroy. ╷ │ Warning: Resource targeting is in effect │ │ You are creating a plan with the -target option, which means that the │ result of this plan may not represent all of the changes required to │ synchronize your real infrastructure with your configuration. │ │ The -target option is not for routine use, and is provided only for │ exceptional circumstances such as recovering from errors or mistakes. ╵
-targetが正当に使える場面
1. 壊れたリソースのピンポイント再作成
本番環境で特定のリソースだけが壊れており、他のリソースへの影響を最小化して再作成したい場面で有効です。`terraform taint` でリソースを再作成対象にマークしてから `-target` で適用するパターンです。# Terraform 1.x 以降: taint は非推奨。-replace を使う $ terraform apply -replace="aws_security_group.app" -target="aws_security_group.app" # Terraform 0.15.x 以前の場合 $ terraform taint aws_security_group.app $ terraform apply -target="aws_security_group.app"
2. ドリフトした単一リソースの修正
手動操作(コンソール直接変更等)でドリフトが発生した特定リソースだけをコード定義に戻したい場合です。# まずドリフトの内容を確認 $ terraform plan -refresh-only -target="aws_security_group.app" # 確認後、対象リソースのみコード定義に戻す $ terraform apply -target="aws_security_group.app" Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
3. 大規模なモジュール追加の一時的な段階確認
新しいモジュールを追加して全体 plan を実行したとき、差分が多すぎて確認しきれない場合にモジュール単位で分割して確認・適用するケースがあります。ただしこれは「一時的な対処」であり、本来はモジュールを別ルートに分離することが正しい設計です。
-targetの危険な乱用パターン
1. ステートの整合性が崩れる
`-target` を使って一部のリソースだけを適用すると、ステートファイルが「中途半端な状態」になります。他のリソースとの依存関係が更新されないまま、特定のリソースだけが変更されるためです。実際のインシデント例として、ECSタスク定義のみを `-target` で更新し、ALBのターゲットグループは旧設定のまま放置したケースがあります。次の `terraform apply`(全体適用)でALBが予期しない再設定を受け、本番サービスが2時間停止しました。
# 危険なパターン: ECSタスク定義のみ適用 $ terraform apply -target="aws_ecs_task_definition.app" # ALBのターゲットグループとの依存関係は更新されていない状態で... # 後日、全体applyを実行すると $ terraform apply # → ALBの設定が予期しない内容で変更されサービス断
2. 「一時的な使用」が常態化する
「今回だけ」で使った `-target` がチームの慣習になってしまうケースが非常に多いです。コードには `aws_rds_cluster` と `aws_elasticache_cluster` の両方が定義されているが、RDSだけ先に作って ElastiCache は後でと言いながら、両者の依存部分が中途半端なまま何週間も経過する——こうした状況が現場でよく起きます。
3. planとapplyの乖離が発生する
CIパイプラインで `terraform plan` の結果を確認してから `terraform apply` を承認する運用をしている場合、`-target` を使ったapplyは「承認した内容と異なる変更が入る」状態を作り出す可能性があります。# NG: planは全体、applyはターゲット指定(別物になる) $ terraform plan # 全リソースの差分を確認してチームがレビュー承認 $ terraform apply -target="aws_instance.web" # 一部のみ適用 # → レビューした内容と適用内容が一致しない状態になる
4. 公式の警告を「無視」する習慣がつく
HashiCorp の公式ドキュメントには以下の記述があります。「The -target option is an escape hatch for exceptional situations, and by using it in this way you are doing something that Terraform normally would not allow, and potentially bypassing important safety checks.」(-target は例外的な状況のための逃げ道であり、Terraform が通常許可しないことを実行しており、重要なセーフティチェックをバイパスする可能性がある)
この警告を毎回読み飛ばしているうちに、セーフティチェックの重要性への感覚が麻痺していきます。
>> Terraform実践セミナーの詳細はこちら
-targetに頼らない設計パターン
1. モジュール分割で「部分適用の必要性」をなくす
「一部だけ先に適用したい」という要求の多くは、モジュールの粒度が粗いことが原因です。VPC・コンピュート・データ層を別モジュールに分割すると、モジュール単位で安全に適用できます。# modules/ を責務で分割する例 module "network" { source = "./modules/network" } module "compute" { source = "./modules/compute" vpc_id = module.network.vpc_id subnet_ids = module.network.private_subnet_ids } module "data" { source = "./modules/data" subnet_ids = module.network.private_subnet_ids }
2. depends_onで依存関係を明示する
リソース間の依存が暗黙になっているため `-target` に頼ってしまう場合、`depends_on` で明示することで Terraform が正しい順番で自動適用するようになります。resource "aws_security_group" "app" { name = "app-sg" vpc_id = aws_vpc.main.id # ... } resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro" # 暗黙依存では不十分な場合に明示する depends_on = [aws_security_group.app] }
3. terraform planの差分を読む力をつける
`-target` に逃げる最大の理由の一つは「全体 plan の差分が多くて怖い」という心理的な問題です。差分を正確に読む習慣をつけることで、不必要な `-target` 使用を避けられます。・Plan の `~`(update)と `+/-`(replace)を区別する:`~` はインプレース変更でサービス断なし、`+/-` はリソース再作成でサービス断あり
・大きな差分は `terraform plan -out=plan.tfplan && terraform show -json plan.tfplan | jq` でJSON化して確認:差分の全量を把握してから適用判断する
・CIのplan結果をPRにコメントで表示:atlantis や GitHub Actions でplanをコードレビューの一部にすることで「怖いから-target」を回避できる
-targetでステートが乱れた場合のトラブル対処と安全な使用フロー
「-targetは絶対禁止」ではなく「適切な文脈でのみ使う」が正しい姿勢です。緊急時に `-target` を使う場合の安全な手順を示します。1. 使用前に全体planを保存する
# ターゲット指定の前に全体の差分を保存しておく $ terraform plan -out=full.plan $ terraform show full.plan > full_plan_before_target.txt # その後ターゲット指定でapply $ terraform apply -target="aws_instance.web"
2. 使用後に全体planでクリーンアップを確認する
# -target apply後、必ず全体planで差分残りがないか確認 $ terraform plan # 差分が残っている場合は速やかに全体適用する # (放置するとステート整合性が崩れたまま時間が経過する) $ terraform apply
3. 使用記録をチケット・コメントに残す
「なぜ -target を使ったか」「使用後の全体plan確認結果」をチケットやコメントに記録します。ドキュメントなしで `-target` が習慣化するのが最大のリスクです。本記事のまとめ
| 項目 | 内容 |
|---|---|
| -targetの本来の位置づけ | 緊急避難の「escape hatch」。通常運用での使用は公式非推奨 |
| 正当な用途1 | 壊れたリソースの緊急再作成(-replace と組み合わせて使う) |
| 正当な用途2 | ドリフトした単一リソースのコード定義への修正 |
| 危険な乱用パターン | 日常的な部分適用・planとapplyの乖離・ステート整合性の崩壊 |
| 根本解決の設計 | モジュール分割・depends_on明示・CI/CDでのplan可視化 |
| 緊急時の最低限のルール | 使用前に全体planを保存 → 使用後に全体planで整合性を確認 |
Terraform の設計パターンをさらに深めたい方は、以下の関連記事も参照してください。
・Terraformのmoduleとfor_each・countで構成を再利用する設計パターン
・Terraformのlifecycleブロックで本番リソースを誤削除から守る方法
・Terraformのplan・applyエラーを調査・解決する方法|TF_LOG・Stateロック・ドリフトを実践的に切り分ける
>> Terraform実践セミナーの詳細はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Terraformで複数AWSアカウントをまたぐ設計|provider aliasとassume_roleでマルチアカウント構成を実装する方法
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます