【2019年12月版】GCPでは沼だった Terraform に Azure でリベンジ ?!

# Azure の Terraform チュートリアルをやってみる。

はい、毎度~~沼ってることで~~おなじみの Terraform ですが、Azure の公式チュートリアルを発見してしまったのでこれはもう**やるっきゃない☆**

- [Azure 上の Terraform のドキュメント](https://docs.microsoft.com/ja-jp/azure/terraform/)

以下のクイックスタートに挑戦してみました。

- [Install and configure Terraform to provision Azure resources](https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fja-jp%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fja-jp%2Fazure%2Fbread%2Ftoc.json)

## 1. Terraform のインストールについて

実は上記のクリックスタートページにあるように、Cloud Shell では Terraform が**インストール済み** です。
とりあえず使ってみるだけとか小規模なインフラなら Cloud Shell 上で `git clone` してその場で terraform init と apply でもありかと思います。(いや、ちゃんとバックエンドの設定が必要になるからこの方がレベル高いかも。)

自分の環境では 0.11から0.12に破壊的な更新があったことを踏まえて **tfenv** 使ってます。というか、これから新規に Terraformを始める方は **tfenvがマスト** だと思います。

というわけで tfenv は[こちらのgitリポジトリからインストール](https://github.com/tfutils/tfenv)してください。
使い方は `nvm` とか**そっち系のツール**とだいたい同じで、`list-remote` でリリースを確認して `install` で追加して `list` でインストール済みの確認して `use`で切り替える、という感じです。

今回は安易に "最新版" を入れてしまいます。

```shell
$ tfenv install latest
...

$ tfenv list
* 0.12.18 (set by /home/xxxxxx/.tfenv/version)
  0.12.2
  0.11.13
```

`install` すると `use` してくれるようです。以後、`0.12.18` で作業を進めたいと思います。

## 2. Azure のアカウント設定

チュートリアルに従って、Azure のアカウントを Terraform で参照できるようにしておきましょう。`az login` はしておいてください。

まずサブスクリプションを取得します。

```sehll
$ az account list --query "[].{name:name, subscriptionId:id, tenantId:tenantId}"
...
```
サブスクリプションのリストが出てくると思います。
この`subscriptionId`を環境変数に入れて、`az`コマンドで参照するサブスクリプションを設定します。

```
$ export SUBSCRIPTION_ID=xxxxxx-xxxxxx-xxxx-xxxx-xxxxxxxxxxx
$ az account set --subscription="${SUBSCRIPTION_ID}"
```
続いてTerrform用のロールを作成します。

```
$ az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/${SUBSCRIPTION_ID}"
...

{
  "appId": "xxxxxxxx-xxxx-xxxx-xxxxxxxxxxx",
  "displayName": "xxxxxxxxxxxxxxxxxxxxxxx",
  "name": "http://xxxxxxxxxxxxxxxxxxxxxxx",
  "password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "tenant": "xxxxxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```
これらの値を環境変数に入れる `setenv.sh` を作成します。

```sh:setenv.sh
#!/bin/sh
echo "Setting environment variables for Terraform"
export ARM_SUBSCRIPTION_ID=xxxxxxx-xxxx-xxxx-xxxxxxxxxxxx
export ARM_CLIENT_ID=xxxxxxx-xxxx-xxxx-xxxxxxxxxxxx
export ARM_CLIENT_SECRET=xxxxxxx-xxxx-xxxx-xxxxxxxxxxxx
export ARM_TENANT_ID=xxxxxxx-xxxx-xxxx-xxxxxxxxxxxx

# Not needed for public, required for usgovernment, german, china
export ARM_ENVIRONMENT=public
```
もう、この`setenv.sh`は**どう管理していいのかわからない**です。。。(間違いなく、核燃料棒みたいなもんです。。。)

で、準備は完了です！

## 3. リソースの準備

今回は試しに "リソースグループ" だけを作ってみましょう。

```hcl:test.tf
provider "azurerm" {
}
resource "azurerm_resource_group" "rg" {
        name = "testResourceGroup"
        location = "westus"
}
```

で、ファイルを保存したら Terraform のプロジェクト開始します！

```shell
$ terraform init
...

```
ここでバックエンドのセットアップやプラグインのインストールが行われます。

## 4. 実行！

クイックスタートではいきなり`apply`しちゃってますがこれは**御法度**です。
まずは実行計画の確認をしましょう。

```shell
$ terraform plan --out plan.out
...
```
で、実行計画のメッセージが表示されて `plan.out` に実際に適応されるクリプト？が生成されます。

で、内容を確認して問題がなければ、この `plan.out` を `apply`します。

```shell
$ terraform apply plan.out
Acquiring state lock. This may take a few moments...
azurerm_resource_group.rg: Creating...
azurerm_resource_group.rg: Creation complete after 3s [id=/subscriptions/xxxxx-xxxx-xxxx-xxxxxxxx/resourceGroups/testResourceGroup]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Releasing state lock. This may take a few moments...
```

はいっ！無事に `apply` できた模様です。
Azure Portalでも確認してみましょう。

![testResourceGroup - Microsoft Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/c2d24a40-f97d-28fd-cbd1-ad0f0cb35f65.png)

大丈夫のようです。ちゃんと作成されていますね～！

## 5. 撤収！

Terraformの動作確認が出来ましたので TestResourceGroup を撤収いたします！

```
$ terraform destroy
...
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
...
azurerm_resource_group.rg: Destruction complete after 1m5s

Destroy complete! Resources: 1 destroyed.
```
ちゃんと確認してきますので `yes` と答えましょう。
`test.tf`で定義したリソースをすべて削除してくれます。

## 6. tfstate を Azure の Storage でやる場合

今回は tfstate をローカルで保存してますがこれは問題ありですので、リモートのどこかを利用したいですが・・・せっかくなので Azure のストレージを使用しましょう。(というか当然の流れですよね。。。)

手順は以下のチュートリアルにある通りです。(雑)

- [Tutorial: Store Terraform state in Azure Storage](https://docs.microsoft.com/ja-jp/azure/terraform/terraform-backend)

ストレージの作成は Azure Portal からでもできるので、そっちのスクショを貼ろうとも思ったのですが、シェルスクリプトがそのまんま記載されているのでそれで十分でしょう・・・というかそれが早い。。

---
駆け足でしたがAzureの公式チュートリアルを触ってみて、Terraform + Azure、とりあえず大丈夫そうなのが確認できました。
この先は各サービスごとの設定との戦いになるので**沼、確定**なのですが、頑張っていきたいと思います！

今回は以上です。