Terraformの「依存地獄」を解剖する:暗黙的依存の掌握と`depends_on`の禁忌的設計
Terraformを扱う際、多くのエンジニアが陥る罠がある。それは「依存関係の制御を`depends_on`という魔法の杖だけで解決しようとする」という安易な設計思想だ。
大規模なインフラをコード化する際、リソース間の依存関係を正しく記述できないことは、単なるデプロイ失敗に留まらない。破壊的な再作成(Recreation)の連鎖や、Terraformのグラフ構築におけるメモリ消費の爆発、そして修正不可能な循環依存(Circular Dependency)という名の「終わらない悪夢」を招く。
本稿では、Terraformの内部構造を理解し、真に堅牢かつ冪等性の高いインフラを構築するための「依存関係の哲学」を伝授する。
—
1. 暗黙的依存(Implicit Dependency)こそがTerraformの血流である
Terraformにおける依存関係は、原則として「参照(Reference)」によって自動的に構築される。これが暗黙的依存だ。
resource “aws_vpc” “main” {
cidr_block = “10.0.0.0/16”
}
resource “aws_subnet” “public” {
vpc_id = aws_vpc.main.id # ここで暗黙的な依存が発生している
cidr_block = “10.0.1.0/24”
}
`aws_subnet`は`aws_vpc.main.id`を必要とするため、Terraformは自動的に「VPC作成 → サブネット作成」の順序をグラフに書き込む。これを手動で`depends_on`に書き足すのは、コードのノイズを増やすだけでなく、グラフの最適化を阻害する「アンチパターン」だ。
エキスパートの知見:
TerraformはDAG(有向非巡回グラフ)を用いて構築順序を決定する。暗黙的な依存関係を優先させることで、Terraformは並列処理(`parallelism`)を最大化できる。`depends_on`を乱用することは、Terraformの並列実行能力を自ら殺し、デプロイ速度を低下させる行為に他ならない。
—
2. `depends_on`は「最終手段」である
`depends_on`を使用すべきシーンは極めて限定的だ。それは、「リソース間の属性参照が物理的に不可能だが、論理的に実行順序を強制しなければならない場合」のみである。
陥りやすい罠:不要な再作成
特に厄介なのは、モジュール全体に`depends_on`を付与する場合だ。
悪例:不要なdepends_onが招く破滅
module “application” {
source = “./modules/app”
depends_on = [aws_db_instance.db]
}
この記述は、`aws_db_instance`のリソースが少しでも変更される(例えばタグの変更など)と、その下流にある`module.application`全体が「変更の連鎖」に巻き込まれ、再作成が走るリスクがある。Terraformの差分計算において、`depends_on`は依存先リソースの「すべての属性変更」をトリガーにしてしまうからだ。
—
3. 実践:循環依存を回避する設計パターン
循環依存(AがBに依存し、BがAに依存する)は、多くの場合、設計の分離不足が原因だ。これを回避するためのエキスパート・テクニックを2つ紹介する。
A. データソースとリソースの分離(分割統治)
IAMポリシーとロールのように、相互に参照し合うリソースがある場合、`aws_iam_policy`と`aws_iam_role_policy_attachment`に分離し、依存の方向を一方通行に統一せよ。
B. `null_resource` や `terraform_data` の活用
どうしても順序制御が必要だが、リソースの属性参照ができない場合、トリガー(`triggers_replace`)を細かく制御することで、不必要な再作成を回避できる。
resource “terraform_data” “dependency_bridge” {
# 変更時にのみ再構築されるように制御
triggers_replace = {
db_id = aws_db_instance.db.id
}
}
resource “aws_instance” “app” {
depends_on = [terraform_data.dependency_bridge]
# …
}
—
4. パフォーマンスと内部アーキテクチャの最適化
大規模なStateファイルを運用していると、`terraform plan`の速度が劇的に低下する。これはTerraformがグラフ全体をメモリ上に展開し、全リソースの依存関係を評価するためだ。
- State分割の極意: 依存関係が複雑すぎる場合、それは「モノリスなState」の弊害だ。`terragrunt`やTerraformワークスペースを活用し、Stateを適切な粒度で分割せよ。
- APIコールの最適化: `depends_on`を減らし、暗黙的依存を活用することで、Terraformは「作成可能なリソース」を即座に特定し、APIリクエストを並列化する。これにより、デプロイ時間の短縮だけでなく、AWS APIのレート制限(Throttling)への接触確率も下げられる。
—
最後に:伝説的エンジニアからの提言
Terraformの真髄は、「ツールを使うこと」ではなく「宣言的コードによる抽象化の極致を目指すこと」にある。
`depends_on`を書く前に一度立ち止まって考えてほしい。「これは本当に物理的な依存なのか? それとも自分の設計が密結合しすぎているだけではないか?」と。
優れたIaCコードは、まるで川の流れのように、最小の抵抗で構築が完了する。依存関係を整理し、暗黙のルールを掌握し、インフラを「自動化された芸術」へと昇華させてほしい。
君が書くそのコードが、何千ものリソースを安全に、そして静かに管理する礎となることを期待している。