複数のサブネットを作成する
いきなりですが、例えば以下のようにAzure環境で4つのサブネットを作るとします。
(providerは省略)
variable "location" {
type = string
default = "japaneast"
}
# リソースグループを作成する
resource "azurerm_resource_group" "rg" {
name = "rg-test"
location = var.location
}
# vNetを作成する
resource "azurerm_virtual_network" "vnet" {
name = "vnet-test-01"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
address_space = ["10.0.0.0/16"]
}
# サブネットを作成する
resource "azurerm_subnet" "subnet" {
count = 4
name = "subnet-${count.index + 1}"
virtual_network_name = azurerm_virtual_network.vnet.name
# cidrsubnet関数は第一引数のCIDRを分割してくれます
address_prefixes = [cidrsubnet(element(azurerm_virtual_network.vnet.address_space, 0), 10, count.index)]
resource_group_name = azurerm_resource_group.rg.name
}
以下はPlan結果。
Terraform will perform the following actions:
# azurerm_resource_group.rg will be created
+ resource "azurerm_resource_group" "rg" {
+ id = (known after apply)
+ location = "japaneast"
+ name = "rg-test"
}
# azurerm_subnet.subnet[0] will be created
+ resource "azurerm_subnet" "subnet" {
+ address_prefixes = [
+ "10.0.0.0/26",
]
+ enforce_private_link_endpoint_network_policies = (known after apply)
+ enforce_private_link_service_network_policies = (known after apply)
+ id = (known after apply)
+ name = "subnet-1"
+ private_endpoint_network_policies_enabled = (known after apply)
+ private_link_service_network_policies_enabled = (known after apply)
+ resource_group_name = "rg-test"
+ virtual_network_name = "vnet-test-01"
}
# azurerm_subnet.subnet[1] will be created
+ resource "azurerm_subnet" "subnet" {
+ address_prefixes = [
+ "10.0.0.64/26",
]
+ enforce_private_link_endpoint_network_policies = (known after apply)
+ enforce_private_link_service_network_policies = (known after apply)
+ id = (known after apply)
+ name = "subnet-2"
+ private_endpoint_network_policies_enabled = (known after apply)
+ private_link_service_network_policies_enabled = (known after apply)
+ resource_group_name = "rg-test"
+ virtual_network_name = "vnet-test-01"
}
# azurerm_subnet.subnet[2] will be created
+ resource "azurerm_subnet" "subnet" {
+ address_prefixes = [
+ "10.0.0.128/26",
]
+ enforce_private_link_endpoint_network_policies = (known after apply)
+ enforce_private_link_service_network_policies = (known after apply)
+ id = (known after apply)
+ name = "subnet-3"
+ private_endpoint_network_policies_enabled = (known after apply)
+ private_link_service_network_policies_enabled = (known after apply)
+ resource_group_name = "rg-test"
+ virtual_network_name = "vnet-test-01"
}
# azurerm_subnet.subnet[3] will be created
+ resource "azurerm_subnet" "subnet" {
+ address_prefixes = [
+ "10.0.0.192/26",
]
+ enforce_private_link_endpoint_network_policies = (known after apply)
+ enforce_private_link_service_network_policies = (known after apply)
+ id = (known after apply)
+ name = "subnet-4"
+ private_endpoint_network_policies_enabled = (known after apply)
+ private_link_service_network_policies_enabled = (known after apply)
+ resource_group_name = "rg-test"
+ virtual_network_name = "vnet-test-01"
}
# azurerm_virtual_network.vnet will be created
+ resource "azurerm_virtual_network" "vnet" {
+ address_space = [
+ "10.0.0.0/16",
]
+ dns_servers = (known after apply)
+ guid = (known after apply)
+ id = (known after apply)
+ location = "japaneast"
+ name = "vnet-test-01"
+ resource_group_name = "rg-test"
+ subnet = (known after apply)
}
Plan: 6 to add, 0 to change, 0 to destroy.
はい、こんな感じになりますね。
ちょっと内部で利用している関数を説明します。
cidrsubnet関数
cidrsubnet関数は第一引数のCIDRを分割してくれます。
例えば以下の通り。
> cidrsubnet("172.17.0.0/16",10,0)
"172.17.0.0/26"
> cidrsubnet("172.17.0.0/16",10,1)
"172.17.0.64/26"
> cidrsubnet("172.17.0.0/16",10,2)
"172.17.0.128/26"
element関数
element関数は、listから単一の要素を取り出します。
つまり、
element(azurerm_virtual_network.vnet.address_space, 0)
は
azurerm_virtual_network.vnet.address_space[0]
と同じです。好みによりますが、element関数を使ったほうがスタイリッシュですね。
ちなみにこんな感じにも書けますね。
one(azurerm_virtual_network.vnet.address_space)
この場合だったらこれが一番シンプルかもしれません。
count
count
はその数字の回数だけ処理を繰り返してくれます。
count.index
を指定すると、その繰り返した回数を取得できます。
例では、subnet名を変えるのに利用していますね。
count
はほとんど同じリソースをつくるのであればfor_each
よりも有効です。
(for_each
の説明は別の機会に)
4つサブネットを名前とIPアドレス範囲のmapにする
サブネット名をキーにしてサブネットのIPアドレスを拾いたいとします。
生成された4つのサブネットを名前とIPアドレスのmap
にしてみましょう。
それにはまずlocal valuesを利用します。
local values
local valuesはvariableの親戚みたいなものですが、大きな違いは以下の通りです。
-
local
では関数や変数が利用できる -
local
で定義したものは外部から上書きできない - 宣言されたモジュール内でのみ使える
例えば、以下のような指定はvariableではできません。
NG例
variable "env"{
type = string
default = "dev"
}
variable "subnet_name"{
type = string
default = "subnet-${var.env}"
}
ですが、localならできちゃいます。
variable "env"{
type = string
default = "dev"
}
locals{
subnet_name = "subnet-${var.env}"
}
local valuesを利用することで、効率化したコードを書くことができます。
便利でなおかつ気持ちがいい!
サブネット名とアドレスをlist→mapにしてみる
早速local valuesを利用して4つのサブネット名とアドレスをそれぞれリストにし、zipmap
関数で統合します。zipmap
関数は特に説明しませんが、2つのlistを合体させてmapにできます。
locals {
subnet_name = [for s in azurerm_subnet.subnet : s.name]
subnet_address = [for s in azurerm_subnet.subnet : s.address_prefixes]
subnet = zipmap(local.subnet_name, local.subnet_address)
}
output "output_subnet" {
value = local.subnet
}
ここで注意してほしいのは、azurerm_subnet.subnet.address_prefixes
はもともとlistであること。つまりlist化するとlistの中にlistがあるという構造となってしまいます。つまり以下。
Changes to Outputs:
+ output_subnet = {
+ subnet-1 = [
+ "10.0.0.0/26",
]
+ subnet-2 = [
+ "10.0.0.64/26",
]
+ subnet-3 = [
+ "10.0.0.128/26",
]
+ subnet-4 = [
+ "10.0.0.192/26",
]
}
これを解決するために flatten関数を使います。
flatten関数
flatten関数は複数のリストを1つのリストに統合してくれます(フラット化)
入れ子構造になっている場合は有効です。
サンプル
> flatten(["a","b"])
[
"a",
"b",
]
> flatten(["a","b",["c","d","e"]])
[
"a",
"b",
"c",
"d",
"e",
]
では以下のように書き換えてみましょう。
locals {
subnet_name = [for s in azurerm_subnet.subnet : s.name]
subnet_address = flatten([for s in azurerm_subnet.subnet : s.address_prefixes])
subnet = zipmap(local.subnet_name, local.subnet_address)
}
output "output_subnet" {
value = local.subnet
}
すると、以下のようにきれいにmapとなりました。
Changes to Outputs:
+ output_subnet = {
+ subnet-1 = "10.0.0.0/26"
+ subnet-2 = "10.0.0.64/26"
+ subnet-3 = "10.0.0.128/26"
+ subnet-4 = "10.0.0.192/26"
}
やったね!
参考(公式ドキュメント)
element
https://developer.hashicorp.com/terraform/language/functions/element
cidrsubnet
https://developer.hashicorp.com/terraform/language/functions/cidrsubnets
count
https://developer.hashicorp.com/terraform/language/meta-arguments/count
for_each
https://developer.hashicorp.com/terraform/language/meta-arguments/for_each
locals
https://developer.hashicorp.com/terraform/language/values/locals
zipmap
https://developer.hashicorp.com/terraform/language/functions/zipmap
flatten
https://developer.hashicorp.com/terraform/language/functions/flatten