Terraform で ExpressRoute や VritualNetworkGateway を用いて専用線接続の設定を行う

# reference
- https://qiita.com/moaikids/items/26ee0db670ae9d9fa158
- https://qiita.com/moaikids/items/8a7b72f51662c3cb214d

# はじめに
今回は、ExpressRoute や VirtualNetworkGateway の設定を Terraform から行い、Azure への専用線接続の設定を行います。

Azure に対して専用線経由で接続するというのはそこまで多いケースではないと思いますし、それを Terraform で設定するという面で公開されている事例も少ないように見えます。
ですので、なんとなくノウハウ的なものを書いておきます。


# 構築シナリオ
今回は以下を構築・設定します。

- あらかじめ、回線業者軽油で専用線の契約を行っておく
- 専用線 - ExpressRoute - Connection - VirtualNetworkGateway という経路で、特定の ResourceGroup(vNet/Subnet)に対して接続設定を行う。

# 概要
## ExpressRoute について
専用線と Azure リソースを接続するための手段して、Azure では ExpressRoute という機能が提供されています。こちらの機能を通じて、専用線と Azure リソースのピアリングを行います。

AWS における Direct Connect と、提供する機能が同じというわけではないですが、専用線接続を行う観点においては似たような機能になります。

<https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-circuit-peerings>

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44364/3d1e0bf2-31d2-5464-e1a2-e94205531cde.png)


Azure とのピアリング方式は以下３種が提供されています。

- Azure プライベートピアリング
- Azure パブリックピアリング
- Microsoft ピアリング

ここでは、「Azure プライベートピアリング」のみ対象にします。

## Azure リソースへの経路
構築シナリオにもなんとなく記載していますが、専用線から Azure リソースにアクセスするためには、以下の設定を行う必要があります。

- Resource Group / Virtual Network / Subnet
  - Azure 側のリソースの基本的な設定です。
- Virtual Network Gateway
  - 後述の ExpressRoute Circuit と Virutan Network を接続するための Gateway になります。こちらを通じて ExpressRoute と VirtualNetwork を接続します。
- ExpressRoute Circuit
  - 専用線と、Azure 側のリソースを接続するための回路の設定を行います。 
- Private Peering
  - ExpressRoute Circuit と Azure のネットワークの Peering 設定です。
- Connection(Virutal Network と Express Route の接続)
  - 上記で用意した ExpressRoute と VirtualNetworkGateway を実際に接続するための設定です。 
 
なんだかたくさん要素が出てきますが、以下の設定の中でより詳細な情報は述べていきます。
  

# 設定
## 前提(Resource Group / Virtual Network / Subnet)
以下の環境はすでに構築済みとします。

- resource group
- virtual network
- subnet

当記事では、上記構築後に、上記環境を使用して構築を行うものとします。

```main.tf
provider "azurerm" {
    version = "~> 1.13.0"
}

resource "azurerm_resource_group" "rg" {
    name     = "${var.resource_group_name}"
    location = "${var.location}"
}

resource "azurerm_virtual_network" "vnet" {
    name                = "${var.vnet_name}"
    address_space       = ["${var.ip_range}"]
    location            = "${azurerm_resource_group.rg.location}"
    resource_group_name = "${azurerm_resource_group.rg.name}"
}

resource "azurerm_subnet" "subnet" {
    name                 = "${var.subnet_name}"
    resource_group_name  = "${azurerm_resource_group.rg.name}"
    virtual_network_name = "${azurerm_virtual_network.vnet.name}"
    address_prefix       = "${var.ip_subnet}"
}
```


## VitualNetworkGateway
VirtualNetwork と ExpressRoute 間で疎通を行うための Gateway になります。

```main.tf
data "azurerm_subscription" "subscription" {}

resource "azurerm_public_ip" "publicip" {
    name                         = "${var.vng_name}-publicip"
    location                     = "${var.location}"
    resource_group_name          = "${var.resource_group_name}"
    public_ip_address_allocation = "dynamic"
}

resource "azurerm_virtual_network_gateway" "vng" {
    name = "${var.vng_name}"
    location = "${var.location}"
    resource_group_name = "${var.resource_group_name}"

    type = "ExpressRoute"
    sku = "${var.vng_sku}"

    ip_configuration {
        name = "${var.vng_name}-config"
        public_ip_address_id = "${azurerm_public_ip.publicip.id}"
        subnet_id = "${data.azurerm_subscription.subscription.id}/resourceGroups/${var.resource_group_name}/providers/Microsoft.Network/virtualNetworks/${var.vnet_name}/subnets/${var.subnet_name}"
    }
}


```

SKU については補足します。

### Gateway Type と SKU
今回は専用線との接続用途で Virtual Network Gateway を用いますが、VNG の用途としては以下の２通りが存在します。

- VPN
- ExpressRoute を用いた専用線接続

VNG の視点で見ると、用途に応じて設定する SKU の内容も異なってきます。
ここでは ExpressRoute 接続のみに言及しますが、VPN 接続用途で構築する場合は以下の公式ドキュメントなどを参照してください。
<https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-about-vpngateways>

ExpressRoute 向けには、以下の３種の SKU が用意されています。

- SKU
  - Standard
  - High Performance
  - Ultra Performance

SKU ごとに、VNG が提供する性能（データ量や、接続数、パケット数など）が異なります。詳しくは以下ドキュメントを参照ください。

<https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-about-virtual-network-gateways#gwsku>

## ExpressRoute Circuit
専用線と、Azure 側のリソースを接続するための回路の設定を行います。

```main.tf
resource "azurerm_express_route_circuit" "exrcircuit" {
    name                     = "${var. exrcircuit_name}"
    resource_group_name      = "${var.resource_group_name}"
    location                 = "${var.location}"
    service_provider_name    = "${var.exrcircuit_provider}"
    peering_location         = "${var.exrcircuit_location}"
    bandwidth_in_mbps        = "${var.exrcircuit_bandwidth}"
    sku {
        tier   = "${var. exrcircuit_sku_tier}"
        family = "${var. exrcircuit_sku_family}"
    }
    allow_classic_operations = false
}

```

以下補足します。

### service_provider_name と peering_location
契約している専用線と Azure のリソースを、どの拠点で接続するか、を設定する必要があります。

専用線業者によって、どの拠点をサポートしているかはまちまちです。Azure への接続を行うことが前提な場合は、回線契約時にまず以下を参照し、期待する環境が提供されているかを確認する必要があります。

<https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-locations>

期待する環境への接続が行える場合、Terraform 経由では `service_provider_name` と `peering_location` にて回線業者と接続拠点の設定を行います。

```main.tf
    service_provider_name    = "SADA"
    peering_location         = "Tokyo"
```

service_provider_name に指定する値は回線業者により異なりますので、業者に問い合わせをする必要があります。
peering_location については、東京リージョンであれば `Tokyo` と指定します。こちらも不明な場合は Azure のサポートに問い合わせましょう。

### SKU
tier と familly を指定します。

tier は以下２種で、それぞれ提供される機能が異なります。

- Standard
- Premium

family は課金体系です。

- MeteredData
  - 従量課金
- UnlimitedData
  - 無制限

どちらを選ぶかは、予算やデータ量の見積もりなどに応じて選択することになると思います。

```main.tf
    sku {
        tier   = "Standard"
        family = "MeteredData"
    }
```

## Private Peering
ExpressRoute Circuit と Azure のネットワークの Peering 設定を行います。
こちらについては、今の所 Terraform での設定が難しそうです。

以下に設定のドキュメントがまとめられていますので、こちらの手順に応じて設定を行うことになります。

<https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-routing-portal-resource-manager#private>

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44364/1e4e8ef2-b713-8fea-bd48-6c5a49973e1e.png)

具体的には、以下の設定項目を埋める必要があります。

| 項目 | 値 | 凡例 |
|:-----|:-----|:-----|
| Peer ASN | Private AS番号 | 394749 |
| Primary / Secondary Subnet | Azure 側の接続 Subnet。 Primary / Secondary 構成にすることができます。こちらの subnet は Connection で関連付ける Virtual Network の IP レンジと異なるものを指定する必要があります。 | 172.16.0.0 / 30 |
| VLAN ID | VLAN ID | 154 |

## Connection(Virutal Network と Express Route の接続)
ルーティング設定が終わった後は、実際に接続したい Virtual Network との接続設定を行います。
こちらについても現時点では Terraform に対応していないように見えます。

<https://docs.microsoft.com/ja-jp/azure/expressroute/expressroute-howto-linkvnet-portal-resource-manager>

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44364/11ef1c9a-778b-970f-77e0-4eef6ed68eca.png)


主な設定項目は以下。

| 項目 | 値 | 凡例 |
|:-----|:-----|:-----|
| Connection Type | ExpressRoute 固定 | ExpressRoute |
| Virtual Network Gatewa | 関連付ける VNG を指定。上記で作成したものになると思います。 | |
| ExpressRoute Circuit | 関連付ける ExpressRoute Circuit を指定。上記で作成したものになると思います。 |  |

当該作業は手で行っていくとミスを起こしがちですので、Azure のコマンドラインツールなどを使って作成できるようにしておくのが望ましいと思います。もちろん、いずれ Terraform で対応してもらえるのが一番良い気がします。

```
$ az network vpn-connection create \
  --name ${CONNECTIONS} \
  --resource-group ${RESOURCE_GROUP} \
  --vnet-gateway1 ${VNET_GATEWAY} \
  --express-route-circuit2 ${EXPRESS_ROUTE} \
  --location ${LOCATION} 
```


# まとめ
上記のような形で、Terraform で Express Route 周りの構築を行う事ができます。
手で作業すると面倒なことも、多くの部分が自動化できているのではないかと思います。

これ以外にもできることがありますので、詳しく知りたい方はドキュメントなどを参照してください。


- <https://www.terraform.io/docs/providers/azurerm/r/express_route_circuit.html>
- <https://www.terraform.io/docs/providers/azurerm/r/virtual_network_gateway.html>