[2020年度版]GCPをTerraform管理するベストプラクティス

## はじめに
この記事は2020年のterraformのローカル開発環境、
そしてGoogle Cloud Platform(GCP)をTerraform管理下にするためのオレオレベストプラクティスを紹介する記事です。

# Terraformとは
詳しい記事がいっぱいあるので説明は割愛しますが、クラウド環境をstateファイルで管理して、
クラウドコンポーネントの削除・作成を楽チンにするためのツールです。
~~本当に楽チンなのかはわかりません。~~

# Terraform開発環境
ここではVScode限定して**俺の**terraform開発環境を紹介します。
terraformのインストールは割愛します。

- やること
   - tflintを入れる
   - ファイル保存時に自動でterraform fmtをかける

### ファイル保存時に自動でterraform fmtをかける
まずはVScodeにTerraformの拡張機能をいれます。
[Terraform](https://marketplace.visualstudio.com/items?itemName=hashicorp.terraform)こちらを有効にします
※codeコマンドが使えない場合は、VScodeのGUIからインストールするか、[こちらの記事](https://qiita.com/naru0504/items/c2ed8869ffbf7682cf5c)でcodeコマンドを使えるようにしてください

```
code --install-extension hashicorp.terraform
```

そしてVScodeの `Command Palette`から `terraform: Enable/Disable Language Server` を実行すれば、v0.12の記法に対応されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575547/2e0b9c63-ee40-2976-7be8-fd8ee28b7345.png)

vscodeの設定で`editor.formatOnSave`にチェックを入れておくと、
保存時に自動で `terraform fmt` を実行してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575547/ce11d5f5-882e-ed93-ddf6-2061a9c9a6ab.png)


### TFlint
Macの方限定のインストール方法ですが、brewでTerraform用のlinterを入れます。
ログインシェルの方でパス通ってれば自動でlintをしてくれて、エラーの箇所を赤字にしてくれるので便利です。

```
brew install tflint
```

以上で開発環境の準備が整いました。

# Google Cloud Platform(GCP)とは
Googleが作っているクラウドです。以上。
他にネット上に詳しい記事があるのでここでは割愛します。
ただ、AWSを使っている人に説明するとAWSとはTerraformでの管理の仕方が異なります。
それを念頭に置いてこの記事を読んでいただければと思います。

### GCPのTerraform管理方法
実はGCPが以下のURLでTerraformでGCPをどう管理するかというドキュメントを用意してくれてます。
ここでは以下の資料をもとに簡単にGCPにおけるTerraform管理を説明します。
引用元: https://cloud.google.com/community/tutorials/managing-gcp-projects-with-terraform

GCPの権限まわりの話は後述しますが、
GCPでTerraform管理する場合は、まずTerraform管理プロジェクトをOrganization直下に作ります。
この図で言うところの`Admin Project`です。このプロジェクトでTerraformのサービスアカウントを作り、作ったサービスアカウントを別プロジェクトでも使えるように権限を与えて、そのプロジェクトのリソースを管理させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575547/05cb0463-c04a-6104-81ab-b3a07e9faa71.png)

### GCPの権限管理
GCPは3つのリソース階層があります。

- Organization: GCPのアカウント管理する
- Folders: プロジェクトをグループ化し、プロジェクトを分離するときに使う
- Projects: GCPのサービスを使う単位 例えば本番環境を作りたいと思ったらprod-appというプロジェクトを作り、そこにインスタンスなどを立てる

以下の図の通り、この３つのリソースは階層構造になっており、上位リソースに所属するユーザの権限を下位リソースに継承します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575547/1762d1ef-2b00-c3c1-d58d-da340f5d672a.png)

ちなみに継承を使わずとも、あるプロジェクトのユーザに別プロジェクトの権限を付与することもできます。
引用元: https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy

# オレオレTerraform構成
上記のGCPでのTerraform管理の仕方と権限まわりを考慮にいれて私はこのようなディレクトリ構成でTerraformを管理します。

```
gcp/
├── hogehoge
│  ├──production-hogehoge
│  │  ├── main.tf
│  │  └── variable.tf
│  └──staging-hogehoge
│     ├── main.tf
│     └── variable.tf
├── management-project
│  ├── service_account.tf
│  ├── main.tf
│  └── variable.tf
├── folder.tf
├── main.tf
└── organization_iam.tf
```

ディレクトリ階層でリソース階層のfoldersを表現しています。
例えば`hogehoge`フォルダーの下に`production-hogehoge`と`staging-hogehoge`の２つのプロジェクトが存在する形です。
フォルダを分ける単位ですが、サービスごとに分けてた方がいいと考えます。例えば、ある会社で社内サービスでQiitaのようなサービスがあるとすると、`demo-Qiita`フォルダーの下に本番環境の`prod-demo-Qiita`プロジェクトとステージング環境の`stag-demo-Qiita`があるイメージです。

gcpの直下においてあるtfファイルはOrganizationのリソース管理用です。
ここでいうと、 `organization_iam.tf` でOrganizationに存在するIAMユーザを管理します。
`folder.tf` はフォルダーを管理しています。

`management-project` はterraformのサービスカウントが存在する`Admin Project`になります。`management-project`にterraformのstateファイルも置きます。

# その他のTips
GCPに特化しないTerraform全般のベストプラクティスはいかに載っています。
リソースの命名規則などは非常に参考になりました。
参考資料: https://www.terraform-best-practices.com/

# 終わりに
私自身Terraformは2018年から触り始めていたのですが、
lintやフォーマットの自動修正を入れる設定をしていなかった情弱であり、
最近GCPを触る機会があり、どうやってTerraformを管理すればいいか悩んで、この記事でまとめました。
TerraformでGCPを管理する場合はどうすればいいか悩んでいる人の手助けにこの記事がなれば幸いです。
またコメントもお待ちしております。