こんにちは。リモートワークに伴う運動不足解消のため、日々、Z戦士として走り込んでいるCTO室のkazです。
概要
Terraform 0.12以前はcount-functionとcidrsubnet-functionを使用してネットワークを作成していましたが、ネットワークに変更が入るときにリソースが再作成されてしまう問題がありました。また、可読性も落ちます。HCL2ではfor_eachを使うことで可読性を上げ、既存リソースに影響が出ないようにリファクタリングできます。
count
リソースのcountパラメーターを使用すると、構成を単純化し、単純に数値を増加させることによってリソースを拡張することができます。
resource "aws_instance" "web" { instance_type = "t3.small" ami = lookup(var.aws_amis, var.aws_region) # This will create 4 instances count = 4 }
cidrsubnet
3つの引数を使用してネットワークを計算してくれます。
cidrsubnet(prefix, newbits, netnum)
- prefixはCIDR表記で指定
- newbitsはプレフィックスを拡張する追加ビットの数
- netnumは、2進数で表現できる整数
> cidrsubnet("172.20.0.0/16", 3, 2) 172.20.64.0/19 > cidrsubnet("172.20.0.0/24", 4, 15) 172.20.0.240/28
cidrsubnet("172.20.0.0/16", 3, x)を例にすると、netnumをインクリメントしていくと/16の上位3bitにインクリメントしたビットが割り当てられるので、 下記のようなネットワークが作成されます。
172.20.0.0 10101100.00010100. 00000000.00000000 172.20.32.0 10101100.00010100.001 00000.00000000 172.20.64.0 10101100.00010100.010 00000.00000000 172.20.96.0 10101100.00010100.011 00000.00000000 172.20.128.0 10101100.00010100.100 00000.00000000 172.20.160.0 10101100.00010100.101 00000.00000000 172.20.192.0 10101100.00010100.110 00000.00000000 172.20.224.0 10101100.00010100.111 00000.00000000
上記を踏まえ、4つのネットワークを作成する設定は下記になります。
- region = ap-northeast-1
- availability zone = apne1-az4,apne1-az1
aws_subnet
resource "aws_subnet" "environment_example_subnet" { count = 4 vpc_id = data.aws_vpc.environment_example.id availability_zone = var.environment_example_subnet_availability_zones[count.index % 2] cidr_block = cidrsubnet(data.aws_vpc.environment_example.cidr_block, 3, count.index) tags = { Name = var.environment_example_subnet_names[count.index] Service = "environment_example" Description = "Managed by Terraform" } }
variables
variable "environment_example_subnet_availability_zones" { type = list default = [ "ap-northeast-1a", "ap-northeast-1c", ] }
問題点
この設定だと、countやvariableの値を変更すると、aws_subnet.environment_example_subnet[x]
の各配列が再作成されて既存環境に影響が出てしまいます。
解決策
for_each
for_eachでmapを使用すると、定義されている要素の数だけループするので、配列に配慮せずに変更が可能になり、可読性も上がります。
aws_subnet
resource "aws_subnet" "environment_example_subnet" { vpc_id = aws_vpc.environment_example.id availability_zone = each.value.zone for_each = var.environment_example_subnets cidr_block = each.value.cidr map_public_ip_on_launch = each.value.launch tags = { Name = each.value.name Service = "environment_example" Description = "Managed by Terraform" } }
variables
variable "environment_example_subnets" { type = map default = { public-1a = { cidr = "172.20.0.0/19" zone = "ap-northeast-1a" launch = "true" name = "environment-example-public-a" } public-1c = { cidr = "172.20.32.0/19" zone = "ap-northeast-1c" launch = "true" name = "environment-example-public-c" } private-1a = { cidr = "172.20.64.0/19" zone = "ap-northeast-1a" launch = "false" name = "environment-example-private-a" } private-1c = { cidr = "172.20.128.0/19" zone = "ap-northeast-1c" launch = "false" name = "environment-example-private-c" } } }
ENECHANGEではエネルギーの未来を作る仲間を募集しています。 ぜひエントリーを!!!!