今回はTerraformを用いて、AWS上に3AZ分のサブネットを1つの定義(リソースブロック)で構築しましたので、その方法をご紹介していきます。
AWS構成図
Terraformで構築する構成は以下です。
東京リージョンに、1つのVPC、3つのパブリックサブネット(各AZ)の構成です。
Terraformで定義が必要なAWSリソースは、次の5つとなります。
・VPC
・インターネットゲートウェイ
・サブネット
・ルートテーブル
・サブネットとルートテーブルの紐づけ
tfファイルの内容
構築に使用するtfファイル(main.tf)の内容は以下です。
※terraform apply1回で構築可
############################################################################
# VPC
############################################################################
resource "aws_vpc" "vpc_01" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "vpc-01"
}
}
############################################################################
# インターネットゲートウェイ
############################################################################
resource "aws_internet_gateway" "igw_01" {
vpc_id = aws_vpc.vpc_01.id
tags = {
Name = "igw-01"
}
}
############################################################################
# サブネット
############################################################################
resource "aws_subnet" "public_subnet" {
for_each = {
"a" = "10.0.0.0/24"
"c" = "10.0.1.0/24"
"d" = "10.0.2.0/24"
}
vpc_id = aws_vpc.vpc_01.id
cidr_block = each.value
availability_zone = "ap-northeast-1${each.key}"
tags = {
Name = "public-subnet-${each.key}"
}
}
############################################################################
# ルートテーブル
############################################################################
resource "aws_route_table" "public_route" {
vpc_id = aws_vpc.vpc_01.id
route {
gateway_id = aws_internet_gateway.igw_01.id
cidr_block = "0.0.0.0/0"
}
tags = {
Name = "public-route"
}
}
# サブネットとの紐づけ
resource "aws_route_table_association" "route_public_association" {
for_each = {
"a" = "1"
"c" = "2"
"d" = "3"
}
subnet_id = aws_subnet.public_subnet["${each.key}"].id
route_table_id = aws_route_table.public_route.id
}
「for_each」について
サブネット、サブネットとルートテーブルの紐づけで、ループ処理を行う「for_each」を記述しています。
「for_each」は、1つのリソースブロック内に、任意の数だけ “key” = “value” を定義することができます。
リソースブロック内で定義された “key” = “value” の数だけループ処理が走るため、”key” = “value” の数だけリソースが構築されます。
keyは each.key 、valueは each.value と記述してパラメータに指定することができます。
上記サブネットの場合、key にa,c,dの文字列、value に3AZ分のCIDRを定義しています。
そして、CIDRのパラメータに each.value でvalue(10.0.0.0/24,10.0.1.0/24,10.0.2.0/24)を指定しています。
AZ・Nameタグのパラメータに each.key でkey(a,c,d)を指定しています。
※Nameタグのように、文字列中に key か value を埋め込みたい場合は ${} で囲います。
サブネットとルートテーブルの紐づけでは、key にa,c,dの文字列、value に1,2,3(valueは使わないので何でもよい)を定義しています。
そして、紐づけ先のサブネットIDに each.key (a,c,d)を指定しています。
※構築時・後はTerraformリソース名の行末に、 [“<for_eachで定義したkey>”] の文字列が付与されて別々のリソースとしてTerraformに認識されます。
例えば、構築したAZ-AのサブネットIDだけをパラメータとして設定したい場合は、 aws_subnet.public_subnet[“a”].id と記述します。
▼terraform planの出力例(リソースブロック名の行末に[“for_eachで定義したkey”]が付与されて別々に構築される)
参考情報
・The for_each Meta-Argument(公式ドキュメント)https://www.terraform.io/docs/language/meta-arguments/for_each.html
今回はTerraformで、3AZ分のサブネットを1つのリソースブロックで定義・構築する方法をご紹介しました。
補足ですが、ループ処理に用いた「for_each」の “key” = “value” は、variables.tfに定義しておく使い方もあるようです。
しかし、サブネット構築の場合は、CIDRが使い回せる値ではないので、”key” = “value” を変数に入れても可読性が落ちるだけ(複数の箇所を見ないとリソースのパラメータが分からない)です。
言わずもがなですが、他のエンジニアが見てもすぐに内容が分かるtfファイルの方が、チーム内や部署間での内容・構築の連携がはかどります。
この記事を通して、少しでもTerraform習得のお役に立てれば幸いです。