Azure Terraform Vnet

  • Terraform
  • VNet
  • やること

    今回は、Terraform を使って Azure にこんな感じの Vnet を作ってみようと思います。

    複数の subnet も作ります。Security Group の作成方法は次回の記事で紹介します。

    title

    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 が自動的に解釈して順番に実行してくれるということです。

    azure-terraform-vnet-01

    変数の定義と参照

    変数の定義

    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

    サブネット構成

    今回は、以下のように複数のサブネットを作成する予定です。

    title

    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個のサブネットが作成されていました!

    azure-terraform-vnet-03

    結果から 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 について調べてみたいと思います。

  • Terraform
  • VNet