Terraformで冗長構成のVPCをデプロイ

## はじめに
以前作成した冗長構成のCloudFormationテンプレートからTerraformのテンプレートを作成してデプロイしてみました。


## 比較
TerraformとCloudFormationの簡単な比較を挙げるとすると以下の点になります。
### CloudFormation
- AWS特化でAWSリソースの管理を迅速に行いたい場合
- 管理コストを抑え、AWS公式のサポートを受けられる

### Terraform
- マルチクラウド
- AWS以外のリソースも必要で柔軟性重視


## 作成するリソースについて
CFnテンプレートについては以下の記事を参照してください。
[冗長構成WebサーバーのCloudFormationテンプレートを作成、デプロイ](https://qiita.com/Ryuta_Uchimura/items/a77e533a6e11b942bc59)
Githubから直接ダウンロードできます。
https://github.com/ryt117/LAMP
### VPC
- 今回はVPCのみです
![名称未設定ファイル.drawio(3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/d40a4b17-8467-fe89-129d-d7b0c3df3214.png)

### コードの概要
目的: 高可用性構成のVPCを作成し、パブリックおよびプライベートサブネットを設定
テンプレート概要:
- 1つのVPC
- 2つのパブリックサブネット
- 2つのプライベートサブネット
- インターネットゲートウェイとそれに紐づくルートテーブル
        
### パラメータ
- VPC

|項目  |値  |
|---|---|
|名前  |test-vpc  |
|CIDRブロック  |10.0.0.0/16  |
|DNSサポート  |有効  |
|DNSホスト名  |有効  |

- サブネット

|サブネット名  |CIDRブロック  |可用性ゾーン  |パブリックIP  |備考  |
|---|---|---|---|---|
|PublicSubnet1  |10.0.0.0/24  |AZ1  |自動割り当て  |パブリック通信が可能  |
|PublicSubnet2  |10.0.1.0/24  |AZ2  |自動割り当て  |パブリック通信が可能  |
|PrivateSubnet1 |10.0.10.0/24 |AZ1  |無効  |プライベート通信  |
|PrivateSubnet2 |10.0.11.0/24 |AZ2  |無効  |プライベート通信  |

- インターネットゲートウェイ

|項目  |値  |
|---|---|
|名前  |test-igw  |
|接続VPC  |test-vpc  |

- ルートテーブル

|項目  |値  |
|---|---|
|名前  |test-public-crt  |
|ルート  |デフォルトルート (0.0.0.0/0) をインターネットゲートウェイに設定  |
|サブネットの関連付け  |PublicSubnet1, PublicSubnet2  |


## 作成したTerraformコード
```
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "test-vpc"
  }
}

resource "aws_subnet" "public1" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.0.0/24"
  availability_zone       = data.aws_availability_zones.available.names[0]
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-1"
  }
}

resource "aws_subnet" "public2" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = data.aws_availability_zones.available.names[1]
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-2"
  }
}

resource "aws_subnet" "private1" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.10.0/24"
  availability_zone = data.aws_availability_zones.available.names[0]

  tags = {
    Name = "private-subnet-1"
  }
}

resource "aws_subnet" "private2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.11.0/24"
  availability_zone = data.aws_availability_zones.available.names[1]

  tags = {
    Name = "private-subnet-2"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

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

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "test-public-crt"
  }
}

resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.main.id
}

resource "aws_route_table_association" "public1" {
  subnet_id      = aws_subnet.public1.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "public2" {
  subnet_id      = aws_subnet.public2.id
  route_table_id = aws_route_table.public.id
}

data "aws_availability_zones" "available" {
  state = "available"
}

output "vpc_id" {
  description = "VPC ID"
  value       = aws_vpc.main.id
}

output "public_subnet1_id" {
  description = "Public Subnet 1 ID"
  value       = aws_subnet.public1.id
}

output "public_subnet2_id" {
  description = "Public Subnet 2 ID"
  value       = aws_subnet.public2.id
}

output "private_subnet1_id" {
  description = "Private Subnet 1 ID"
  value       = aws_subnet.private1.id
}

output "private_subnet2_id" {
  description = "Private Subnet 2 ID"
  value       = aws_subnet.private2.id
}
```



## 実行結果
```
Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

private_subnet1_id = "subnet-0cf2161a97bac1e24"
private_subnet2_id = "subnet-0643ec94941964990"
public_subnet1_id = "subnet-096f15906f75ab82d"
public_subnet2_id = "subnet-0aac66abee5aeb7ca"
vpc_id = "vpc-06a4ad69313a28fb1"

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.
```
- VPC
![Screenshot 2024-11-25 at 14-41-51 vpcs VPC Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/046b4b37-95af-dadf-0fde-c94adc0a8b0d.png)

- サブネット
![Screenshot 2024-11-25 at 14-42-10 subnets VPC Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/e500d93b-976a-35f5-2ebe-366f2f0403a7.png)

- インターネットゲートウェイ
![Screenshot 2024-11-25 at 14-42-32 igws VPC Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/4f003e61-26da-9d35-bf9f-129468ce4d44.png)




## 最後に
Terraformはマルチクラウドで実行可能なのが学習の後押しとなりました。
シェアからみてもAWS以外のクラウドが伸びつつある中、AzureやGCPに対しても一貫性を保ち、クラウド環境間で移行可能という点がCloudFormationと比較しても魅力的に感じるポイントだと思いました。