【実務・中級編】Terraformのfor_eachとdynamicブロック完全攻略!複雑なJSONや複数リソースを自在に生成する裏技 – インフラ構成管理(IaC)活用バイブル

Terraformの真髄:`for_each`と`dynamic`ブロックでコードの「濁流」を止める極意

Terraformを書いていると、いつの間にか「コピペ地獄」に陥っていないか?
「似たようなセキュリティグループルールを10個書く」「サブネットごとに微妙に異なる設定を追記する」。そんなDRY原則を無視したコードは、いずれ負債となり、君の夜を奪うことになる。

今日は、中級者から「真のプロ」へ脱皮するための、Terraformにおける動的生成の極致を伝授する。

—

1. なぜ`count`ではなく`for_each`なのか?

まず大前提だ。`count`は、配列のインデックスに依存する。もし途中の要素を削除したらどうなる?後ろのインデックスがすべてズレて、既存のリソースが破壊・再作成される。これがインフラエンジニアの悪夢だ。

`for_each`は、MapやSetをキーとしてリソースを管理する。キーさえ一意なら、順序は関係ない。「破壊しないIaC」の鉄則は、`count`を捨て、`for_each`を愛することから始まる。

—

2. 実務で直面する「複雑なネスト」を攻略する

複雑なJSONやYAMLからリソースを生成する場合、ただ`for_each`を使うだけでは足りない。`flatten`関数を組み合わせ、多次元配列をフラット化するのがプロの定石だ。

実践:複雑なルール設定をDRYに管理する

例えば、環境ごとに異なる複数のポートを開放するセキュリティグループを定義する場合、以下のように記述する。

localsで複雑なネストを「フラット」に定義する
locals {
# 複雑なJSON構造を想定
raw_config = {
web = { ports = [80, 443], cidrs = [“0.0.0.0/0”] }
api = { ports = [8080], cidrs = [“10.0.0.0/16”] }
}

# リソース生成用にフラット化する魔法のコード
rules = flatten([
for service, config in local.raw_config : [
for port in config.ports : {
key = “${service}-${port}”
port = port
cidr = config.cidrs
}
]
])
}

resource “aws_security_group_rule” “ingress” {
for_each = { for rule in local.rules : rule.key => rule }

type = “ingress”
from_port = each.value.port
to_port = each.value.port
protocol = “tcp”
cidr_blocks = each.value.cidr
security_group_id = aws_security_group.main.id
}

この「`flatten` + `for`式」の組み合わせさえあれば、どんな複雑なJSON構造でも恐怖する必要はない。

—

3. `dynamic`ブロックのネスト:可読性の死守

リソースブロックの中にさらにネストされたブロックがある場合、`dynamic`ブロックが必須だが、使いすぎるとコードが読みづらくなる。

コツは、「`dynamic`ブロック内でさらに`dynamic`を使わない」ことだ。 構造が深すぎる場合は、別途リソースとして切り出すのが「疎結合」の原則だ。

許容されるネストの限界例
dynamic “ingress” {
for_each = var.ingress_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = “tcp”
}
}

—

4. 生産性を極限まで高める「テックリードの道具箱」

ここからは、コードの書き方以上に重要な「環境」の話だ。

推奨プラグイン

  • HashiCorp Terraform (VS Code): これがないと始まらない。`terraform validate`を裏で走らせてくれる。
  • TFLint: これを入れずにコードをマージするな。クラウドプロバイダー固有の「非推奨設定」や「型エラー」をCIを回す前に教えてくれる。
  • Indent-rainbow: 複雑なHCLのインデントを視覚的にサポートする。

設定の共有化ルール(ベストプラクティス)

  • `tfvars`の分離: 環境ごとのパラメータは`environments/prod.tfvars`のように必ず分離せよ。
  • YAML活用: 複雑な設定はTerraformコードに直書きせず、`config.yaml`を`yamldecode()`で読み込むのが、非エンジニア(PMやセキュリティ担当)との共同編集をスムーズにする唯一の道だ。

開発スピードを加速させるキーボードショートカット (VS Code)

  • `Alt + Shift + F`: Terraformコードのフォーマットを強制実行(保存時自動実行設定が必須)。
  • `Ctrl + Shift + P` -> `Terraform: Init` / `Plan`: コマンドを打つ時間を節約する。

—

5. 最後に:コードは「読み手」のために書く

どんなに洗練された`for_each`も、他のメンバーが理解できなければ「技術的負債」だ。
複雑なループを書いたときは、必ず`locals`ブロックで意味のある名前を付け、意図をコメントに残すこと。

「動くコード」を作るのは新米でもできる。
「壊れにくく、かつ誰が読んでも意図がわかるコード」を作るのが、我々SREの仕事だ。

明日の朝、君のプロジェクトの`main.tf`が、この知見で少しでもクリーンになっていることを願っている。健闘を祈る。

タイトルとURLをコピーしました