AWSにてチーム開発をする際のTerraformの設定

# はじめに
AWSにてチーム開発をする際の設定です。
CloudFormationでは意識しないような設定がTerraformでは必要です。
チーム開発のために下記のリソースを別途構築する必要があります。

- S3をBackendとし、terraform.tfstateを管理する。
- DynamoDBにてlockをし、開発者の ```terraform apply``` の実行の排他制御をする。

Terraformのバージョンは ```v1.1.6```とする。

# 実行環境の準備
[AWSでTerraformを動かすための設定](https://qiita.com/miyabiz/items/b647c93aaf3c05c61525)を参考にしてください。

※ CloudFormationと同じです。

# S3とDynamoDBを構築する
1.  [terraform-aws-tfstate-backend](https://github.com/cloudposse/terraform-aws-tfstate-backend)を利用する。
    ```
    git clone https://github.com/cloudposse/terraform-aws-tfstate-backend
    ```

1.  S3のバケット名をカスタマイズする。
 
    ```tf:variables.tf
    variable "s3_bucket_name" {
      type        = string
      default     = "akane-dev-terraform-state"
      description = "S3 bucket name. If not provided, the name will be generated by the label module in the format namespace-stage-name"
    }
    ```

1.  DynamoDBのテーブル名をカスタマイズする。

    ```tf:variables.tf
    variable "dynamodb_table_name" {
      type        = string
      default     = "akane-dev-terraform-state-lock"
      description = "Override the name of the DynamoDB table which defaults to using module.dynamodb_table_label.id`"
    }
    ```

1.  terraformにてS3とDynamoDBを構築する。
    ```
    terraform init

    terraform apply -auto-approve
    ```

# AWS リソース構築内容

  - VPC
  - パブリックサブネット
  - プライベートサブネット
  - インターネットゲートウェイ
  - ナットゲートウェイ
  - ルートテーブル


VPC構築のために下記のファイルを別途作成する。

```text:ディレクトリ構成
akane (システム)
└── terraform
    ├── common
    │   ├── variables.tf (パラメータ定義)
    │   └── vpc.tf (VPC)
    └── dev
        └── main
            ├── backend.tf (S3とDynamoDBの利用設定)
            ├── main.tf (パラメータ設定)
            └── providers.tf (AWSの設定)
```

# AWS リソース構築手順
1. 下記を実行してリソースを作成

    ```
    cd ~/akane/terraform/dev/main

    terraform init

    terraform apply -auto-approve
    ```

1. 下記を実行してリソースを削除

    ```
    cd ~/akane/terraform/dev/main

    terraform destroy -auto-approve
    ```

# 構築テンプレート
**1. パラメータ設定**
 
```tf:terraform/common/variables.tf
variable "aws_default_region" {
  type    = string
  default = "ap-northeast-1"
}

variable "aws_account_id" {
  type = string
}

variable "env" {
  type = string
}

variable "akane_cidr" {
  type = string
}
```

**2. VPC**
 
```tf:terraform/common/vpc.tf
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = "jins-${var.env}"
  cidr = var.jins_cidr

  azs              = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
  public_subnets   = [cidrsubnet(var.akane_cidr, 8, 10), cidrsubnet(var.akane_cidr, 8, 11), cidrsubnet(var.jins_cidr, 8, 12)]
  private_subnets  = [cidrsubnet(var.akane_cidr, 8, 20), cidrsubnet(var.akane_cidr, 8, 21), cidrsubnet(var.jins_cidr, 8, 22)]
  database_subnets = [cidrsubnet(var.akane_cidr, 8, 30), cidrsubnet(var.akane_cidr, 8, 31), cidrsubnet(var.jins_cidr, 8, 32)]


  enable_nat_gateway     = true
  single_nat_gateway     = false
  one_nat_gateway_per_az = true # One NAT Gateway per availability zone
  enable_vpn_gateway     = true
  enable_dns_hostnames   = true
  enable_dns_support     = true

  dhcp_options_domain_name_servers = ["AmazonProvidedDNS"]

  public_subnet_tags = {
    "kubernetes.io/role/elb" = "1"
  }
}

```

**3. S3とDynamoDBの利用設定**
 
```tf:terraform/dev/main/backend.tf
terraform {
  required_version = ">= 1.1.6"

  backend "s3" {
    bucket = "akane-dev-terraform-state"

    key            = "terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "akane-dev-terraform-state-lock"
  }
}
```

**4.パラメータ設定**
 
```tf:terraform/dev/main/main.tf
module "common" {
  source = "../../common"

  env                = "dev"
  aws_account_id     = "XXXXXXXXXXXX"
  aws_default_region = "ap-northeast-1"
  jins_cidr          = "10.0.0.0/16"
}
```

**5.AWSの設定**
 
```tf:terraform/dev/main/providers.tf
provider "aws" {
  region = "ap-northeast-1"
  default_tags {
    tags = {
      Environment = "dev"
      Terraform   = "true"
    }
  }
}
```