【AWS】 Terraformで仮想ネットワークを構築

##概要
TerraformでAWSの仮想ネットワーク構築手順をまとめました。
Terraformのインストールから簡単なEC2インスタンス構築までは下記の記事でまとめています。
こちら：　[Terraformを使ってEC2インスタンス構築](https://qiita.com/ramunauna/items/57bd4235b89c059b296f)

##目次
1. VPCを作成
1. パブリックサブネットを作成  
  - サブネットを作成  
  - インターネットゲートウェイを作成  
  - ルートテーブルを作成  
  - サブネットへの関連付け
1. プライベートサブネットを作成
   - サブネットを作成
   - Elastic IPの割り当て / NATゲートウェイを作成
   - ルートテーブルを作成
   - サブネットへの関連付け

##構成図
今回の構成図はこちら。
![AWS_Network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/d4b647cd-2feb-b2e3-3dae-891034c406e9.png)

##1. VPCを作成
main.tfを作成し、VPCの情報を書いていく。

```terraform:main.tf
provider "aws" {
  region = "ap-northeast-1"
}

# VPC作成
resource "aws_vpc" "vpc" {
  cidr_block           = "10.0.0.0/16" #CIDRブロックの指定

  tags = {
    Name : "my-vpc-001"
  }
}
```
今回は簡単にCIDRブロックのみを指定。applyコマンドを実行。
![スクリーンショット 2021-08-15 22.54.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/2d0f94b6-c8ce-b01b-6f20-26848ff1f075.png)
このVPC内にリソースを追加していく。

##2. パブリックサブネットを作成
###サブネットを作成
VPCをさらに分割し、インターネットへアクセス可能なサブネットを作成する。
上記のVPCの記述に続けて下記を追記。

```terraform:main.tf
#サブネットを作成
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.0.0.0/24"
  map_public_ip_on_launch = true
  availability_zone       = "ap-northeast-1a"

  tags = {
    Name : "my-public-subnet-001"
  }
}
```

- `vpc_id = aws_vpc.vpc.id`  
ここではVPCのidを`resource "aws_vpc" "vpc" {`記述箇所から参照している。  
Terraformでは、「リソース(aws_xxx).名前.属性」の形式で書くことで他リソースの情報を参照できる。
- `map_public_ip_on_launch = true`  
trueに設定することで、サブネット内で起動したインスタンスにパブリックIPアドレスを自動的に割り当てる。  

applyコマンドを実行した結果がこちら。
![スクリーンショット 2021-08-15 23.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/39927720-a7d0-0140-c32b-05aa1e038f88.png)
サブネットがVPC内に作成された。

###インターネットゲートウェイを作成
続いて作成したサブネットから、インターネットへアクセスできる様にインターネットゲートウェイを作成。
サブネットの記述に続いて下記を追記。

```terraform:main.tf
#インターネットゲートウェイを作成
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name : "my-igw-001"
  }
}
```
###ルートテーブルを作成
これではまだインターネットを通信できないので、ルーティング情報を管理するルートテーブルを作成する。
下記の3点のリソースを記述していく。

- ルートテーブルの作成 `aws_route_table`
- インターネットゲートウェイへのルートを設定 `aws_route`
- ルートテーブルとサブネットの関連付け `aws_route_table_association`

インターネットゲートウェイの記述に続いて下記を追記。

```terraform:main.tf
#パブリックルートテーブルの作成
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name : "my-public-rtb-001"
  }
}

# インターネットゲートウェイへのルートを設定
resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  gateway_id             = aws_internet_gateway.igw.id
  destination_cidr_block = "0.0.0.0/0"
}

# ルートテーブルとサブネットの関連付け
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}
```
- `aws_route_table_association`  
関連付けをしていない場合、デフォルトルートテーブルが自動的に使われる。  
デフォルトはアンチパターンなので関連付けを忘れない様にしよう。

ここまででapplyコマンドを実行。

インターネットゲートウェイ
![スクリーンショット 2021-08-15 23.46.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/19f8825f-3379-9706-3ff4-b13ae9d5710c.png)
ルートテーブル & サブネットとの関連付け
![スクリーンショット 2021-08-15 23.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/cbe9458f-840f-3b0a-7f43-8f84c405770f.png)
ルートの設定
![スクリーンショット 2021-08-16 0.32.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/f1c649df-ce03-264b-e94d-094866ed0162.png)

全て問題なく作成されたことを確認。
ここまででパブリックサブネットは完了！

##3. プライベートサブネットを作成
インターネットからアクセスできないネットワークを構築する。
その一方で、プライベートサブネットからはインターネットへアクセスできる様、NATゲートウェイを設置する。
###サブネットを作成

```terraform:main.tf
# サブネットを作成
resource "aws_subnet" "private" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = false
  availability_zone       = "ap-northeast-1a"

  tags = {
    Name : "my-private-subnet-001"
  }
}
```
基本パブリックサブネットと同じ。
パブリックIPアドレスは不要なので`map_public_ip_on_launch`はfalseに設定している。

###Elastic IPの割り当て / NATゲートウェイを作成
NATゲートウェイにはElastic IPの割り当てが必要なため、両リソースについて記述する。

```terraform:main.tf
# EIP
resource "aws_eip" "nat_gateway" {
  vpc = true
  depends_on = [
    aws_internet_gateway.igw
  ]

  tags = {
    Name : "my-eip-001"
  }
}

# NATゲートウェイ
resource "aws_nat_gateway" "nat_gateway" {
  allocation_id = aws_eip.nat_gateway.id # Elastic IPアドレスの関連付け
  subnet_id     = aws_subnet.public.id #　NATゲートウェイの設置位置はパブリックサブネット
  depends_on = [
    aws_internet_gateway.igw
  ]

  tags = {
    Name : "my-nat-gate-way-001"
  }
}
```
- NATゲートウェイの設置位置について  
パブリックサブネットに設置する。プライベートサブネットからパブリックサブネット内のNATゲートウェイへルーティングすることにより、インターネットへのアクセスを可能にする。
- `depends_on`について  
`depends_on`では、リソースの依存関係を明示的に定義している。  
ここではインターネットゲートウェイを指定することによって、  
「__先に__インターネットゲートウェイを作成し、インターネットゲートウェイ__作成後__にEIPやNATゲートウェイを構築する」  
という流れを確立している。

続いて、パブリックサブネット同様、ルートテーブルの設定を追記していく。

```terraform:main.tf
# プライベートルートテーブルの作成
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name : "my-private-rtb-001"
  }
}

# NATゲートウェイへのルートを設定
resource "aws_route" "private" {
  route_table_id         = aws_route_table.private.id
  nat_gateway_id         = aws_nat_gateway.nat_gateway.id #gateway_idじゃないよ!
  destination_cidr_block = "0.0.0.0/0"
}

# ルートテーブルとサブネットの関連付け
resource "aws_route_table_association" "private" {
  subnet_id      = aws_subnet.private.id
  route_table_id = aws_route_table.private.id
}
```
ルート設定にて、
パブリックサブネットでは`gateway_id`だった箇所が、プライベートサブネットでは`nat_gateway_id`になるので注意。

applyコマンドを実行。

サブネット
![スクリーンショット 2021-08-16 0.38.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/f27e7716-06b3-c82c-aafa-4a09200acfbf.png)

Elastic IP
![スクリーンショット 2021-08-16 0.28.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/8f4139fc-cc28-2c8f-2571-363a723aada1.png)
NATゲートウェイ
![スクリーンショット 2021-08-16 0.31.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/413d97eb-9982-bec3-747f-f4c08f943033.png)
ルートテーブル
![スクリーンショット 2021-08-16 0.32.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/eb374d87-484c-ec59-36f5-b5e3cbe57a50.png)
ルートの設定
![スクリーンショット 2021-08-16 0.33.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1813991/9b9c4437-cd9f-bc0a-fb15-a15bccf45941.png)

全て問題なく作成されたことを確認。
ここまででプライベートサブネットも完了！

##終わりに
今回はVPC、サブネット、ルートテーブル、各種ゲートウェイの構築をまとめました。
のちに、今回の構成のサブネットにEC2インスタンスを構築する手順、マルチAZ構成などをまとめようと思います。