TerraformでAWSのネットワークまわり（VPC、サブネット、ルートテーブル他）をデプロイする

Terraformシリーズ第4弾はネットワークです。

項目はけっこういろいろあってネットワークの主要になる**VPC、サブネット、ルートテーブル、DHCPオプションセット、IGW、NATGW、エンドポイント、ピアリング**あたりです。イメージしにくいと思うので図にしてみました:pencil2:

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/b47cf6f7-2f6b-57f4-4180-d98ff66bb913.png">


※過去のTerraform記事はこちら
第一弾：[TerraformでAWSリソースをデプロイしてみる](https://qiita.com/hiyanger/items/ca337f70ad4801072850)
第二弾：[TerraformでAWS環境をデプロイする前に認識しておくべきこと（tfstate.tf / providor.tf / output.tf / ディレクトリ構造）](https://qiita.com/hiyanger/items/9efdc570e6cfed5aab13)
第三弾：[TerraformでAWSのIAMまわりをデプロイする](https://qiita.com/hiyanger/items/8f925e21166461a5ddb1)

※以下実際にコードを記述していきますが、 **"${local.XXX}"** と記述されているものは個人的に外出しした箇所なので、より参考になるかと思いそのまま残しておきました。

## VPC
```terraform
resource "aws_vpc" "vpc01" {
  cidr_block           = "${local.VPCCIDR値}"
  enable_dns_support   = true #VPC内でのDNSによる名前解決
  enable_dns_hostnames = true #VPC内インスタンスのDNSホスト名取得

  tags = {
    Name = "${local.環境名}"
  }
}
```
※作成されたVPCを他のモジュールで利用する場合、以下のように出力させておきます。（outputに関する詳細は第二弾の記事を参考）
```terraform
output "vpcid" {
  value = "${aws_vpc.vpc01.id}"
}
```

#### DHCPオプションセット
```terraform
resource "aws_vpc_dhcp_options" "dhcp01" {
  domain_name = "${local.DHCPオプションのドメイン名}"
  domain_name_servers = ["${local.DNSサーバ①}","${local.DNSサーバ②}","AmazonProvidedDNS"]
  ntp_servers = ["${local.NTPサーバ①}","${local.NTPサーバ②}"]
  
  #NetBIOSノードタイプ
  netbios_node_type = 2

  tags = {
    Name = "${local.DHCPオプションのドメイン名}"
  }
}

#VPCとの紐付け
resource "aws_vpc_dhcp_options_association" "vpc_vpc01-dhcp-association" {
  vpc_id = aws_vpc.vpc01.id
  dhcp_options_id = aws_vpc_dhcp_options.dhcp01.id
}
```
・DNSサーバは環境に合わせて適宜変更してください（上記はDNSをキャッシュできるサーバが2台存在する前提で記述しています）
・NetBIOSノードタイプはAWSでは「2」が推奨されています

## サブネット
※プラベートサブネットの場合
```terraform
resource "aws_subnet" "private-1a" {
  vpc_id                  = aws_vpc.vpc01.id
  cidr_block              = "${local.サブネットのCIDR値"}
  availability_zone       = "ap-northeast-1a"

  tags = {
    Name = "${local.環境名}"-private-1
  }
}
```
・private/publicの区別は **"aws_subnet"** やタグで記述してあげます
・サブネットもVPC同様outputさせる場合は以下です
```terraform
output "サブネット名" {
  value = "${aws_subnet.private-1a.id}"
}
```
## ゲートウェイ
以下**NATゲートウェイ**までの利用を前提に記載します。
#### インターネットゲートウェイ
```terraform
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc01.id #紐づけるVPC
  tags = {
    Name = "${local.環境名}-igw
  }
}
```
#### EIP
```terraform
resource "aws_eip" "ngw" {
  vpc        = true
  depends_on = [aws_internet_gateway.igw]　#紐付けるIGW
}
```
紐づける先はIGWですが、NATGW用のEIPのため **"aws_eip" "ngw"** としています。
#### NATゲートウェイ
```terraform
resource "aws_nat_gateway" "ngw" {
  allocation_id = aws_eip.ngw.id #紐づけるEIP
  subnet_id     = aws_subnet.public-1a.id #紐づけるパブリックサブネット
  depends_on    = [aws_internet_gateway.igw] #紐付けるIGW
  tags = {
    Name = "${local.環境名}"-ngw
  }
}
```
## ルートテーブル
#### パブリック用
```terraform
#ルートテーブル作成
resource "aws_route_table" "rtb-public" {
  vpc_id = aws_vpc.vpc01.id #VPCとの紐付け

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id #IGWとの紐付け
  }

  tags = {
    Name = "${local.環境名}"-public
  }
}

#サブネットとの紐付け
resource "aws_route_table_association" "rtb-public-1a" {
  subnet_id      = aws_subnet.public-1a.id
  route_table_id = aws_route_table.rtb-public.id
}
```
#### プライベート用
```terraform
#ルートテーブル作成
resource "aws_route_table" "rtb-private" {
  vpc_id = aws_vpc.vpc01.id #VPCとの紐付け

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_nat_gateway.ngw.id #NATGWとの紐付け
  }
  
  tags = {
    Name = "${local.環境名}"-private
  }
}

#サブネットとの紐付け
resource "aws_route_table_association" "rtb-private-1a" {
  subnet_id      = aws_subnet.private-1a.id
  route_table_id = aws_route_table.rtb-private.id
}
```

## エンドポイント（S3の場合）
```terraform
#エンドポイントの作成
resource "aws_vpc_endpoint" "vpces3" {
  vpc_id       = aws_vpc.vpc01.id #VPCとの紐付け
  service_name = "com.amazonaws.ap-northeast-1.s3"
  policy = file("./vpcendpointpolicy.json") #エンドポイントポリシーはjsonで外だしして記述
  tags = {
    Name = "${local.環境名}"-vpce-s3
  }
}

#ルートテーブルとの紐付け
resource "aws_vpc_endpoint_route_table_association" "vpce-01" {
  route_table_id  = aws_route_table.rtb-private.id
  vpc_endpoint_id = aws_vpc_endpoint.vpces3.id
}
```

## VPCピアリング
```terraform
#ピアリング
resource "aws_vpc_peering_connection" "ピア名" {
  peer_owner_id = "${local.ピア先アカウント}"
  peer_vpc_id   = "${local.ピア先VPC}"
  vpc_id        = aws_vpc.vpc01.id

  tags = {
    Name = "${local.環境名}"-"ピア"
  }
}

#ルートテーブルとの紐付け
resource "aws_route" "ピア名" {
  route_table_id            = aws_route_table.rtb-private.id
  destination_cidr_block    = "${local.ピア先CIDR}"
  vpc_peering_connection_id = aws_vpc_peering_connection.ピア名.id
}
```