Terraform の lifecycle メタ引数は、変更の順序や破壊的変更の抑制、意図的な置換トリガーなど、デプロイの安全性と可観測性に直結します。
この記事では公式ドキュメントの挙動に沿って、よく問われる create_before_destroy を軸に注意点をまとめ、試験(Associate/Pro)での出題パターンと実務パターンを短時間で復習できるように構成しました。
lifecycle は各リソース(および一部の最近の Terraform ではモジュール)に指定できるメタ引数で、Plan/Apply における更新戦略を制御します。代表的なものは create_before_destroy(置換時の順序制御)、prevent_destroy(意図しない削除の防止)、ignore_changes(特定属性の差分無視)、replace_triggered_by(外部の変更で置換を強制)です。
重要な前提として、Terraform は宣言的な依存グラフに基づきプランを構築します。lifecycle はそのグラフ上の順序や置換判定にヒントを与えますが、最終的な挙動は各プロバイダとリモート API の制約に依存します(例: 一意名の衝突や上限により create_before_destroy が成立しない場合がある)。試験でもこの前提(プロバイダ/API 依存の制約)を前提知識として問われがちです。
最小例: 代表的な 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 は、リソースが「置換(new resource required)」になる変更で効果を発揮します。Plan 上は -/+ と表示され、旧 → 新の順で切り替えたいときに有効です。可用性確保(無停止切替)や一時的な二重稼働を許容できるケースで活用します。
注意点は、重複作成が許される前提があることです。名前が一意で衝突する、同一 IP/EIP を同時にアタッチできない、クォータ上限に達する、などの制約があると先行作成が失敗します。こうした場合はユニークな名前付け(ランダムサフィックス)、アタッチの切替順序の工夫、あるいは Blue/Green 構成で衝突リソースを分離するのが定石です。
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 は、Destroy を含むプランをエラーにして適用を止めます。誤削除防止に有効ですが、置換(-/+)も Destroy を伴うためブロックされます。どうしても削除・置換が必要な場合は、一時的に prevent_destroy を外してから適用する運用が基本です。
ignore_changes は、指定属性の差分を無視します。外部システムがタグや特定設定を上書きする場合のノイズ低減に有効ですが、長期運用では実環境とのドリフトを温存することになります。後から整合を取りたい場合は ignore_changes を外して計画的に適用し直します。
| メタ引数 | 主目的 | 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"],
]
}
}depends_on はリソースの作成順序(依存グラフのエッジ)を追加するだけで、置換を強制しません。一方、replace_triggered_by は参照先リソース(またはその属性)が変化した場合に、対象リソースを置換(-/+)します。すなわち、前者は順序制御、後者は置換トリガの付与という役割の違いがあります。
実務では、暗号鍵・証明書・KMS キーなどセキュリティ重要度が高い素材が更新された際に、依存する機密ストアや設定を「必ず新品にする」ために replace_triggered_by を用います。create_before_destroy と併用すると、置換が発生した際の順序も安全側に寄せられます。
例: 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: 実体を色分けして併存させ、トラフィックだけを切り替える。create_before_destroy は色ごとのコンポーネント内部(例: VM/ASG/TG アタッチ)で二重稼働を許し、色同士の切替は DNS/ALB 重みでノーダウンに近づける。
Immutable: AMI/イメージ生成を前提に常に置換で更新する。create_before_destroy を既定にし、固定資源(EIP/一意名)は最後に切り替える段取りにする。ユニーク名はランダムサフィックスで衝突を避ける。
衝突回避: 一意名や上限が厳しいリソースは、別リソースに状態を委譲してから(例: EIP のアタッチ変更や Route53 の切替)旧実体を削除する。Plan が -/+ になる箇所を読み、名前・紐付け・容量のいずれで衝突するかを事前に洗い出す。
実装ヒント(擬似コード): 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 はドリフト温存の代償がある。
コマンド例: 置換/差分確認の基本
# 置換を明示して適用(taint の代替)
terraform apply -replace=aws_instance.app
# Plan だけで挙動確認
terraform plan
# 注意: prevent_destroy は CLI で無視できない。設定を外してから apply するAssociate / Pro
問題 1
本番稼働中の EC2 インスタンスを新しい AMI に置き換えたい。無停止に近い切替を目指し、名前の衝突も避ける必要がある。Terraform 側の適切な対応はどれか?
正解: 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 オプションでバイパスする方法はありません。誤削除防止が目的のため、設定変更という明示的な手順が求められます。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...