【Azure】Terraformの初期セットアップと仮想ネットワークの作成

# 1. はじめに
### 1-1 ご挨拶
初めまして、井村と申します。
インフラの自動化に興味がありまして、Terraformの勉強を始めました。
公式ドキュメント、先輩方の記事を見て、色んな書き方があるということを知りました。

本記事の目的は以下になります。
- 初期セットアップのエビデンス（基本的には1度だけなので、忘れないようにです。）
- 今の知識をとりあえずまとめたい

### 1-2 対象読者
- Azureに興味がある
- Terrafromに興味がある

### 1-3 実行環境
実行環境としてWindows 10の端末を使用します。端末にインストールするものは、Azure CLI、Terraform、Visual Studio Codeになります。
※事前にAzureアカウントは作成済みです。

### 1-4 成果物
Azure上に仮想ネットワークを作成します。

# 2. 準備
Terraftormの実行環境である端末の環境構築を行います。

### 2-1 Azure CLIのセットアップ
端末からAzureへ接続するため、Azure CLIをセットアップします。

2-1-1 [Windows での Azure CLI のインストール](https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli-windows?tabs=azure-cli)からインストーラをダウンロードします。

2-1-2 インストーラを起動、Azure CLIをインストールします。

2-1-3 コマンドプロントを開いて「az」を実行し、コマンド一覧が表示されることを確認します。

|![cmd-az.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/1c3721a2-4191-4235-2407-8533e32b8c5e.png)|
|:--|

### 2-2 Terraformのセットアップ
端末からTerraformを実行するため、Terraformをセットアップします。

2-2-1 [Download Terraform](https://www.terraform.io/downloads)から実行ファイルをダウンロードします。

2-2-2 任意のフォルダに「terraform.exe」を格納します（今回は"C:\terraform"直下に格納）。

|![terraform-exe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/bdcf0904-80a7-187e-976c-ee12f8bb3d42.png)|
|:--|

2-2-3 環境変数に上記パスを追加（今回は"C:\terraform"）。
※環境変数の変更は、「Win」+「R」キー同時押し → 「ファイル名を指定して実行」→ "sysdm.cpl"を実行し、システムプロパティからいけます。

2-2-4 コマンドプロンプトを開いて「terraform -v」を実行し、バージョンが表示されることを確認します。

|![terraform-v.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/c8cf531c-e389-dcb4-170f-89162149256a.png)|
|:--|

### 2-3 Visual Studio Codeのセットアップ
Terraformの記述ミス防止のため、Visual Studio Codeをセットアップします。

2-3-1 [Download Visual Studio Code](https://code.visualstudio.com/download)から実行ファイルをダウンロードします。

2-3-2 インストーラを起動、インストールします。

2-3-3 拡張機能から「Azure Terraform」をインストールします([概要: Azure Terraform Visual Studio Code 拡張機能をインストールする](https://docs.microsoft.com/ja-jp/azure/developer/terraform/configure-vs-code-extension-for-terraform?tabs=azure-cli))。

### 2-4 サービスプリンシパルの作成
個人ユーザで作業は出来ますが、Terraform専用のアカウントとしてサービスプリンシパルを作成します。
※サービスプリンシパルは認証時の資格情報および権限の割当てを含んだアカウントです。。と思っています。。

2-4-1 コマンドプロンプトを開いて「az login」を実行し、個人ユーザでログインします。ログインが成功するとログイン情報が出力されます。"id": "AAAAAAAA-AAA-AAAA-AAAA-AAAAAAAA"をメモします。

```
# 以下が出力値の例です。
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "********-****-****-****-*********",
    "id": "AAAAAAAA-AAA-AAAA-AAAA-AAAAAAAA",
    "isDefault": true,
    "managedByTenants": [],
    "name": "*******",
    "state": "Enabled",
    "tenantId": "****************************",
    "user": {
      "name": "**********@*****",
      "type": "user"
    }
  }
]
```
2-4-2 以下コマンドでサービスプリンシパルを作成します。先ほどメモしたidをこちらで使用します。そして今回も出力値をメモします。
--role Contributor は共同作成者の権限になります。
--scopes "～" はサービスプリンシパルの権限範囲です。今回はサブスクリプションです。
--name "app-terra" はサービスプリンシパルの名前です（任意です）。

```
# 以下が実行コマンドの例です。
az ad sp create-for-rbac --role Contributor --scopes "/subscriptions/AAAAAAAA-AAA-AAAA-AAAA-AAAAAAAA" --name "app-terra"

# 以下が出力値の例です。
{
  "appId": "BBBBBB-BBBB-BBB-BBB-BBBBBBBB",
  "displayName": "app-terra",
  "password": "CCCCCCCCCCCCCCCCCCCCCCCCCCC",
  "tenant": "DDDDDDD-DDD-DDDD-DDDD-DDDDDDDD"
}
```
2-4-3 確認として、サービスプリンシパルを用いてAzureへログインします。先ほどメモしたidをこちらで使用します。
-u ユーザアカウントです。
-p パスワードです。
-t テナントです。

```
# 以下が実行コマンドの例です。
az login --service-principal -u BBBBBB-BBBB-BBB-BBB-BBBBBBBB -p CCCCCCCCCCCCCCCCCCCCCCCCCCC -t DDDDDDD-DDD-DDDD-DDDD-DDDDDDDD
```
 
# 3. tfファイルの作成
tfファイルとはTerraformで使用されるファイルになります。ここのファイル構成がとても悩みます。百人百様ですね。
今回は自分が理解でき、シンプルな構成を心掛けました。Azureサービス単位でファイルを分けます。
また、今回のtfファイルはデスクトップ上に「Terraform」というフォルダを作成、格納しています。

### 3-1 「probider.tf」の作成
「probider.tf」はTerraformのバージョン、TerraformでAzureを用いること、サービスプリンシパルの認証情報を記載します。
上記で色々とメモした情報を張り付けます（[Terraform プロバイダー ブロックでサービス プリンシパルの資格情報を指定する](https://docs.microsoft.com/ja-jp/azure/developer/terraform/get-started-cloud-shell-bash?tabs=bash)）。

```
# probider.tf
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.0.0"
    }
  }
}

provider "azurerm" {
  features {}
  subscription_id = "AAAAAAAA-AAA-AAAA-AAAA-AAAAAAAA"
  tenant_id       = "DDDDDDD-DDD-DDDD-DDDD-DDDDDDDD"
  client_id       = "BBBBBB-BBBB-BBB-BBB-BBBBBBBB"
  client_secret   = "CCCCCCCCCCCCCCCCCCCCCCCCCCC"
}
```
### 3-2 「locals.tf」の作成
「locals.tf」は、変数情報を記載します。変数を用いることでTerraformの管理が楽になります。

```
# locals.tf
locals {
  # ロケーション
  location = "japaneast"

  # リソースグループ名
  rg_name = "rg-terra"

  #　仮想ネットワーク名
  vnet_name = "vnet-terra"

  # パブリックサブネット名
  snet_name_pub = "snet-terra-pub"

  # プライベートサブネット名
  snet_name_pri = "snet-terra-pri"
}

```

### 3-3 「rg.tf」の作成
「rg.tf」は、リソースグループ作成用のファイルになります。
参考としてここでの"name"は「locals.tf」の"rg_name"を取得しています(locationも同様)。

```
# rg.tf
resource "azurerm_resource_group" "rg" {
  name     = local.rg_name
  location = local.location
}

```
### 3-4 「network.tf」の作成
「network.tf」は、仮想ネットワークおよびサブネット作成用のファイルになります。
参考としてここでの"name"は「locals.tf」から取得しています。
では、リソースグループ名はどうでしょうか？正解は「locals.tf」ではなく「rg.tf」から取得します。
Azureは仮想ネットワークを作成する前に、リソースグループを作成する必要があります。そこで「locals.tf」から取得しようとすると、優位性が無くなってしまいます。同様の考えでサブネットでの仮想ネットワーク名も「locals.tf」から取得しません。

```
# network.tf
resource "azurerm_virtual_network" "vnet" {
  name                = local.vnet_name
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  address_space       = ["10.0.0.0/16"]
}

resource "azurerm_subnet" "public" {
  name                 = local.snet_name_pub
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

resource "azurerm_subnet" "private" {
  name                 = local.snet_name_pri
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.2.0/24"]
}
```
# 4. Terraformの実行
それでは以下コマンドを実行しましょう。

```
# Terraformフォルダへ移動
cd C:\Users\"ユーザ名"\Desktop\terraform

# tfファイルの存在確認
dir /b

# terraformの初期化
terraform init

# tfファイルの記述および実行後のAzureサービス成果物の確認
terraform plan

# Terraformの実行
terraform apply

Enter a value:yes
```
Azureポータルで是非確認してみてください！

# 5. おわりに
本記事を最後まで読んで頂きましてありがとうございます。
Terraformはゴールデンウイークの心身リフレッシュの空き時間で触ってみました。そしてやるべき事、理解すべき事が山積みであることがわかりました。権限の扱い、その他Azureサービスの記述、本番、テスト環境を考えての記載が直近の課題になります。

# 6. 参考記事

-  [Windows での Azure CLI のインストール](https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli-windows?tabs=azure-cli)
- [Download Terraform](https://www.terraform.io/downloads)
- [Download Visual Studio Code](https://code.visualstudio.com/download)
- [概要: Azure Terraform Visual Studio Code 拡張機能をインストールする](https://docs.microsoft.com/ja-jp/azure/developer/terraform/configure-vs-code-extension-for-terraform?tabs=azure-cli)
- [az ad sp](https://docs.microsoft.com/ja-jp/cli/azure/ad/sp?view=azure-cli-latest)
- [Terraform プロバイダー ブロックでサービス プリンシパルの資格情報を指定する](https://docs.microsoft.com/ja-jp/azure/developer/terraform/get-started-cloud-shell-bash?tabs=bash)

- [Terraform公式ドキュメント Azure Provider](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
- [Terraform公式ドキュメント リソースグループ](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group)
- [Terraform公式ドキュメント 仮想ネットワーク](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network)
- [Terraform公式ドキュメント サブネット](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet)
- [Terraform公式ドキュメント 変数](https://www.terraform.io/language/values/locals)