マルチクラウド下でのTerraformのディレクトリを改めて考える

# 概要
TerraformはAWSやGCPなどのクラウドを管理するための構成管理ツールですが、
自分でtfファイルやディレクトリ構成の粒度を決めれます。
Terraformでマルチクラウドを扱う時にどのような粒度でディレクトリを分ければいいのかを考えていきます。

## 前提条件
Terraformを使う場面は様々ですが、今回はGCPとAWS2つのクラウドをTerraformで管理することを前提とします。
またAWSはステージングアカウントと本番アカウント2つある前提で話します。

※様々な流派がTerraformにあるのですが、今回はシンプルにしたいのでworkplaceやmoduleは使わないです

以下が今回例として扱うGCPとAWSの状態です。

```yaml
AWSアカウント:
- prodアカウント     ・・・ 本番環境用
- stgアカウント      ・・・ ステージング環境用/開発環境用

GCPアカウント:
- anlytics folder  ・・・ 分析環境用のfolder
  |- prod project  ・・・ 本番分析環境用のプロジェクト
  |- stg project   ・・・ ステージング分析環境用のプロジェクト
  |_ dev project   ・・・ 開発分析環境用のプロジェクト
- corporate folder ・・・ 社内ツール用のfolder
  |- prod project  ・・・ 本番社内ツール環境用のプロジェクト
  |- stg project   ・・・ ステージング社内ツール環境用のプロジェクト
  |_ dev project   ・・・ 開発社内ツール環境用のプロジェクト
```

## 各クラウドの特徴

AWSとGCPの特徴は色々あるのですが、Terraformで扱う上で一番の違うはnamespaceの違いだと思います。

AWS: 1アカウントでnamespaceを分けて複数の環境を管理しづらい
GCP: 1アカウントでFolder/Projectごとに環境を分けて管理できる

AWSは1アカウントで役割ごとにVPCをなどのAWSサービスを分けても強権のIAMを持っていれば、
アカウント内にあるどのAWSサービスでも触ることができます。
ですが、GCPはこのProjectでは強権を持っているが、別のProjectでは強権を持たせない等の振り分けができます。

# Terraformのディレクトリ案

上記を踏まえた上で以下の案があります。

### 案1: 環境ごとで分ける

- メリット
    - 階層が深くないのでどのような環境があるかがパッと見でわかる
- デメリット
    - どのクラウドでどのアカウントを扱っているのかがわからない

```yaml
main/common          ・・・ 環境共通用tfファイル郡
    /prod            ・・・ 本番環境用tfファイル郡
    /stg             ・・・ ステージング環境用tfファイル郡
    /dev             ・・・ 開発環境用tfファイル郡
```

### 案2: サービスごとに分ける

- メリット
    - GCPとAWSが密接に関わっているアプリケーションがあると表現がしやすい
- デメリット
    - どのクラウドでどのアカウントをあつかっているかが分かりづらい

```yaml
main/common          ・・・ サービス共通用tfファイル郡
    /frontend        ・・・ フロントエンドサービス用のディレクトリ
      /prod          ・・・ 本番フロントエンド環境用tfファイル郡
      /stg           ・・・ ステージングフロントエンド環境用tfファイル郡
      /dev           ・・・ 開発フロントエンド環境用tfファイル郡
    /backend         ・・・ バックエンドサービス用のディレクトリ
      /prod          ・・・ 本番バックエンド環境用tfファイル郡
      /stg           ・・・ ステージングバックエンド環境用tfファイル郡
      /dev           ・・・ 開発バックエンド環境用tfファイル郡
    /corporate       ・・・ 社内ツール環境用のディレクトリ
      /prod          ・・・ 本番社内ツール環境用tfファイル郡
      /stg           ・・・ ステージング社内ツール環境用tfファイル郡
      /dev           ・・・ 開発社内ツール環境用tfファイル郡
    /analytics       ・・・ 分析サービス用のディレクトリ
      /prod          ・・・ 本番分析環境用tfファイル郡
      /stg           ・・・ ステージング分析環境用tfファイル郡
      /dev           ・・・ 開発分析環境用tfファイル郡
```

### 案3: クラウドごとアカウント(folder)ごと環境ごとで分ける

- メリット
    - どのクラウドでどのアカウント(folder)があり、どんな環境があるかわかる
- デメリット
    - ディレクトリ階層が深いので、ディレクトリ構造が分かってないと分かり辛い

```yaml
main/aws           ・・・ aws用のディレクトリ
      /prod        ・・・ 本番AWSアカウント用のディレクトリ
        /common    ・・・ 本番AWSアカウントで共通に使うもののtfファイル群
        /prod      ・・・ 本番環境用tfファイル郡
      /stg         ・・・ ステージングAWSアカウント用のディレクトリ             
        /common    ・・・ ステージングAWSアカウントで共通に使うもののtfファイル群
        /stg       ・・・ ステージング環境用tfファイル郡
        /dev       ・・・ 開発環境用tfファイル郡
    /gcp           ・・・ gcp用のディレクトリ
      /anlytics    ・・・ gcp分析環境folder用のディレクトリ
        /prod      ・・・ 本番分析環境用tfファイル郡
        /stg       ・・・ ステージング分析環境用tfファイル郡
        /dev       ・・・ 開発分析環境用tfファイル郡
      /corporate   ・・・ gcp社内ツール環境用のディレクトリ
        /prod      ・・・ 本番社内ツール環境用tfファイル郡
        /stg       ・・・ ステージング社内ツール環境用tfファイル郡
        /dev       ・・・ 開発社内ツール環境用tfファイル郡
```

# 結論

今回の例であれば、ディレクトリでクラウド、アカウントを表現している `案3` か、サービスごとに分ける `案2`が運用しやすいと思います。

もしAWSとGCPが疎結合であれば、 `案3` を採用するとどのクラウドのどのアカウントにどういうリソースがあるのかがパッとわかるので事故を防止できて運用しやすいと思いますし、

AWSとGCPが密結合であれば、 `案2`を採用し、サービスという単位で管理すると各クラウドの環境ごとにTerraformを適用し、それぞれで整合性をとる必要がないので運用がしやすいと思います。

`案1`の場合は、AWSだけでTerraformを使って管理する場合、もしくはマルチクラウド 間、マルチサービス間(上記の例だとAWSとGCP、フロントエンドサービスとバックエンドサービス)が密結合である場合に採用することをお勧めします。