Terraformを用いたAzureインフラ構築

# 前提とゴール
この記事ではTerraformというツールを用いてAzure環境構築を行っていく方法を紹介しています。
Azureに関する基礎知識は身に着けていることを前提としています。

ゴールは以下のような環境をAzure上に作成することです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504436/df3c8292-f73f-4667-6244-6d1a57b99c2a.png)

# Terraformとは
[HashiCorp社](https://www.terraform.io/)によって提供されているIaC(Infrastructure as Code)ツールになります。
IaCとは簡単にいうとインフラ構築をコード化するということです。IaCを用いることで以下のようなメリットがあります。

- 環境をコードで管理することができ、Git等を用いた管理を行える
- 誰でも同じ環境を構築することができる

このようなIaCツールの中でTerraformは、Azureを始めとした様々なサービスに対応することができ、比較的短いコードで記載することができるという特徴があります。そのため、IaCツールの中ではデファクトスタンダードになっています。

# 環境準備のための参考サイト
#### wsl2セットアップ（Windows11）
[https://dev.classmethod.jp/articles/how-to-setup-wsl2-for-windows11/](https://dev.classmethod.jp/articles/how-to-setup-wsl2-for-windows11/)
#### terraformのインストール
[https://computingforgeeks.com/how-to-install-terraform-on-ubuntu/](https://computingforgeeks.com/how-to-install-terraform-on-ubuntu/)
#### tfenv(terraformのversion管理)のインストール
[https://engineer-lifestyle-blog.com/code/terraform-install-tfenv-usage-command-list/](https://engineer-lifestyle-blog.com/code/terraform-install-tfenv-usage-command-list/)
#### azコマンドのインストール
[https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli-linux?pivots=apt](https://learn.microsoft.com/ja-jp/cli/azure/install-azure-cli-linux?pivots=apt)

## Terraformの認証
azコマンド及びterraformのインストールまで完了したら、AzureでTerraformを認証します。以下の4つの環境変数を設定することで認証できるので、それぞれの設定値の取得方法について見ていき、これらをbashrc内に追記します。

- ARM_SUBSCRIPTION_ID
- ARM_TENANT_ID
- ARM_CLIENT_ID
- ARM_CLIENT_SECRET

まずはazコマンドを用いてAzureにloginします。ブラウザが立ち上がるため、ログインを行ってください。
```bash:input
az login
```
ブラウザ上でログインを行うとコンソールに以下のような結果が出力されます。これらは自身のサブスクリプションIDやテナントIDの情報になります。
```bash:output
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Azure subscription 1",
    "state": "Enabled",
    "tenantId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "user": {
      "name": "user name",
      "type": "user"
    }
  }
]
```
得られた出力の中でidの項目に記載されているサブスクリプションIDを用い、az ad sp create-for-rbacコマンドを実行することでサービスプリンシパルを作成します。
```bash:input
az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
```
上記コマンドを実行すると以下のような結果が出力されます。
```bash:output
{
  "appId": "cccccccc-cccc-cccc-cccc-cccccccccccc",
  "displayName": "azure-cli-2023-10-15-10-01-05",
  "password": "dddddddddddddddddddddddddddddddddd",
  "tenant": "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"
}
```
以上で必要な情報は出力し終えたため、環境変数を設定します。設定すべき環境変数と設定値は以下のような対応関係になります。

|環境変数|設定値|key|
|--|--|--|
|ARM_SUBSCRIPTION_ID|bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb|id|
|ARM_CLIENT_ID|cccccccc-cccc-cccc-cccc-cccccccccccc|appId|
|ARM_CLIENT_SECRET|dddddddddddddddddddddddddddddddddd|password|
|ARM_TENANT_ID|eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee|tenant|

これらを設定するようにbashrc内に追記を行います。具体的には以下の内容を追記します。
```bash:~/.bashrc
export ARM_SUBSCRIPTION_ID="bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
export ARM_CLIENT_ID="cccccccc-cccc-cccc-cccc-cccccccccccc"
export ARM_CLIENT_SECRET="dddddddddddddddddddddddddddddddddd"
export ARM_TENANT_ID="eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"
```

これで設定は完了です。

# Terraformのコマンド
基本的にTerraformでは.tf拡張子のファイルを作成していきます。
作成したファイルは1つのワークスペース用ディレクトリに配置して、Azureへの反映を行います。
特定のディレクトリをワークスペースに登録するには以下のコマンドを使用します。
```bash
terraform init
```
続いて、.tf拡張子のファイルの配置が完了したら以下のコマンドを使用して、.tfファイルに記載された内容の変更されるリソース情報を確認します。
```bash
terraform plan
```
上記コマンドを実行し、特に問題なければAzureへの反映を行います。反映は以下のコマンドを用いて実行します。
```
terraform apply
```

# Terraformの文法
この章では要素ごとのコードの記述方法について紹介しています。

## providerの作成
Azureのリソースとは直接関係しませんが、Terraformを使うには、まずprovider（今回provider.tf）を作成する必要があります。このproviderには、どのクラウドサービスを使用するのかという情報を記載します。そのため、同じクラウドサービスを使用する場合、基本的には同じ文言となります。Azureの場合は以下のように記載します。
```Terraform:provider.tf
Terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.0.0"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  skip_provider_registration = true # This is only required when the User, Service Principal, or Identity running Terraform lacks the permissions to register Azure Resource Providers.
  features {}
}
```
## Azureのリソースの作成
Azure上のリソースを作成する場合の基本的な文法は以下のようになります。
```Terraform
resource "リソース名" "任意の名前"{
    設定項目1="設定値1"
    設定項目2="設定値2"
    ...
}
```
また以下の節では各リソースに対するリソース名、設定項目、実際のコードの流れで情報を記載しております。また公式のドキュメントページのリンクを記載しておきます。今回の説明では必要な設定項目のみを説明しておりますので、その他の設定項目等については公式ドキュメントを適宜参照してください。

### リソースグループの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group)
##### リソース名
*azurerm_resource_group*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|リソースグループの名前|sample_rg|
|location|リソースグループのregion|japaneast|
##### コード
```Terraform:resource_group.tf
resource "azurerm_resource_group" "resource_group" {
  name     = "sample_rg"
  location = "japaneast"
}
```

### Virtual Networkの作成
#### Virtual Networkの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network)
##### リソース名
*azurerm_virtual_network*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Virtual Networkの名前|sample_vnet|
|local|Virtual Networkのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|resource_group_name|Virtual Networkをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|address_space|Virtual Networkのアドレス空間|10.0.0.0/16|
##### コード
```terraform:virtual_network.tf
resource "azurerm_virtual_network" "virtual_network" {
  name                = "sample_vnet"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name
  address_space       = ["10.0.0.0/16"]
}
```

#### Sub Networkの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet)
##### リソース名
*azurerm_subnet*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Sub Networkの名前|public,private|
|address_prefixes|アドレスプレフィックス|10.0.1.0/24,10.0.2.0/24|
|resource_group_name|Sub Networkをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|virtual_network_name|Sub NetworkをどのVirtual Networkに作成するか|sample_vnet（上で作成したvirtual networkのnameを参照させる）|
|service_endpoints|Sub Networkに関連付けるサービス エンドポイントのリスト|Microsoft.Sql|
##### コード
```terraform:virtual_network.tf
resource "azurerm_subnet" "public" {
  name                 = "public"
  resource_group_name  = azurerm_resource_group.resource_group.name
  virtual_network_name = azurerm_virtual_network.virtual_network.name
  address_prefixes     = ["10.0.1.0/24"]
}
resource "azurerm_subnet" "private" {
  name                 = "private"
  resource_group_name  = azurerm_resource_group.resource_group.name
  virtual_network_name = azurerm_virtual_network.virtual_network.name
  address_prefixes     = ["10.0.2.0/24"]
  service_endpoints    = ["Microsoft.Sql"]
}
```

### ネットワークインターフェースの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface)
##### リソース名
*azurerm_network_interface*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Network Interfaceの名前|network_interface|
|location|Network Interfaceのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|resource_group_name|Network Interfaceをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|ip_configuration|IPの構成設定|以下参照|

ip_configuration
|key|概要|今回の設定値|
|--|--|--|
|name|IP Configurationの名前|ip_configuration|
|subnet_id|どのSub Networkに所属させるか|上で作成したSub Network(private)のidを参照させる|
|private_ip_address_allocation|IPアドレスを明示的に割り当てるか|Dynamic|

##### コード
```terraform:network_interface.tf
resource "azurerm_network_interface" "network_interface" {
  name                = "network_interface"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name

  ip_configuration {
    name                          = "ip_configuration"
    subnet_id                     = azurerm_subnet.private.id
    private_ip_address_allocation = "Dynamic"
  }
}
```

### Network Security Groupの作成
#### Network Security Groupの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_group)
##### リソース名
*azurerm_network_security_group*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Network Interfaceの名前|network_security_group|
|location|Network Interfaceのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|resource_group_name|Network Security Groupをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
##### コード
```terraform:network_security_group.tf
resource "azurerm_network_security_group" "network_security_group" {
  name                = "network_security_group"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name
}
```

#### Network Security Ruleの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_rule)
##### リソース名
*azurerm_network_security_rule*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Network Security Ruleの名前|RDP,HTTP|
|priority|ルールの優先度|100,110|
|direction|受信か送信か|Inbound|
|access|アクセス許可|Allow|
|protocol|プロトコル|Tcp|
|source_port_range|どのポートから受信するか|*|
|destination_port_range|どのポートに送信するか|3389,80|
|source_address_prefix|どのアドレスから受信するか|*|
|destination_address_prefix|どのアドレスへ送信するか|*|
|resource_group_name|Network Security Ruleをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|network_security_group_name|Network Security RuleをどのNetwork Security Groupに適用するか|network_security_group（上で作成したnetwork_security_groupのnameを参照させる）|

##### コード
```terraform:network_security_group.tf
resource "azurerm_network_security_rule" "rdp" {
  name                        = "RDP"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "3389"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.resource_group.name
  network_security_group_name = azurerm_network_security_group.network_security_group.name
}
resource "azurerm_network_security_rule" "http" {
  name                        = "HTTP"
  priority                    = 110
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "80"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.resource_group.name
  network_security_group_name = azurerm_network_security_group.network_security_group.name
}
```

#### Network Interface-Network Security Groupの関連付けの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface_security_group_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface_security_group_association)
##### リソース名
*azurerm_network_interface_security_group_association*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|network_interface_id|関連付けを行うNetwork InterfaceのID|上で作成したNetwork Interfaceのidを参照させる|
|network_security_group_id|関連付けを行うNetwork Security GroupのID|上で作成したNetwork Security Groupのidを参照させる|
##### コード
```terraform:network_security_group.tf
resource "azurerm_network_interface_security_group_association" "network_interface_security_group_association" {
  network_interface_id      = azurerm_network_interface.network_interface.id
  network_security_group_id = azurerm_network_security_group.network_security_group.id
}
```

### Virtual Machineの作成
#### Virtual Machineの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/windows_virtual_machine](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/windows_virtual_machine)
##### リソース名
*azurerm_windows_virtual_machine*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Virtual Machineの名前|virtual_machine|
|resource_group_name|Virtual Machineをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|location|Virtual Machineのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|size|AzureのSKU|Standard_D2s_v3|
|admin_username|管理者権限ユーザの名前|admin|
|admin_password|管理者権限ユーザのパスワード|Password|
|network_interface_ids|どのネットワークインターフェースに割り当てるか|上で作成したNetwork Interfaceのidを参照させる|
|os_disk|-|以下参照|
|source_image_reference|-|以下参照|

os_disk
|key|概要|今回の設定値|
|--|--|--|
|caching|OS ディスクに使用するキャッシュのタイプ|ReadWrite|
|storage_account_type|OS ディスクをバックアップするストレージアカウントのタイプ|Standard_LRS|

source_image_reference
|key|概要|今回の設定値|
|--|--|--|
|publisher|Virtual Machineの作成に使用されるイメージの発行者|MicrosoftWindowsServer|
|offer|Virtual Machineの作成に使用されるイメージのオファー|WindowsServer|
|sku|Virtual Machineの作成に使用されるイメージのSKU|2019-Datacenter|
|version| Virtual Machineの作成に使用されるイメージのバージョン|latest|


##### コード
```terraform:virtual_machine.tf
resource "azurerm_windows_virtual_machine" "virtual_machine" {
  name                = "virtual_machine"
  resource_group_name = azurerm_resource_group.resource_group.name
  location            = azurerm_resource_group.resource_group.location
  size                = "Standard_D2s_v3"
  admin_username      = "admin"
  admin_password      = "Password"
  network_interface_ids = [
    azurerm_network_interface.network_interface.id,
  ]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter"
    version   = "latest"
  }
}
```

#### Virtual machineの拡張機能の作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine_extension](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine_extension)
##### リソース名
*azurerm_virtual_machine_extension*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Virtual Machine拡張ピアリングの名前|install-iis|
|virtual_machine_id|Virtual Machineの ID|上で作成したVirtual Machineのidを参照させる|
|publisher|拡張機能の発行者|Microsoft.Compute|
|type|拡張機能の種類|CustomScriptExtension|
|type_handler_version|使用する拡張機能のバージョン|1.9.5|
|settings|拡張機能に渡される設定|-|

##### コード
```terraform:virtual_machine.tf
resource "azurerm_virtual_machine_extension" "virtual_machine_extension" {
  name                 = "install-iis"
  virtual_machine_id   = azurerm_windows_virtual_machine.virtual_machine.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.9"

  settings = <<SETTINGS
 {
    "commandToExecute": "powershell -ExecutionPolicy Unrestricted Install-WindowsFeature -Name Web-Server -IncludeAllSubFeature -IncludeManagementTools"
 }
SETTINGS
}
```

### Public IPの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip)
##### リソース名
*azurerm_public_ip*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Public IPの名前|public_ip|
|location|Public IPのresgion|japaneast（上で作成したresource groupのlocalを参照させる）|
|resource_group_name|Public IPをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|allocation_method|IPアドレスの割り当て方法|Static|
|sku|Public IPのSKU|Standard|

##### コード
```terraform:bastion.tf
resource "azurerm_public_ip" "public_ip" {
  name                = "public_ip"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name
  allocation_method   = "Static"
  sku                 = "Standard"
}
```

### Bastionの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/bastion_host](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/bastion_host)
##### リソース名
*azurerm_bastion_host*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Bastionの名前|bastion_host|
|location|Bastionのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|resource_group_name|Bastionをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|ip_configuration|-|以下参照|

ip_configuration
|key|概要|今回の設定値|
|--|--|--|
|name|IP構成の名前|bas_configuration|
|subnet_id |bastionを作成するSub Network|新規作成したSubNet(bastion)のidを参照させる|
|public_ip_address_id|bastionに関連付けるPublic IPアドレス|上で作成したパブリックIPのidを参照させる|

##### コード
併せてBastionの所属するSub Networkの作成を行っています。
```terraform:bastion.tf
resource "azurerm_bastion_host" "bastion_host" {
  name                = "bastion_host"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name

  ip_configuration {
    name                 = "bas_configuration"
    subnet_id            = azurerm_subnet.bastion.id
    public_ip_address_id = azurerm_public_ip.public_ip.id
  }
}
```
```terraform:virtual_network.tf
resource "azurerm_subnet" "bastion" {
  name                 = "AzureBastionSubnet"
  resource_group_name  = azurerm_resource_group.resource_group.name
  virtual_network_name = azurerm_virtual_network.virtual_network.name
  address_prefixes     = ["10.0.3.0/27"]
}
```

### Load Balancerの作成
#### Load Balancerの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb)
##### リソース名
*azurerm_lb*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Load Balancerの名前|LoadBalancer|
|location|Load Balancerのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|resource_group_name|Load Balancerどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|frontend_ip_configuration|-|以下参照|

frontend_ip_configuration
|key|概要|今回の設定値|
|--|--|--|
|name|フロントエンドIP構成の名前|PublicIPAddress|
|public_ip_address_id|Load Balancerに関連付ける必要があるPublic IPアドレスのID|新規作成したPublic IP(public_ip_lb)のidを参照させる|

##### コード
併せてLoad Balancerの所属するPublic IPの作成を行っています。
```terraform:lb.tf
resource "azurerm_lb" "lb" {
  name                = "LoadBalancer"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name

  frontend_ip_configuration {
    name                 = "PublicIPAddress"
    public_ip_address_id = azurerm_public_ip.public_ip_lb.id
  }
}

resource "azurerm_public_ip" "public_ip_lb" {
  name                = "public_ip"
  location            = azurerm_resource_group.resource_group.location
  resource_group_name = azurerm_resource_group.resource_group.name
  allocation_method   = "Static"
  sku                 = "Standard"
}
```

#### Backend Address Poolの作成
[icorp/azurerm/latest/docs/resources/lb_backend_address_pool](icorp/azurerm/latest/docs/resources/lb_backend_address_pool)
##### リソース名
*azurerm_lb_backend_address_pool*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|loadbalancer_id|Backend Address Poolを作成するLoad BalancerのID|上で作成したLoad Balancerのidを参照させる|
|name|Backend Address Poolの名前|lb_backend_address_pool|
##### コード
```terraform:lb.tf
resource "azurerm_lb_backend_address_pool" "lb_backend_address_pool" {
  loadbalancer_id = azurerm_lb.example.id
  name            = "lb_backend_address_pool"
}
```

#### Backend Address Poolの関連付けの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface_backend_address_pool_association](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface_backend_address_pool_association)
##### リソース名
*azurerm_network_interface_backend_address_pool_association*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|network_interface_id|Network InterfaceのID|上で作成したNetwork Interfaceのidを参照させる|
|ip_configuration_name|tmp|configuration|
|backend_address_pool_id|Network Interfaceが接続されるBackend Address PoolのID|上で作成したBackend Address Poolのidを参照させる|
##### コード
```terraform:lb.tf
resource "azurerm_network_interface_backend_address_pool_association" "nibapa" {
  network_interface_id    = azurerm_network_interface.network_interface.id
  ip_configuration_name   = "configuration"
  backend_address_pool_id = azurerm_lb_backend_address_pool.lb_backend_address_pool.id
}
```

#### 正常性probeの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_probe](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_probe)
##### リソース名
*azurerm_lb_probe*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|loadbalancer_id|NATルールを作成するLoad BalancerのID|上で作成したLoad Balancerのidを参照させる|
|name|probeの名前|lb-probe|
|port|probeがBackend Endpointにクエリを実行するポート|22|
##### コード
```terraform:lb.tf
resource "azurerm_lb_probe" "lb-probe" {
  loadbalancer_id = azurerm_lb.lb.id
  name            = "lb-probe"
  port            = 80
}
```

#### 負荷分散規則の作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_rule)
##### リソース名
*azurerm_lb_rule*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|loadbalancer_id|ルールを作成するLoad BalancerのID|上で作成したLoad Balancerのidを参照させる|
|name|負荷分散規則の名前|LBRule|
|protocol|外部Endpointのトランスポートプロトコル|Tcp|
|frontend_port|外部Endpointのポート|80|
|backend_port|Endpointの内部接続に使用されるポート|80|
|backend_address_pool_ids|この負荷分散規則が動作するBackend Address PoolのID|上で作成したBackend Address Poolのidを参照させる|
|frontend_ip_configuration_name|ルールが関連付けられているフロントエンドIP構成の名前|PublicIPAddress|
|probe_id|この負荷分散規則で使用されるprobeのID|上で作成したprobeのidを参照させる|
##### コード
```terraform:lb.tf
resource "azurerm_lb_rule" "lb_rule" {
  loadbalancer_id                = azurerm_lb.lb.id
  name                           = "LBRule"
  protocol                       = "Tcp"
  frontend_port                  = 80
  backend_port                   = 80
  backend_address_pool_ids       = azurerm_lb_backend_address_pool.lb_backend_address_pool.id
  frontend_ip_configuration_name = "PublicIPAddress"
  probe_id                       = azurerm_lb_probe.lb-probe.id
}
```
### SQL Serverの作成
#### Serverの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_server](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_server)
##### リソース名
*azurerm_sql_server*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|SQL Serverの名前|sqlserver|
|resource_group_name|SQL Serverをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|location|SQL Serverのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|version|Serverのバージョン|12.0|
|administrator_login|Serverの管理者のログイン名|admin|
|administrator_login_password|ユーザーに関連付けられたパスワード|Password|
##### コード
```terraform:sql_server.tf
resource "azurerm_sql_server" "sql_server" {
  name                         = "sqlserver"
  resource_group_name          = azurerm_resource_group.resource_group.name
  location                     = azurerm_resource_group.resource_group.location
  version                      = "12.0"
  administrator_login          = "admin"
  administrator_login_password = "Password"
}
```

#### Firewallの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_firewall_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_firewall_rule)
##### リソース名
*azurerm_sql_firewall_rule*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Firewall Ruleの名前|FirewallRule|
|resource_group_name|Firewall Ruleをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|server_name|Firewall Ruleを作成するSQL Serverの名前|上で作成したSQL Serverのnameを参照させる|
|start_ip_address|Firewall通過を許可する開始IPアドレス|0.0.0.0|
|end_ip_address|Firewall通過を許可する終了IPアドレス|0.0.0.0|
##### コード
```terraform:sql_server.tf
resource "azurerm_sql_firewall_rule" "sql_firewall_rule" {
  name                = "FirewallRule"
  resource_group_name = azurerm_resource_group.resource_group.name
  server_name         = azurerm_sql_server.sql_server.name
  start_ip_address    = "0.0.0.0"
  end_ip_address      = "0.0.0.0"
}
```

#### Databaseの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_database](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_database)
##### リソース名
*azurerm_sql_database*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|Databaseの名前|sqldatabase|
|resource_group_name|Databaseをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|location|Databaseのregion|japaneast（上で作成したresource groupのlocalを参照させる）|
|server_name|Databaseを作成するSQL Serverの名前|上で作成したSQL Serverのnameを参照させる|
##### コード
```terraform:sql_server.tf
resource "azurerm_sql_database" "sql_database" {
  name                = "sqldatabase"
  resource_group_name = azurerm_resource_group.resource_group.name
  location            = azurerm_resource_group.resource_group.location
  server_name         = azurerm_sql_server.sql_server.name
}
```

#### Service End Pointの作成
[https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_virtual_network_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/sql_virtual_network_rule)
##### リソース名
*azurerm_sql_virtual_network_rule*
##### 設定項目
|key|概要|今回の設定値|
|--|--|--|
|name|SQL Virtual Network Ruleの名前|sql-vnet-rule|
|resource_group_name|SQL Virtual Network Ruleをどのリソースグループ上に作成するか|sample_rg（上で作成したresource groupのnameを参照させる）|
|server_name|SQL Virtual Network Ruleが適用されるSQL Serverの名前|上で作成したSQL Serverのnameを参照させる|
|subnet_id|SQL Serverが接続されるSub NetworkのID|上で作成したSub Network(private)のidを参照させる|
##### コード
```terraform:sql_server.tf
resource "azurerm_sql_virtual_network_rule" "sql_virtual_network_rule" {
  name                = "sql-vnet-rule"
  resource_group_name = azurerm_resource_group.resource_group.name
  server_name         = azurerm_sql_server.sql_server.name
  subnet_id           = azurerm_subnet.private.id
}
```
## 完成
以上の通りファイルを作成していき、terraform applyを実行することでAzure上に目的のとしていた構成が完成します。

# 最後に
今回の記事ではTerraformを用いてAzure上に環境を構築してみました。実際の運用では変数の利用やモジュール化を用いますが、今回はリソースを作るということを実施しました。
基本的な使用方法についてはおおよそ理解できたかと思いますが、その他の情報については、必要に応じて[公式サイト](https://registry.terraform.io/)を確認してください。
また、記載内容に誤りがありましたらコメントいただければと思います。