「世の中には難しいことが多い!」と感じることが多い私が、様々な用語を、初学者向けにわかりやすく全力で解説します。
解説する内容
Terraformのfor_eachについて解説をします。Terraformを使用するうえで、ソースコードの可読性を上げるためにも必須の知識となっています。本記事では具体的なソースコードをもとに解説をしていきますので、ぜひ最後まで読んでみてください。
Terraformのfor_eachとは
Terraformのfor_eachを使うことで繰り返し処理をすることが出来ます。同じテンプレートを使用することが出来るため、少ないソースコードの量で複数のリソースを作成することができる便利な機能です。
for_eachはmap型とset型でのみ使用することが出来ます。map型とset型で定義した値の数だけ繰り返し処理が行われます。
map型とは、以下のようにキーと値のペアでデータを格納するデータ構造のことです。
ages = {
"Alice": 25,
"Bob": 30,
"Charlie": 28
}
set型とは、以下のように重複することのないユニークな値を保持する配列のデータ型です。list型とは異なり、同じ値を複数含むことは出来ません。
fruit_list = ["apple", "banana", "orange"]
set型について詳しく知りたい方は以下の記事を読んでみてください。
例を用いて詳細に説明するよ
for_eachの使い方について、ソースコードをもとに具体的に説明をしていきます。今回はmap型で使用する方法を説明します。
本記事の例としてterraformで作成するリソース
Google Cloudでサブネットを2つ作成します。「subnet-1」と「subnet-2」という名前の2つのサブネットを作成します。
前提条件として、プロジェクトやVPCネットワークが作成されている必要がありますが、今回はfor_eachの使い方の説明のため、その部分は省略します。
サブネットが何かわからない方は以下の記事を読んでみてください。
今回はfor_eachの使い方の説明のため、Google Cloudが分からない方も「サブネットを2つ作成するんだな~」と理解して読み進めていただければOKです。
for_eachを使用した例
variable.tf
variable.tfでは、作成するサブネットの変数と値を定義します。for_eachを使うため、今回は以下のようにmap型で定義します。
# variable.tf
variable "subnets" {
description = "作成するサブネットのリスト"
# 値を格納するための変数を定義する
type = map(object({
region = string
cidr = string
}))
# サブネットに指定する値を定義していく
default = {
# 1つ目に作成するサブネットの値
subnet-1 = {
region = "us-central1"
cidr = "10.0.1.0/24"
},
# 2つ目に作成するサブネットの値
subnet-2 = {
region = "us-central1"
cidr = "10.0.2.0/24"
}
}
}
13行目からは、作成するサブネットの値を定義しています。今回はkeyの値で定義しているように、「subnet-1」と「subnet-2」という名称の2つのサブネットを作成していきます。
main.tf
main.tfでは、リソースを作成する処理を記載します。今回はサブネットを作成するような処理を記載していきます。
# main.tf
resource "google_compute_subnetwork" "subnet" {
# variableで定義した変数を参照し、keyごとに値を取得していくことができる
for_each = var.subnets
name = each.key # subnetsのkeyの値を参照する
region = each.value.region # subnetsのregionで定義した値を参照する
ip_cidr_range = each.value.cidr # subnetsのcidrで定義した値を参照する
network = google_compute_network.vpc_network.id # VPCを指定します(今回は無視でOK)
}
6行目では、for_eachを使用して繰り返し処理を行うように記載しています。for_each=var.subnetsと記載することで、variableのsubnetsで定義したkeyの数だけ繰り返し処理を行います。今回はkeyで定義した、「subnet-1」と「subnet-2」の2回分の繰り返し処理が行われます。
8行目では、variableのsubnetsで定義したkeyの値を取り出しています。each.keyと記載することで、keyの値を取り出すことが出来ます。
9,10行目では、variableのsubnetsで定義したvalueの値を取り出しています。each.valueと記載することで、valueの値を取り出すことが出来ます。
つまり、1回目の繰り返し処理ではmain.tfは以下のようになります。
# main.tf
resource "google_compute_subnetwork" "subnet" {
name = "subnet-1"
region = "10.0.1.0/24"
ip_cidr_range = "us-central1"
network = "test-vpc-network"
}
2回目の処理ではmain.tfは以下のようになります。
# main.tf
resource "google_compute_subnetwork" "subnet" {
name = "subnet-2"
ip_cidr_range = "us-central2"
region = "10.0.2.0/24"
network = "test-vpc-network"
}
こうして、for_eachを使用して、subnet1とsubnet2という2つのサブネットが作られました。
for_eachを使用しない場合
上記の例で、for_eachを使用しないでサブネットを2つ作成する場合は、main.tfは以下のように書きます。
# main.tf
resource "google_compute_subnetwork" "subnet1" {
name = "subnet-1"
ip_cidr_range = var.subnets["subnet-1"].cidr
region = var.subnets["subnet-1"].region
network = "test-vpc-network"
}
resource "google_compute_subnetwork" "subnet2" {
name = "subnet-2"
ip_cidr_range = var.subnets["subnet-2"].cidr
region = var.subnets["subnet-2"].region
network = "test-vpc-network"
}
作成するサブネットの数だけ、resourceブロックを記載しなければいけません。今回は2つだけですが、多くなってくるとソースコードの行数が増えてしまいます。
for_eachを使用することで、シンプルにコードを記載することが出来ることが分かりますね。
まとめ
- for_eachを使用することで、ループ処理によって複数のリソースを作成することが出来る
- ソースコードの量を減らし、可読性を上げることが出来る
- for_eachはset型とmap型でのみ使用することが出来る
参考
Udemyの以下の講座を参考にさせていただきました。複数の講座を視聴しましたが、個人的にはこちらの講座が一番分かりやすかったです。講座ではTerraformについて、初学者にも分かりやすく説明してくれているので、Terraformを学びたい方は視聴してみてください。
Infrastructure as Code のツールとしてよく使われる Terraform を、基本的な実装方法やコマンドから、モジュール化・複数環境の管理といった実践的な内容まで、AWS でのハンズオンでしっかり学びましょう!