【Terraform】GCP事始め

# 概要
TerraformでGCPリソースを扱い始めるためのチュートリアルのような内容を記載します。
ハンズオンライクに、terraformコマンドでVPCネットワークを生成できることを本記事でのゴールとします。

AWS編は[こちら](https://qiita.com/mintak21/items/4a11e084229a1c5915fb)を参照ください。

# 前提
- MacOSである
- Homebrewを導入している
- GCPアカウントを保持している・プロジェクトを作成している
- terraformのバージョンは`0.13`以降のバージョンを利用する
- 2021/11時点での内容である（今後のアップデートによって手順やコードに変更が入る可能性有）

# 手順
## 1. セットアップ
terraformを利用するためのサービスアカウントの発行、tfstateを置くStorage Bucketの作成は手動で行う必要があります。

### 1.1. サービスアカウントの作成

IAMと管理 -> サービスアカウント -> サービスアカウントの作成 よりterraform実行用のサービスアカウントを作成します。
わかりやすく、`terraform`という文字列をいれておくといいでしょう。

![IAM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552343/23c56b62-b09c-b86e-db21-34ad14be81c2.png)

### 1.2. ロール付与

続いてこのサービスアカウントに対してオーナーロールを付与します。
※注：オーナーロールはプロジェクトのすべてのリソース管理を行うことができる強力な権限を有しています。本来は必要最低限の権限を有したロールを付与すべきですが、その手間を省く意味と個人用プロジェクトであることを鑑みてオーナーロールを利用します。

IAMと管理 -> IAM -> 追加　より 新しいメンバーに先ほど作成したサービスアカウントを入力、ロールに「オーナー」を選択して保存してください。

![IAM2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552343/3c5f2dfa-3d0e-7589-c415-58f577cab581.png)

### 1.3. キーの発行

作成したサービスアカウントを利用するためにキーを発行します。
IAMと管理 -> サービスアカウント より先ほど作成したサービスアカウントを選択し、編集ボタンを押下します。
下段のあたりにキー -> 鍵を追加 というボタンがあるのでこちらを押下します。鍵の種類は「JSON」を選択し作成しましょう。
すると、自動的にjsonファイルがダウンロードされるかと思います。
このファイルには認証情報が記載されているため、管理は慎重に行うようにしてください。私は`$HOME/.gcp/account.json`へ移動させました。

### 1.4. state管理バケット作成

Storage -> バケットの作成　にて作成します。次の２箇所以外はデフォルトのままで問題ありません。

- バケットの名称：グローバルで一意な必要があるので、キャプチャの例のようにprefixを利用するとよいです。
- ロケーションタイプ：`Multi-Region`では必要過多なので`Region`にしましょう。リージョンはどこでも構いませんが、もっとも近い`asia-northeast1`かなにかと安い`us-central1`を選ぶと良いでしょう。

![スクリーンショット 2020-10-12 13.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552343/fd718f3c-6dfb-aaea-596b-db9397ab76b7.png)


## 2. ローカル実行環境設定
### 2.1. terraformのインストール

[こちら](https://qiita.com/mintak21/items/4a11e084229a1c5915fb#terraform%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)を参照ください。

### 2.2. Cloud SDK ツールのインストール

なくてもterraformは扱えますが、なにかと利用機会も多いのでインストールしておきます。
コンポーネントも最新化しておきます。

```bash:Terminal
brew install google-cloud-sdk --cask
gcloud components update
```

認証はユーザーアカウントまたはサービスアカウントのどちらかを選択可能です。
詳しくは[ツールの承認ページ](https://cloud.google.com/sdk/docs/authorizing?hl=ja)を参照ください。
ユーザーアカウントで認証する場合は、以下のコマンドを実行したのち、Web画面で使用するユーザーアカウントを選択し、ログインします。

```bash:Terminal
gcloud auth login
```

### 2.3. 環境変数設定

環境変数`GOOGLE_APPLICATION_CREDENTIALS`に1.3でダウンロードしたファイルを設定することで、terraformコマンド実行時はこのサービスアカウントでコマンド（API）が実行されるようになります。

```bash:.bash_profile
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.gcp/accounts.json"
```

## 3. 実行ファイルの作成

GCP上にVPCネットワークを作成するためのコードを記述していきます。

```text:ディレクトリ構成
directory
|- backend.tf    tfstateの配置場所設定
|- main.tf       実行対象
|- providers.tf  プロバイダ設定
|- versions.tf　　利用バージョンの記述
```

- 各ファイル

```terraform:backend.tf
terraform {
  backend gcs {
    bucket = "my-tfstate-1afd45" # 1.4で作成したバケットの名称を設定
    prefix = "tutorial"
  }
}
```

```terraform:providers.tf
provider "google" {
  project = "YOUR_PROJECT_ID" # 利用するプロジェクトのIDを設定
  region  = "us-central1"
}

# 必要に応じて記載(今回は不要)
# provider "google-beta" {
#  project = "YOUR_PROJECT_ID" # 利用するプロジェクトのIDを設定
#   region  = "us-central1"
# }
```

```terraform:versions.tf
# 記載時点での最新版
terraform {
  required_version = "1.1.2"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "4.5.0"
    }
    # 必要に応じて記載(今回は不要)
    # google-beta = {
    #   source  = "hashicorp/google-beta"
    #   version = "4.5.0"
    # }
  }
}
```

```terraform:main.tf
resource "google_compute_network" "tutorial" {
  name                    = "tutorial-network"
  description             = "VPC Network For Tutorial"
  routing_mode            = "REGIONAL"
  auto_create_subnetworks = true
}
```

## 4. リソース作成/削除

# 4.1. init

BackendとプロバイダのInitializeを行います。

```bash:Terminal
$ terraform init
```

# 4.2. plan

いきなり作成コマンドを実行するのはやはり気が引けるので、実行したときの結果のだいたいの予測ができるコマンドがあります。それがplanコマンドです。まずはこれで変更内容を把握しましょう。
エラーとなる場合は、エラー内容が表示されます。
下記の例のように、「applyして、どうぞ」となっていれば実行できる状態です。
※ただし、planが成功したといってapplyが成功するとは限りません。

```bash:Terminal
$ terraform plan

------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_compute_network.tutorial will be created
  + resource "google_compute_network" "tutorial" {
      + auto_create_subnetworks         = true
      + delete_default_routes_on_create = false
      + description                     = "VPC Network For Tutorial"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + name                            = "tutorial-network"
      + project                         = (known after apply)
      + routing_mode                    = "REGIONAL"
      + self_link                       = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
```

## 4.3. apply

4.2. planが成功したら、いよいよapplyコマンドでリソースを作成してみましょう。
planと同様の変更内容がコンソールに表示された後、Do you want to perform these actions?と尋ねられるため、問題なければ「yes」と入力することでリソース作成が開始されます。

```bash:Terminal
$ 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

google_compute_network.tutorial: Creating...
google_compute_network.tutorial: Still creating... [10s elapsed]
google_compute_network.tutorial: Still creating... [20s elapsed]
google_compute_network.tutorial: Still creating... [30s elapsed]
google_compute_network.tutorial: Creation complete after 38s [id=projects/mintak/global/networks/tutorial-network]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

GCPコンソールで見てみると以下のように作成したVPCネットワークが追加されていますね。

![スクリーンショット 2020-10-12 13.53.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552343/07838cb9-f17c-3ddf-d3fc-419dfecf5c28.png)


※APIが有効になっていないというエラーメッセージが出た場合は、有効にするためのURLもメッセージに含まれているはずなので、そちらで有効化したのち、再実行してみてください。

## 4.4. destroy

チュートリアル的にリソース作成が確認できれば、このVPCネットワークは必要ないものなので、削除しておきます。
基本的に必要ないリソースはクリーンアップをしておく癖をつけておくと良いと思います。

```bash:Terminal
$ terraform destroy
```


# References
- [Terraform Provider:GCP](https://registry.terraform.io/providers/hashicorp/google/latest)
- [Cloud SDKツールの承認](https://cloud.google.com/sdk/docs/authorizing?hl=ja)