LoginSignup
16
2

More than 1 year has passed since last update.

複数のサブネットを作成する

いきなりですが、例えば以下のように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の親戚みたいなものですが、大きな違いは以下の通りです。

  1. localでは関数や変数が利用できる
  2. localで定義したものは外部から上書きできない
  3. 宣言されたモジュール内でのみ使える

例えば、以下のような指定は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

16
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
2