やること
今回は、Terraform を使って Azure にこんな感じの Vnet を作ってみようと思います。
複数の subnet も作ります。Security Group の作成方法は次回の記事で紹介します。
Azure で Terraform を実行する場合は、CloudShell を利用すると便利です。詳しくは、「VSCode に CloudShell と Clouddrive を連携する」をご覧ください。
azurerm_virtual_network
公式サイトを見て必須要素(Required)を確認する
Terraform の azurerm_virtual_network の情報は公式サイトに記載されています。
まず、確認すべきは Argument Reference の必須要素(Required)です。それによると、azurerm_virtual_network のフォーマットはこんな感じです。
resource "azurerm_network_security_group" "sample" {
name = "value"
location = "value"
resource_group_name = "value"
address_space = ["10.0.0.0/16"]
}
azurerm_virtual_network の前提にあるもの
必須要素(Required)に resource_group_name が含まれていますね。これはどういう意味かというと、resource group が前提として必要ということです。
そこで、azurerm_resource_group の情報を公式サイトで調べてみます。
すると、以下のフォーマットであることが分かります。
resource "azurerm_resource_group" "example" {
name = "value"
location = "East US"
}
この name と location はどちらも必須要素(Required)ですね。
Terraform のファイル構成
役割毎にファイル分割
やることは Azure で Vnet を作成するだけですが、可読性を意識して役割毎にファイルを分割したいと思います。
terraform-azure-test01
|-- resource_group.tf
|-- subnet.tf
|-- terraform.tfvars
|-- variables.tf
|-- version.tf
|-- virtual_network.tf
terraform バージョンの注意点
基本的に、Terraform ではバージョンを固定して使用することが推奨されています。理由は、マイナーバージョンアップで大幅な仕様変更があるためです。
ファイル分割時の resource 間の依存関係
私も最初の頃は戸惑ったのですが、Terraform の最近のバージョンでは、resource 間の依存関係は自動的に解決してくれるようになりました。
どういうことかというと、以下の相関関係を Terraform が自動的に解釈して順番に実行してくれるということです。
変数の定義と参照
変数の定義
Terraform でインフラを管理する場合、変数はまとめて管理することが通常です。
今回は、variables.tf と terraform.tfvars で管理しています。
variables.tf で変数を定義
このファイルでは変数(中身の値ではない)を定義しています。
### variables.tf ###
# provider
variable my_subscription_id {}
variable my_tenant_id {}
# resource_group
variable rg01_name {}
variable rg01_location {}
variable tags_owner {}
# azurerm_virtual_network
variable vnet01_name {}
variable vnet01_address {}
variable subnet_prefix {}
variable subnet_pub_count {}
variable subnet_pub_name {}
variable subnet_pri_count {}
variable subnet_pri_name {}
terraform.tfvars で変数に格納する値を定義
実際に変数に代入する値は、このファイルで管理しています。
### terraform.tfvars ###
# provider
my_subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
my_tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# resource_group
rg01_name = "koizumi"
rg01_location = "East US"
tags_owner = "koizumi"
# azurerm_virtual_network
vnet01_name = "vnet01"
vnet01_address = "10.112.0.0/16"
subnet_prefix = 8
subnet_pub_count = 3
subnet_pub_name = "public"
subnet_pri_count = 3
subnet_pri_name = "private"
変数を参照 version.tf
変数の参照方法は基本「 var.name 」です。
複数の変数を組み合わせるときは「 "${var.name}_${var.name}" 」という書き方もします。
### version.tf ###
# terraform version
terraform {
required_version = "= 0.12.28"
}
# azurerm version
provider "azurerm" {
version = "= 2.18.0"
subscription_id = var.my_subscription_id
tenant_id = var.my_tenant_id
features {}
}
※ terraform のバージョンと azurerm のバージョンの組み合わせには注意してください。terraform init が失敗したときは、こちらの記事も参考にしてください。
変数を参照 azurerm_resource_group
こんな感じです。
### resource_group.tf ###
# azurerm_resource_group
resource "azurerm_resource_group" "rg01" {
name = var.rg01_name
location = var.rg01_location
}
virtual_network.tf
azurerm_virtual_network
ここからがメインの azurerm_virtual_network です。
公式サイトで仕様を確認しておきましょう。
- name - (Required)
- resource_group_name - (Required)
- address_space - (Required)
- location - (Required)
- tags - (Optional)
タグはオプションですが、おまけで付けることにしました。
resource_group の値を参照する
Terraform では他の resource の値を参照することができます。わざわざ定数を指定する必要はなくなります。
location と resource_group_name は azurerm_resource_group の値を参照しています。
### virtual_network.tf ###
# azurerm_virtual_network
resource "azurerm_virtual_network" "vnet01" {
name = var.vnet01_name
location = azurerm_resource_group.rg01.location
resource_group_name = azurerm_resource_group.rg01.name
address_space = [var.vnet01_address]
tags = {
Owner = var.tags_owner
}
}
ハマりポイント address_space
上記 address_space の値を見て頂きたいのですが、これは "配列" になっています。
参考までに、以下のように address_space を指定するとエラーが発生します。
### virtual_network.tf ###
# azurerm_virtual_network
resource "azurerm_virtual_network" "vnet01" {
name = var.vnet01_name
location = azurerm_resource_group.rg01.location
resource_group_name = azurerm_resource_group.rg01.name
address_space = var.vnet01_address
tags = {
Owner = var.tags_owner
}
}
試しに、terraform plan を実行してみる。
atsushi_koizumi@Azure:~/clouddrive/terraform-azure-test01$ terraform plsn
Error: Incorrect attribute value type
on virtual_network.tf line 6, in resource "azurerm_virtual_network" "vnet01":
6: address_space = var.vnet01_address
|----------------
| var.vnet01_address is "10.112.0.0/16"
Inappropriate value for attribute "address_space": list of string required.
配列にしてください。と怒られてしまいましたね。
azurerm_subnet
サブネット構成
今回は、以下のように複数のサブネットを作成する予定です。
public subnet を3つと、private subnet を3つです。
cidrsubnet Function
cidrsubnet Function は知っておくと便利です。
複数のサブネットを短いコードで作成することが出来ます。
length Function
length は文字数を取得を取得するのに使います。
こちらに情報が記載されています。
Interpolation
Interpolation Syntax もチェックしておきましょう。
配列の中の要素の取り出し方( var.name[0] )や、count / count.index の使用方法についての説明が記載されています。
subnet.tf
以上の手段を用いて出来たのがこちらの virtual_network.tf です。
### subnet.tf ###
# public subnet
resource "azurerm_subnet" "subnet_pub" {
count = var.subnet_pub_count
resource_group_name = azurerm_resource_group.rg01.name
virtual_network_name = azurerm_virtual_network.vnet01.name
name = "${var.subnet_pub_name}_${count.index}"
address_prefixes = [cidrsubnet(azurerm_virtual_network.vnet01.address_space[0], var.subnet_prefix, count.index + 1)]
}
# private subnet
resource "azurerm_subnet" "subnet_pri" {
count = var.subnet_pri_count
resource_group_name = azurerm_resource_group.rg01.name
virtual_network_name = azurerm_virtual_network.vnet01.name
name = "${var.subnet_pri_name}_${count.index}"
address_prefixes = [cidrsubnet(azurerm_virtual_network.vnet01.address_space[0], var.subnet_prefix, count.index + 101)]
}
terraform apply !
実行してみる
それでは、plan からの apply を実行してみます。
atsushi_koizumi@Azure:~/clouddrive/Twemily/terraform-azure-test01$ terraform plan
Acquiring state lock. This may take a few moments...
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
Plan: 8 to add, 0 to change, 0 to destroy.
atsushi_koizumi@Azure:~/clouddrive/Twemily/terraform-azure-test01$ terraform apply
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Releasing state lock. This may take a few moments...
上手くいきましたね。
結果をポータルで確認
パブリックサブネット3個とプライベートサブネット3個の合計6個のサブネットが作成されていました!
結果から count.index でやってることを解説
言葉で説明するのは難しいので、こんな感じです。
# name = "${var.subnet_pri_name}_${count.index}"
==> private_0, private_1, private_2
# address_prefixes = [cidrsubnet(azurerm_virtual_network.vnet01.address_space[0], var.subnet_prefix, count.index + 101)]
==> [(10.112.0.0/16, 8, 0 + 101)], [(10.112.0.0/16, 8, 1 + 101)], [(10.112.0.0/16, 8, 2 + 101)]
==> [(10.112.0.0/24 の 101番目のサブネット)], [(10.112.0.0/24 の 102番目のサブネット)], [(10.112.0.0/24 の 102番目のサブネット)]
==> [10.112.101.0/24], [10.112.102.0/24], [10.112.103.0/24]
終わりに
続いては、Security Group や Virtual Machine について調べてみたいと思います。
TerraformVNet