Terraformで複数のリソースを作成する場合ありますよね。インスタンスとかサブネットとかよくあります。昔、作ったのですが、時間が経ってうろ覚えになってどうすればいいか分からなくなったので再学習しました。備忘録です。
今回はEC2インスタンスを例にします。
初めてEC2インスタンスをTerraformで作る場合以下のようにしか作れないと思ってしまうはずで。無理に変数とか付けて表現しようとするエラーになります。
resource "aws_instance" "web1" {
# インスタンス1の設定
}
resource "aws_instance" "web2" {
# インスタンス2の設定
}
2個ぐらいならこれでいいでしょう。でもたくさん作る場合は?
for_eachを使います。
resource "aws_instance" "web" {
for_each = {
web1 = "Web Server 1"
web2 = "Web Server 2"
}
ami = "ami-0e60b6d05dc38ff11"
instance_type = "t2.micro"
tags = {
Name = each.value
}
}
こんな感じにします。これをどうやって呼び出すのか?
resource "aws_security_group" "example" {
# セキュリティグループの設定
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [aws_instance.web["web1"].public_ip]
}
}
という風に、aws_instance.web[“web1”]と[]で囲んで呼び出します。たぶん、これで用が足りると思いますし、これ以上すると可読性に問題がでると私は思いました。
でも、web1とかを変数で置き換えたいというのがエンジニアの性ですよね。
やり方を調べてみました。
ローカル変数の定義:
まず、作成したいインスタンスの情報をローカル変数として定義します。この際、各インスタンスを一意に識別するためのキー(例:"web1"
、"web2"
)を設定します。
locals {
instances = {
web1 = {
ami = "ami-0e60b6d05dc38ff11"
instance_type = "t2.micro"
}
web2 = {
ami = "ami-0e60b6d05dc38ff12"
instance_type = "t2.small"
}
}
}
for_each
を使用したリソースの定義:
次に、for_each
を使用して、上記で定義したローカル変数を基に複数のインスタンスを作成します。
resource "aws_instance" "web" {
for_each = local.instances
ami = each.value.ami
instance_type = each.value.instance_type
}
この設定により、local.instances
で定義した各キー(web1
、web2
)に対応するインスタンスが作成されます。
リソースの参照:
他のリソースや出力変数から、これらのインスタンスを参照する際には、キーを使用して特定のインスタンスを指定できます。
output "web_instance_ids" {
value = { for k, v in aws_instance.web : k => v.id }
}
この出力では、各インスタンスのキー(web1
、web2
)と対応するインスタンスIDをマップとして出力します。
こんな感じになりました。わかりやすいですか? 僕はわかりにくくなったと思いました。お客様へ納品するのに、こんなコードを読解しろというのはマズくないですか? HashiCorpはfor文やfor_each文を無闇に使うのは可読性が悪くなるので推奨してません。まあ、参考例です。
コメント