1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Terraform初心者向け】`[0]`と`[*]`の違いとは?countとfor_eachのリソースアクセスを理解する

1
Posted at

はじめに

Terraformのコードを読んでいると、リソースの参照で[0][*]といった[](ブラケット)が登場します。

# パターン1
aws_nat_gateway.main[0].id

# パターン2
values(aws_subnet.private)[*].id

この2つは見た目が似ていますが、意味がまったく異なります。この記事では、countfor_eachというリソースの作成方法の違いから、それぞれの[]の意味を初心者向けに解説します。

対象読者

  • Terraformを学び始めたばかりの方
  • [0][*]の意味がよくわからない方
  • countfor_eachの違いを整理したい方

前提知識:countとfor_each

Terraformでは、リソースを条件付きで作成したり、複数作成したりするためにcountfor_eachという2つの仕組みがあります。この作成方法の違いが、[]の使い方の違いに直結します。

パターン1:[0] — countで作ったリソースへのアクセス

countとは

countを使うと、リソースを指定した数だけ作成できます。

resource "aws_nat_gateway" "main" {
  count = var.enable_nat_gateway ? 1 : 0  # trueなら1つ作成、falseなら作成しない
  # ...
}

countを使うとリソースは「配列(リスト)」になる

countを使ったリソースは、配列(リスト) として管理されます。配列の要素には インデックス番号(0から始まる) でアクセスします。

aws_nat_gateway.main
  ├── [0]  ← 最初の要素
  ├── [1]  ← 2番目の要素(count=2以上の場合)
  └── ...

[0]の意味

[0]は「配列の最初の要素」を指します。

# count = 1 の場合(リソースが1つ作成される)
aws_nat_gateway.main[0].id  # → 最初(唯一)のNAT GatewayのID ✅
aws_nat_gateway.main[1].id  # → エラー(2番目は存在しない)❌

# count = 0 の場合(リソースが作成されない)
aws_nat_gateway.main[0].id  # → エラー(リソース自体が存在しない)❌

よくある使い方

countは「作るか作らないか(0 or 1)」の条件分岐でよく使われます。

resource "aws_nat_gateway" "main" {
  count = var.enable_nat_gateway ? 1 : 0
  # ...
}

# 参照するときは [0] で最初の要素にアクセス
resource "aws_route" "private" {
  nat_gateway_id = aws_nat_gateway.main[0].id
}

パターン2:[*] — for_eachで作ったリソースへのアクセス

for_eachとは

for_eachを使うと、mapやsetの各要素に対してリソースを作成できます。

variable "private_subnet_cidrs" {
  default = {
    "a" = "10.0.1.0/24"
    "c" = "10.0.2.0/24"
    "d" = "10.0.3.0/24"
  }
}

resource "aws_subnet" "private" {
  for_each   = var.private_subnet_cidrs  # mapの各要素に対してリソースを作成
  cidr_block = each.value
  # ...
}

for_eachを使うとリソースは「map」になる

for_eachを使ったリソースは、map(キーと値のペア) として管理されます。要素にはキー(文字列) でアクセスします。

aws_subnet.private
  ├── ["a"]  ← キー "a" の要素
  ├── ["c"]  ← キー "c" の要素
  └── ["d"]  ← キー "d" の要素

個別にアクセスする場合

aws_subnet.private["a"].id  # → AZ aのサブネットID ✅
aws_subnet.private["c"].id  # → AZ cのサブネットID ✅
aws_subnet.private[0].id    # → エラー(mapなのでインデックスは使えない)❌

全要素のIDをまとめて取得したい場合

ここで登場するのがvalues()[*](splat演算子)です。

ステップ1:values()でmapからリストに変換

values()は、mapの値だけを取り出してリストにする関数です。

values(aws_subnet.private)
# → [
#     aws_subnet.private["a"],   ← リソースオブジェクト
#     aws_subnet.private["c"],
#     aws_subnet.private["d"]
#   ]

ステップ2:[*](splat演算子)で全要素の属性を取得

[*]はsplat演算子と呼ばれ、リスト内のすべての要素に対して指定した属性を取得します。

values(aws_subnet.private)[*].id
# → [
#     "subnet-aaaaa",   ← aws_subnet.private["a"].id
#     "subnet-ccccc",   ← aws_subnet.private["c"].id
#     "subnet-ddddd"    ← aws_subnet.private["d"].id
#   ]

処理の流れを整理

aws_subnet.private                      ← map(キーと値のペア)
  ↓ values() で値だけ取り出す
[リソースA, リソースC, リソースD]        ← リスト(リソースオブジェクト)
  ↓ [*].id で全要素の.idを取得
["subnet-aaaaa", "subnet-ccccc", ...]   ← リスト(IDの文字列)

比較まとめ

項目 aws_nat_gateway.main[0] values(aws_subnet.private)[*]
作成方法 count for_each
データ構造 配列(リスト) map
アクセス方法 インデックス番号([0], [1]...) キー(["a"], ["c"]...)
[0]の意味 配列の最初の要素 ー(使わない)
[*]の意味 ー(使わない) リスト内のすべての要素に適用
主な用途 単一リソースへのアクセス 複数リソースの属性をまとめて取得

実際のコードでの使用例

# ─── count を使った場合(単一リソース)───
resource "aws_nat_gateway" "main" {
  count = var.enable_nat_gateway ? 1 : 0
  # ...
}

# [0] で1つのNAT GatewayのIDを取得
nat_gateway_id = aws_nat_gateway.main[0].id


# ─── for_each を使った場合(複数リソース)───
resource "aws_subnet" "private" {
  for_each = var.private_subnet_cidrs
  # ...
}

# values() + [*] ですべてのサブネットIDをリストで取得
subnet_ids = values(aws_subnet.private)[*].id
# → ["subnet-aaaaa", "subnet-ccccc", "subnet-ddddd"]

countとfor_eachの使い分け

ケース 使うべきもの 理由
リソースを作るか作らないか(0 or 1) count 単純なON/OFFに最適
同じ種類のリソースを複数作る for_each キーで個別管理でき、追加・削除が安全

countで複数リソースを作ることも可能ですが、途中の要素を削除するとインデックスがずれて意図しない再作成が発生するため、複数リソースにはfor_eachが推奨されます。

まとめ

  • [0]countで作ったリソース(配列)の最初の要素にアクセスするインデックス
  • [*]:リスト内のすべての要素に対して属性を取得するsplat演算子
  • countで作ったリソースは配列for_eachで作ったリソースはmapとして扱われる
  • for_eachのリソースからIDのリストを取得するには、values()でリストに変換してから[*]を使う

[]の中身が数字なのか*なのかで、背景にある仕組みがまったく異なることを覚えておくと、Terraformのコードがぐっと読みやすくなります。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?