Terraformを使用してVPC、Subnet、Internet Gateway、Route Tableを構築した

# 概要
`Terraform`について理解が深まってきた為、今回は`Terraform`を使用して表題の構築を行いました。
備忘録も含めて、今回の構築手順を載せます。


# 前提条件
- `Terraform`をインストールしている
- [aws provider](https://registry.terraform.io/providers/hashicorp/aws/latest)関連の構築が完了している

##  Terraformのvarsion
```sh
terraform --version

# Terraformのvarsion
Terraform v1.7.5

# providerのvarsion
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws 5.70.0
```
<font color="red">**※ Terraformの導入方法やアップデート情報を下記を参照して下さい。**</font>
- [tfenvを使用したTerraformのインストール方法](https://qiita.com/kengo-sk8/items/1d6ca8347da1b5419c58)

# 各リソースの構築
## VPC(Amazon Virtual Private Cloud)
- `VPC`は、クラウド上に作られる専用のネットワーク空間
- 要約すると自分背用の自由にサーバーやネットワーク機器を配置出来る空間
```vpc.tf
resource "aws_vpc" "test_vpc" {
  cidr_block = "10.0.0.0/16"

  assign_generated_ipv6_cidr_block     = false
  enable_dns_hostnames                 = true
  enable_dns_support                   = true
  enable_network_address_usage_metrics = false
  instance_tenancy                     = "default"

  tags = {
   Name = "test-vpc" # 任意の名前
  }
}
```

| メソッド | 説明 |
| :-: | - |
| assign_generated_ipv6_cidr_block | `VPC`に自動生成された`IPv6`の`CIDR`ブロック(`IP`アドレス範囲)を割り当てるかどうかを制御 |
| enable_dns_hostnames | `IP`アドレスの代わりに`DNS`名(例: `ec2-***-****-***-1.compute-1.amazonaws.com`)を使用したアクセスの可否を制御する |
| enable_dns_hostnames | `VPC`内の`IP`アドレス使用状況を監視するメトリクスの有効化を管理 |
| instance_tenancy | `EC2`インスタンスが共有ハードウェアで実行されるか、専用ハードウェアで実行されるかを決める。特殊な用途でない限り`"default"`で良い |


### 参考資料
- [[AWS公式] IPv4 VPC CIDR ブロック](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-sizing-ipv4)
- [[HashiCorp] aws_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc)

## Subnet(サブネット)
- VPC内で作成される小さなネットワークの一部であり、EC2やECS等のリソースを配置する為の論理的な区画
- 各サブネットは特定の**アベイラビリティゾーン(AZ)** に属し、VPCのIPアドレス範囲内で定義される

***
- 今回構築する各サブネットの利用範囲を下記に記載 
(ネットワークアドレスとブロードキャストアドレスは除外している)

| サブネット名                | CIDRブロック | ネットワークアドレス | 利用可能範囲            | 
| :-------------------------: | :----------: | :------------------: | :---------------------: | 
| test-subunet-public-a  | 10.0.1.0/24  | 10.0.1.0             | 10.0.1.1 ~ 10.0.1.254   | 
| test-subunet-public-c  | 10.0.2.0/24  | 10.0.2.0             | 10.0.2.1 ~ 10.0.2.254   | 
| test-subunet-public-d  | 10.0.3.0/24  | 10.0.3.0             | 10.0.3.1 ~ 10.0.3.254   | 
| test-subunet-private-a | 10.0.10.0/24 | 10.0.10.0            | 10.0.10.1 ~ 10.0.10.254 | 
| test-subunet-private-c | 10.0.20.0/24 | 10.0.20.1            | 10.0.20.1 ~ 10.0.20.254 | 
| test-subunet-private-d | 10.0.30.0/24 | 10.0.30.1            | 10.0.30.1 ~ 10.0.30.254 | 
- ブロードキャストアドレス : 同じサブネット内の全てのデバイスに対して、一斉メッセージを送る為の特別なIPアドレス
- ネットワークアドレス : 今回の場合は、そのサブネット全体を指す識別アドレス

***

- `Terrform`を使用した`subnet`の構築を下記に記載
```tf
# パブリック
resource "aws_subnet" "public_subnet_a" {
  cidr_block        = "10.0.1.0/24"
  vpc_id            = aws_vpc.test_vpc.id
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "test-subunet-public-a"
  }
}

resource "aws_subnet" "public_subnet_c" {
  cidr_block        = "10.0.2.0/24"
  vpc_id            = aws_vpc.test_vpc.id
  availability_zone = "ap-northeast-1c"

  tags = {
    Name = "test-subunet-public-c" # 任意の名前
  }
}

resource "aws_subnet" "test_public_subnet_d" {
  cidr_block        = "10.0.3.0/24"
  vpc_id            = aws_vpc.test_vpc.id
  availability_zone = "ap-northeast-1d"

  tags = {
    Name = "test-subunet-public-d" # 任意の名前
  }
}


# プライベート
resource "aws_subnet" "test_private_subnet_a" {
  cidr_block        = "10.0.10.0/24"
  vpc_id            = aws_vpc.test_vpc.id
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "test-subunet-private-a" # 任意の名前
  }
}

resource "aws_subnet" "test_private_subnet_c" {
  cidr_block        = "10.0.20.0/24"
  vpc_id            = aws_vpc.test_vpc.id
  availability_zone = "ap-northeast-1c"

  tags = {
    Name = "test-subunet-private-c" # 任意の名前
  }
}

resource "aws_subnet" "test_private_subnet_d" {
  cidr_block        = "10.0.30.0/24"
  vpc_id            = aws_vpc.test_vpc.id
  availability_zone = "ap-northeast-1}d"

  tags = {
    Name = "test-subunet-private-d" # 任意の名前
  }
}
```
### 参考資料
- [[HashiCorp] aws_subnet](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet)


## Internet Gateway
- VPC内のリソース(例: EC2やECS等)をインターネットと接続する為のゲートウェイ
```tf
resource "aws_internet_gateway" "test_igw" {
  vpc_id = aws_vpc.test_vpc.id

  tags = {
    Name  = "test-igw"
  }
}
```

### 参考資料
- [[HashiCorp] aws_internet_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway)


## Route Table
- VPC内のネットワークトラフィックがどこに送られるかを管理・制御する機能
- 今回は、パブリックサブネットにルートテーブルを設定し、インターネットゲートウェイを通してインターネットと通信出来る様に構築している


```tf
resource "aws_route_table" "test_public_route_table" {
  vpc_id = aws_vpc.test_vpc.id
  
  tags = {
    Name = "test-route-table"
  }
}

# ルートの設定
# Internet Gatewayへの経路情報を追加
resource "aws_route" "test_public_route_table" {
  route_table_id         = aws_route_table.test_public_route_table.id
  gateway_id             = aws_internet_gateway.test_igw.id
  destination_cidr_block = "0.0.0.0/0"
}

# サブネットの関連付け
# Public Subnet aと紐付け
resource "aws_route_table_association" "test_public_a" {
  route_table_id = aws_route_table.test_public_route_table.id
  subnet_id      = aws_subnet.test_public_subnet_a.id
}

# Public Subnet cと紐付け
resource "aws_route_table_association" "test_public_c" {
  route_table_id = aws_route_table.test_public_route_table.id
  subnet_id      = aws_subnet.test_public_subnet_c.id
}

# Public Subnet dと紐付け
resource "aws_route_table_association" "test_public_d" {
  route_table_id = aws_route_table.test_public_route_table.id
  subnet_id      = aws_subnet.test_public_subnet_d.id
}
```

# 著者の作成したコード

https://github.com/kengo-sk8/basic_network_structure


# 参考資料
- [[公式 hashicorp] ドキュメント](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
- [[TerraformでAWS VPCを構築してみる] Route Table](https://www.ios-net.co.jp/blog/20230405-910/#Route_Table)

# まとめ
今回は、`Terraform`を使用して基本的なネットワークを構築しました。基本的な事が分かっていなかったので、今回学べて良かったです。