[Terraform/AWS]複数のサブネットを一度に作る
はじめに
AWSでVPCを構築する際、パブリックサブネットとプライベートサブネットそれぞれ3AZずつの計6個(もしくは2AZずつの計4個)以上を作成するケースがあるかと思います。
今回、その個数分だけTerraformのresourceを記述するのではなく、まとめて作成してみたいと思います。
本記事ではTerraformの以下の機能を使います。
count
count.index
-
cidrsubnet
関数 -
length
関数
環境
- Terraform 0.14.3
count
count
を使うことで、指定した数だけresourceが作成されます。
resource "aws_subnet" "public" {
count = 3
// 略
}
resource "aws_subnet" "private" {
count = 3
// 略
}
なお、count
によって作成されたリソースは、0
から始まる連番となります。
# aws_subnet.public[0] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
// 略
}
もし、連番0
であるリソースの要素(例えばid
)を参照する場合は、以下のように指定します。
resource "aws_nat_gateway" "example" {
// 略
subnet_id = aws_subnet.public[0].id
// 略
}
count.index
count
によって各サブネットが3個作成されますが、それぞれのアベイラビリティゾーンは別のものにする必要があります。
そのためにcount.index
を使うことにします。
まず、あらかじめアベイラビリティゾーン名を格納するlist型の変数availability_zones
を定義します。
variable "availability_zones" {
type = list(string)
default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}
その上で、list型である変数availability_zones
のインデックスを、count.index
で指定するようにします。
resource "aws_subnet" "public" {
count = 3
availability_zone = var.availability_zones[count.index]
// 略
}
resource "aws_subnet" "private" {
count = 3
availability_zone = var.availability_zones[count.index]
// 略
}
これで、
- 各サブネットの1個目は、アベイラビリティゾーンが
ap-northeast-1a
- 各サブネットの2個目は、アベイラビリティゾーンが
ap-northeast-1c
- 各サブネットの3個目は、アベイラビリティゾーンが
ap-northeast-1d
となります。
cidrsubnet関数とlength関数
最後に、各サブネットのCIDRがそれぞれ異なるようにします。
これにはcidrsubnet
関数を使います。
cidrsubnet
関数の使い方は以下の例を見たほうがわかりやすいと思います。
第一引数のCIDRを分割して返してくれます。
$ terrafform console
> cidrsubnet("172.31.0.0/16", 8, 0)
"172.31.0.0/24"
> cidrsubnet("172.31.0.0/16", 8, 1)
"172.31.1.0/24"
このcidrsubnet
関数を使うと、サブネットの定義は以下になります。
resource "aws_subnet" "public" {
count = 3
availability_zone = var.availability_zones[count.index]
cidr_block = cidrsubnet(aws_vpc.vpc.cidr_block, 8, count.index)
// 略
}
resource "aws_subnet" "private" {
count = 3
availability_zone = var.availability_zones[count.index]
cidr_block = cidrsubnet(aws_vpc.vpc.cidr_block, 8, count.index + length(aws_subnet.public))
// 略
}
なお、プライベートサブネットでは、パブリックサブネットとCIDRが重複しないよう、length
関数を使用してcidrsubnet
関数の第三引数を
- count.index + length(aws_subnet.public))
としています。
これにより、
- パブリックサブネットの3個目 :
cidrsubnet({VPCのCIDR}, 8, 2)
- プライベートサブネットの1個目 :
cidrsubnet({VPCのCIDR}, 8, 3)
となり、CIDRが重複せず、連続するようになります。
終わりに
count
の存在はもともと知ってはいたのですが、cidrsubnet
関数は非常に便利ですね。
Terraformには他にも便利な関数があるので積極活用していきたいと思います。
Discussion