Terraformモジュール設計の深淵:保守性を殺し、インフラを「負債の墓場」に変える5つのアンチパターン
IaCを導入した多くのチームが、数年後に「Terraformのコードベースがスパゲッティ化し、修正するたびに恐怖を感じる」という現実に直面する。再利用性を追い求めるあまり、抽象化という名の「メンテナンスの爆弾」を自ら埋め込んでいるからだ。
真のSREは、モジュールを「便利ツール」ではなく、「状態管理の制約」として捉える。ここでは、プロダクション環境で泣きを見ないための、設計の極限におけるアンチパターンを詳述する。
—
1. 「神モジュール」の生成:過度な抽象化と `count` / `for_each` の乱用
最も多い失敗が、あらゆるリソースを一つのモジュールに詰め込み、大量の `variable` で条件分岐させる設計だ。
アンチパターンの例:条件分岐の地獄
module “network” {
source = “./modules/network”
create_nat_gateway = var.env == “prod” ? true : false
enable_ipv6 = var.enable_ipv6
# 複雑なロジックがモジュール内に隠蔽され、デバッグ不能になる
}
【極限の知見】
モジュールは「設定のカタログ」であって、「実行ロジックの隠蔽場所」ではない。条件分岐が3つ以上必要な場合、それはモジュールを分割すべきサインだ。抽象化は、理解のコストを増大させる。 可能な限りシンプルに、リソースを直列に宣言する方が、`terraform plan` の挙動を脳内でシミュレートしやすく、結果として障害発生率を下げる。
2. 密結合:モジュール間での暗黙の依存関係
モジュールAの出力(`output`)をモジュールBの引数として直接渡すことは、論理的な依存関係を生み出す。これが進むと、グラフ構造が複雑化し、`terraform graph` が読めない迷宮と化す。
【極限の知見】
依存関係は `data` ソースや `terraform_remote_state` を介して、「疎結合」に保て。特定のモジュールがダウンした際に、依存するすべてのモジュールが巻き添えを食う構成は、サーキットブレーカーのないシステムと同じだ。依存関係は可能な限りフラットにし、リソース間の通信はタグや命名規則(Namespacing)という「疎な結合」を介して行うべきだ。
3. 「プロバイダー設定」のモジュール内カプセル化
モジュール内で `provider` ブロックを定義してはいけない。これはTerraformの設計思想に対する重大な背信行為だ。
【極限の知見】
プロバイダーはルートモジュールで一元管理し、モジュールには `configuration_aliases` を用いて明示的に渡せ。これを怠ると、マルチリージョンやマルチアカウント構成で `terraform plan` がメモリを浪費し、APIのレートリミットに直撃する。特に大規模な環境では、リソースの探索範囲を絞り込むための `alias` 管理が、実行速度と安定性を左右する鍵となる。
4. 隠蔽された副作用: `null_resource` と `local-exec` の多用
IaCの範疇を超えた処理を `local-exec` で行うのは、Terraformの「冪等性の保証」を自ら放棄する行為だ。
【極限の知見】
`local-exec` は最終手段だ。APIを叩くような処理が必要なら、Terraformの外に分離し、GoやPythonで書いたCLIツールをCI/CDパイプラインから呼び出せ。
Terraformの実行プロセス内に依存関係のないバイナリ実行を混入させると、予期せぬ状態不整合を引き起こす。「Terraformはリソースの宣言に集中し、プロセスの実行はオーケストレーターに任せる」。 この責務分離こそが、大規模インフラの寿命を延ばす。
5. バージョニングの放棄:インフラを破壊する「最新」の追従
モジュールのソースを `main` ブランチやタグなしで指定するのは、明日の自分に対するテロ行為である。
危険:いつ壊れるかわからない
module “vpc” {
source = “git::github.com/org/terraform-aws-vpc.git”
}
推奨:イミュータブルな設計
module “vpc” {
source = “git::github.com/org/terraform-aws-vpc.git?ref=v2.4.1”
}
【極限の知見】
モジュールはイミュータブル(不変)であるべきだ。タグを固定しないことは、インフラの再現性を捨てることと同義だ。CIパイプラインで `terraform validate` を通したとしても、依存するモジュールが裏で更新されれば、環境は汚染される。常に特定のハッシュ値またはタグを参照し、変更は「段階的なプロモーション」で行う。これが、深夜の障害対応を避けるための唯一のプロトコルだ。
—
結び:コードは「捨てる勇気」が最も重要
モジュール設計で最も陥りやすい罠は、「もっと一般化できるのでは?」という過度なエンジニアリング欲求だ。しかし、現場で求められるのは「誰が見ても何をしているか1秒で分かるコード」である。
もしあなたのモジュールが500行を超えているなら、それは設計の失敗だ。モジュールは小さく、短く、そして無機質であれ。あなたの作るIaCが、将来のエンジニアたちにとって「呪文」ではなく「地図」になることを願っている。