Terraform

Terraform lifecycle メタ引数を正しく使い分ける: create_before_destroy などの実務・試験対策

2026-04-19
NicheeLab編集部

Terraform の lifecycle メタ引数は、変更の順序や破壊的変更の抑制、意図的な置換トリガーなど、デプロイの安全性と可観測性に直結します。

この記事では公式ドキュメントの挙動に沿って、よく問われる create_before_destroy を軸に注意点をまとめ、試験(Associate/Pro)での出題パターンと実務パターンを短時間で復習できるように構成しました。

lifecycle メタ引数の基礎

lifecycle は各リソース(および一部の最近の Terraform ではモジュール)に指定できるメタ引数で、Plan/Apply における更新戦略を制御します。代表的なものは create_before_destroy(置換時の順序制御)、prevent_destroy(意図しない削除の防止)、ignore_changes(特定属性の差分無視)、replace_triggered_by(外部の変更で置換を強制)です。

重要な前提として、Terraform は宣言的な依存グラフに基づきプランを構築します。lifecycle はそのグラフ上の順序や置換判定にヒントを与えますが、最終的な挙動は各プロバイダとリモート API の制約に依存します(例: 一意名の衝突や上限により create_before_destroy が成立しない場合がある)。試験でもこの前提(プロバイダ/API 依存の制約)を前提知識として問われがちです。

  • create_before_destroy: 置換が必要な場合、先に新規を作ってから旧リソースを削除。
  • prevent_destroy: 破壊が発生するプランをエラーにする安全装置。
  • ignore_changes: 指定属性の差分を無視(外部システムが上書きするタグなど)。
  • replace_triggered_by: 他リソース(や属性)の変更をトリガーに、対象リソースを置換。

最小例: 代表的な lifecycle の指定

resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = "t3.micro"

  lifecycle {
    create_before_destroy = true
    prevent_destroy       = false
    ignore_changes        = [
      # 例: 外部で上書きされやすいタグ
      tags["owner"],
    ]
    # replace_triggered_by は必要時のみ使う
  }
}

create_before_destroy を安全に使う

create_before_destroy は、リソースが「置換(new resource required)」になる変更で効果を発揮します。Plan 上は -/+ と表示され、旧 → 新の順で切り替えたいときに有効です。可用性確保(無停止切替)や一時的な二重稼働を許容できるケースで活用します。

注意点は、重複作成が許される前提があることです。名前が一意で衝突する、同一 IP/EIP を同時にアタッチできない、クォータ上限に達する、などの制約があると先行作成が失敗します。こうした場合はユニークな名前付け(ランダムサフィックス)、アタッチの切替順序の工夫、あるいは Blue/Green 構成で衝突リソースを分離するのが定石です。

  • 有効な場面: インスタンス置換(AMI 更新)、Launch Template/Config のロールアウト、ロール・ポリシー名にサフィックスを持たせる設計。
  • 失敗しがちな場面: 一意名のバケット/ユーザー、固定 IP を同時に持てない NIC、容量クォータ逼迫。
  • Plan 読解: 置換要因の行に (new resource required) と注記、対象に -/+ の記号。

create_before_destroy の切替イメージ

Old State                     New State (plan)
-----------                   -----------------
[instance v1]  --create-->    [instance v2]
      |                            |
      |  traffic cutover           |  <-- attach / register
      v                            v
  --destroy-------------------->  [instance v1 deleted]

時間軸:  作成 -> 接続/紐付け変更 -> 旧破棄

例: AMI 更新時の無停止置換(AWS EC2 の一例)

resource "aws_instance" "app" {
  ami           = var.ami_id        # AMI を更新すると置換が必要
  instance_type = "t3.micro"
  subnet_id     = var.subnet_id

  lifecycle {
    create_before_destroy = true
  }

  # 固定名/固定 IP が衝突する場合は、切替を段階的に行う
  # 例: EIP は新インスタンスへ付け替えてから旧を破棄
}

# 名前衝突が発生しうるリソースではサフィックスで緩和
resource "random_id" "name" { byte_length = 2 }
resource "aws_iam_role" "app" {
  name = "app-role-${random_id.name.hex}"
  assume_role_policy = data.aws_iam_policy_document.app.json
  lifecycle { create_before_destroy = true }
}

prevent_destroy と ignore_changes の注意点

prevent_destroy は、Destroy を含むプランをエラーにして適用を止めます。誤削除防止に有効ですが、置換(-/+)も Destroy を伴うためブロックされます。どうしても削除・置換が必要な場合は、一時的に prevent_destroy を外してから適用する運用が基本です。

ignore_changes は、指定属性の差分を無視します。外部システムがタグや特定設定を上書きする場合のノイズ低減に有効ですが、長期運用では実環境とのドリフトを温存することになります。後から整合を取りたい場合は ignore_changes を外して計画的に適用し直します。

  • prevent_destroy は Plan/Apply をエラーにする。CLI オプションで強行突破はできないため、設定を外すのが唯一の正攻法。
  • ignore_changes は「差分を見なかったことにする」だけで、実体は変えない。監査要件が厳しい環境では使い所を絞る。
  • for_each/Count の各要素に対して lifecycle は個別に作用する(要素単位での置換/抑止)。
メタ引数主目的Plan/Apply 上の挙動失敗・注意ポイント
create_before_destroy置換時に先に作成してから削除リソースは -/+(new resource required)。順序は作成→切替→削除一意名や固定資源の衝突、クォータ上限で先行作成が失敗
prevent_destroy意図しない削除の防止Destroy を含むプランはエラー。-/+ もブロック削除・置換が必要なら一時的に解除してから適用
ignore_changes特定属性の差分無視(ドリフトを許容)該当属性の差分が Plan に現れず更新もしない長期ドリフトの温存。将来の収束時は一時的に解除して整合
replace_triggered_by外部変更をトリガーに強制置換参照先の更新で対象を -/+ にする過剰置換のリスク。依存と置換の粒度を絞る

例: タグは無視、DB は誤削除防止

resource "aws_db_instance" "main" {
  identifier = "app-db"
  engine     = "postgres"
  # ... 省略 ...
  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = "t3.micro"
  tags = {
    owner = "platform-tooling"  # 外部タグ付与と衝突しやすい例
  }
  lifecycle {
    ignore_changes = [
      tags["owner"],
    ]
  }
}

replace_triggered_by と depends_on の違い

depends_on はリソースの作成順序(依存グラフのエッジ)を追加するだけで、置換を強制しません。一方、replace_triggered_by は参照先リソース(またはその属性)が変化した場合に、対象リソースを置換(-/+)します。すなわち、前者は順序制御、後者は置換トリガの付与という役割の違いがあります。

実務では、暗号鍵・証明書・KMS キーなどセキュリティ重要度が高い素材が更新された際に、依存する機密ストアや設定を「必ず新品にする」ために replace_triggered_by を用います。create_before_destroy と併用すると、置換が発生した際の順序も安全側に寄せられます。

  • depends_on は「順序のみ」。Plan の変化は依存先の変化がある場合でも対象に波及しない。
  • replace_triggered_by は「置換の伝搬」。参照先に変更があれば対象を -/+ にする。
  • 試験では depends_on と replace_triggered_by の混同が頻出。用語と目的を短く言い切れるように。

例: KMS キー更新で Secret を強制置換

resource "aws_kms_key" "root" {
  description = "root key for app secret"
}

resource "aws_secretsmanager_secret" "app" {
  name       = "app/secret"
  kms_key_id = aws_kms_key.root.id

  lifecycle {
    # KMS キーが更新されたら Secret を新品にする
    replace_triggered_by = [
      aws_kms_key.root
    ]
    create_before_destroy = true
  }
}

# これに対し depends_on は順序を保証するだけで置換は起きない
# resource "..." "..." { depends_on = [aws_kms_key.root] }

実務パターン集:Blue/Green・Immutable・衝突回避

Blue/Green: 実体を色分けして併存させ、トラフィックだけを切り替える。create_before_destroy は色ごとのコンポーネント内部(例: VM/ASG/TG アタッチ)で二重稼働を許し、色同士の切替は DNS/ALB 重みでノーダウンに近づける。

Immutable: AMI/イメージ生成を前提に常に置換で更新する。create_before_destroy を既定にし、固定資源(EIP/一意名)は最後に切り替える段取りにする。ユニーク名はランダムサフィックスで衝突を避ける。

衝突回避: 一意名や上限が厳しいリソースは、別リソースに状態を委譲してから(例: EIP のアタッチ変更や Route53 の切替)旧実体を削除する。Plan が -/+ になる箇所を読み、名前・紐付け・容量のいずれで衝突するかを事前に洗い出す。

  • ユニーク名: random_id/random_pet でサフィックスを付けて先行作成を可能にする。
  • 固定 IP/接続: 新実体へ付け替えてから旧を削除。切替を別リソースの更新として分割。
  • 計画外置換の抑止: prevent_destroy をピンポイントで付ける(DB、本番キューなど)。

実装ヒント(擬似コード): Blue/Green の切替分割

# 1) 実体は色付きで併存 (blue/green)。VM/ASG 側は create_before_destroy で安全に置換
resource "aws_autoscaling_group" "svc" {
  # for_each = toset([var.active_color]) などで色を制御する設計も可
  lifecycle { create_before_destroy = true }
}

# 2) トラフィックは後段で切替 (DNS/ALB target weight)
resource "aws_route53_record" "svc" {
  # blue -> green に重みを寄せる。完了後に不要な色を縮退
}

# 3) 衝突資源(EIP/固定名)は最後に再アタッチ or rename 用の属性を用意
#    ランダムサフィックスで同名衝突を避ける
resource "random_id" "suffix" { byte_length = 2 }
# name = "app-${random_id.suffix.hex}"

試験対策チェックリストと落とし穴

Plan の記号と意味を正確に。-/+ は置換(new resource required)。~ はインプレース変更。+ は新規、- は削除。置換の順序は lifecycle とプロバイダ制約で最終決定される点を説明できるようにする。

prevent_destroy は CLI で無効化できない。設定を外してから Apply。replace_triggered_by は depends_on と役割が異なる(置換 vs. 順序)。ignore_changes はドリフト温存の代償がある。

  • create_before_destroy は「置換時のみ」有効。インプレース更新には影響しない。
  • 一意名衝突・クォータ超過時は先行作成に失敗。ユニーク名や分割適用で回避。
  • replace_triggered_by で過剰置換を起こさない。粒度を最小に。
  • ignore_changes は監査・ドリフト戦略とセットで検討。

コマンド例: 置換/差分確認の基本

# 置換を明示して適用(taint の代替)
terraform apply -replace=aws_instance.app

# Plan だけで挙動確認
terraform plan

# 注意: prevent_destroy は CLI で無視できない。設定を外してから apply する

問題で確認

Associate / Pro

問題 1

本番稼働中の EC2 インスタンスを新しい AMI に置き換えたい。無停止に近い切替を目指し、名前の衝突も避ける必要がある。Terraform 側の適切な対応はどれか?

  1. create_before_destroy を有効化し、名前にランダムサフィックスを付けて一意性を確保する
  2. prevent_destroy を有効化してから AMI を変更し、強制的に置換させる
  3. ignore_changes に ami を追加して差分を無視し、後で手動で入れ替える
  4. depends_on に新 AMI のデータソースを追加して順序を保証する

正解: A

無停止に近づけるには create_before_destroy により新規作成→切替→旧削除の順を狙う。名前の衝突を避けるためランダムサフィックス等で一意名にする。prevent_destroy は削除をブロックして置換自体を妨げる。ignore_changes は差分を無視してしまい更新されない。depends_on は順序だけで置換は強制しない。

よくある質問

create_before_destroy が効かないのはどんなとき?

置換が不要な変更(インプレース更新)の場合や、プロバイダ/API の制約で重複作成できない場合(グローバルに一意な名前、同時アタッチ不可、クォータ超過など)は先行作成が失敗します。解決策はユニーク名の採用、切替操作の分割(先にアタッチ変更→旧破棄)、Blue/Green での分離です。

ignore_changes で無視した属性のドリフトを後で解消したいときは?

一時的に ignore_changes の対象から外して plan/apply し、望む値に収束させます。強制置換が必要な場合は terraform apply -replace=... を併用します。

prevent_destroy を付けたリソースを削除したい場合は?

prevent_destroy を削除(または false に変更)してから再度 plan/apply します。CLI オプションでバイパスする方法はありません。誤削除防止が目的のため、設定変更という明示的な手順が求められます。

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

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.