Terraform個人メモ：VPC、6つのサブネット、IGW、ルートテーブル、NAT、ALB、EC2のコード化

## はじめに
まず、大前提として、ここから先は現在キャッチアップしているTerraformを使いながら、さまざまなコードを自分用に書いていきます。

:::note alert
**※補足事項**
***そのため、内容は完全に自分向けとなっています。***
:::

また、このブログ投稿サイトのプラットフォームについても、自分自身の備忘録としてメモを残す場として活用していきたいと考えています。***このプラットフォーム上に記録を積み重ねていく予定です。***

あらかじめ、その点をご理解いただければ幸いです。

## 実際にコードで行っていること

前回の続きです。

https://qiita.com/free-honda/items/1772a6718dd4a34202a4

https://qiita.com/free-honda/items/91b71aa6ac238510a2e6

- **AWSプロバイダー設定**
  - 東京リージョンでリソースを構築する設定。

- **VPC作成**
  - CIDRブロック範囲 `10.0.0.0/16` のVPCを作成。
  - DNSサポートとDNSホスト名を有効化。

- **パブリックサブネット作成**
  - 2つのパブリックサブネットを異なるアベイラビリティゾーンで作成。
  - インターネットゲートウェイを通じてインターネットにアクセス可能。

- **プライベートサブネット作成**
  - 4つのプライベートサブネットを異なるCIDRブロックとアベイラビリティゾーンで作成。
  - NATゲートウェイを経由してインターネットにアクセス可能。

- **インターネットゲートウェイ設定**
  - パブリックサブネットのインターネットアクセスを提供。

- **ルートテーブルの設定**
  - パブリックサブネット用のルートテーブルを作成し、インターネットゲートウェイをルートに設定。
  - プライベートサブネット用のルートテーブルを作成し、NATゲートウェイをルートに設定。

- **NATゲートウェイ設定**
  - Elastic IPを割り当てたNATゲートウェイを作成。
  - プライベートサブネットのアウトバウンド通信をサポート。

- **サブネットとルートテーブルの関連付け**
  - 各サブネットを対応するルートテーブルに関連付け。

- **セキュリティグループ設定**
  - SSH（22番）とALB（80番）のインバウンド通信を許可。。
  - 全アウトバウンドトラフィックを許可。。

- **EC2インスタンス作成**
  - プライベートサブネット1にAmazon Linux 2の`t2.micro`インスタンスを作成。
  - Apacheをインストールして簡易的なWebサーバーをセットアップ。
  - セキュリティグループを適用して通信を制御。

- **ALBとターゲットグループの設定**
  - 外部公開用のALBを作成し、HTTPリクエストを処理するターゲットグループを設定（ヘルスチェックとスティッキーセッションを有効化）。

- **EC2インスタンスの登録**
  - プライベートサブネット内のEC2インスタンスをターゲットグループに登録し、ALBを介してリクエストを転送。

## 作ったコードについて

```main.tf
# AWSプロバイダーの設定
provider "aws" {
  region = "ap-northeast-1" # 東京リージョン
}

# VPCの作成
resource "aws_vpc" "main" {
  cidr_block       = "10.0.0.0/16" # VPCのCIDRブロック
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "Terraform-vpc" # VPCの名前タグ
  }
}

# パブリックサブネット1の作成
resource "aws_subnet" "public1" {
  vpc_id            = aws_vpc.main.id        # 対象のVPC ID
  cidr_block        = "10.0.0.0/20"         # サブネットのCIDRブロック
  availability_zone = "ap-northeast-1a"    # 対象のアベイラビリティゾーン

  tags = {
    Name = "Terraform-subnet-public1-ap-northeast-1a" # サブネットの名前タグ
  }
}

# パブリックサブネット2の作成
resource "aws_subnet" "public2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.16.0/20"        # 別のCIDRブロックを使用
  availability_zone = "ap-northeast-1c"    # 別のアベイラビリティゾーンを指定

  tags = {
    Name = "Terraform-subnet-public2-ap-northeast-1c"
  }
}

# プライベートサブネット1の作成
resource "aws_subnet" "private1" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.128.0/20"       # プライベート用CIDRブロック
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "Terraform-subnet-private1-ap-northeast-1a"
  }
}

# プライベートサブネット2の作成
resource "aws_subnet" "private2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.144.0/20"       # 別のCIDRブロックを使用
  availability_zone = "ap-northeast-1c"

  tags = {
    Name = "Terraform-subnet-private2-ap-northeast-1c"
  }
}

# プライベートサブネット3の作成
resource "aws_subnet" "private3" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.160.0/20"       # さらに別のCIDRブロック
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "Terraform-subnet-private3-ap-northeast-1a"
  }
}

# プライベートサブネット4の作成
resource "aws_subnet" "private4" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.176.0/20"       # 最後のCIDRブロック
  availability_zone = "ap-northeast-1c"

  tags = {
    Name = "Terraform-subnet-private4-ap-northeast-1c"
  }
}

# インターネットゲートウェイの作成
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id # 対象のVPC ID

  tags = {
    Name = "Terraform-igw" # インターネットゲートウェイの名前タグ
  }
}

# パブリックルートテーブルの作成
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id # 対象のVPC ID

  tags = {
    Name = "Terraform-rtb-public" # ルートテーブルの名前タグ
  }
}

# パブリックルートの設定
resource "aws_route" "public_internet_access" {
  route_table_id         = aws_route_table.public.id  # パブリックルートテーブルのID
  destination_cidr_block = "0.0.0.0/0"               # 全トラフィックを許可
  gateway_id             = aws_internet_gateway.main.id # インターネットゲートウェイを指定
}

# パブリックサブネット1をルートテーブルに関連付け
resource "aws_route_table_association" "public1" {
  subnet_id      = aws_subnet.public1.id # パブリックサブネット1のID
  route_table_id = aws_route_table.public.id # パブリックルートテーブルのID
}

# パブリックサブネット2をルートテーブルに関連付け
resource "aws_route_table_association" "public2" {
  subnet_id      = aws_subnet.public2.id # パブリックサブネット2のID
  route_table_id = aws_route_table.public.id
}

# NATゲートウェイ用のEIP（Elastic IP）を作成
resource "aws_eip" "nat" {
  tags = {
    Name = "Terraform-eip-ap-northeast-1a" # Elastic IPの名前タグ
  }
}

# NATゲートウェイの作成
resource "aws_nat_gateway" "public1" {
  subnet_id     = aws_subnet.public1.id # NATゲートウェイを配置するサブネット
  allocation_id = aws_eip.nat.id        # Elastic IPを割り当て

  tags = {
    Name = "Terraform-nat-public1-ap-northeast-1a" # NATゲートウェイの名前タグ
  }
}

# プライベートルートテーブル1の作成
resource "aws_route_table" "private1" {
  vpc_id = aws_vpc.main.id # 対象のVPC ID

  tags = {
    Name = "Terraform-rtb-private1-ap-northeast-1a" # プライベートルートテーブルの名前タグ
  }
}

# プライベートルート1の設定（NATゲートウェイ経由）
resource "aws_route" "private1_nat_access" {
  route_table_id         = aws_route_table.private1.id # プライベートルートテーブル1のID
  destination_cidr_block = "0.0.0.0/0"                # 全トラフィックを許可
  nat_gateway_id         = aws_nat_gateway.public1.id # NATゲートウェイのID
}

# プライベートサブネット1をルートテーブル1に関連付け
resource "aws_route_table_association" "private1" {
  subnet_id      = aws_subnet.private1.id # プライベートサブネット1のID
  route_table_id = aws_route_table.private1.id # プライベートルートテーブル1のID
}

# プライベートルートテーブル2の作成
resource "aws_route_table" "private2" {
  vpc_id = aws_vpc.main.id # 対象のVPC ID

  tags = {
    Name = "Terraform-rtb-private2-ap-northeast-1c" # プライベートルートテーブルの名前タグ
  }
}

# プライベートルート2の設定（NATゲートウェイ経由）
resource "aws_route" "private2_nat_access" {
  route_table_id         = aws_route_table.private2.id # プライベートルートテーブル2のID
  destination_cidr_block = "0.0.0.0/0"                # 全トラフィックを許可
  nat_gateway_id         = aws_nat_gateway.public1.id # NATゲートウェイのID
}

# プライベートサブネット2をプライベートルートテーブル2に関連付け
resource "aws_route_table_association" "private2" {
  subnet_id      = aws_subnet.private2.id # プライベートサブネット2のID
  route_table_id = aws_route_table.private2.id # プライベートルートテーブル2のID
}

# プライベートルートテーブル3の作成
resource "aws_route_table" "private3" {
  vpc_id = aws_vpc.main.id # 対象のVPC ID

  tags = {
    Name = "Terraform-rtb-private3-ap-northeast-1a" # プライベートルートテーブル3の名前タグ
  }
}

# プライベートルート3の設定（NATゲートウェイ経由）
resource "aws_route" "private3_nat_access" {
  route_table_id         = aws_route_table.private3.id # プライベートルートテーブル3のID
  destination_cidr_block = "0.0.0.0/0"                # 全トラフィックを許可
  nat_gateway_id         = aws_nat_gateway.public1.id # NATゲートウェイのID
}

# プライベートサブネット3をプライベートルートテーブル3に関連付け
resource "aws_route_table_association" "private3" {
  subnet_id      = aws_subnet.private3.id # プライベートサブネット3のID
  route_table_id = aws_route_table.private3.id # プライベートルートテーブル3のID
}

# プライベートルートテーブル4の作成
resource "aws_route_table" "private4" {
  vpc_id = aws_vpc.main.id # 対象のVPC ID

  tags = {
    Name = "Terraform-rtb-private4-ap-northeast-1c" # プライベートルートテーブル4の名前タグ
  }
}

# プライベートルート4の設定（NATゲートウェイ経由）
resource "aws_route" "private4_nat_access" {
  route_table_id         = aws_route_table.private4.id # プライベートルートテーブル4のID
  destination_cidr_block = "0.0.0.0/0"                # 全トラフィックを許可
  nat_gateway_id         = aws_nat_gateway.public1.id # NATゲートウェイのID
}

# プライベートサブネット4をプライベートルートテーブル4に関連付け
resource "aws_route_table_association" "private4" {
  subnet_id      = aws_subnet.private4.id # プライベートサブネット4のID
  route_table_id = aws_route_table.private4.id # プライベートルートテーブル4のID
}

# セキュリティグループの作成（プライベートサブネット用）
resource "aws_security_group" "private_instance_sg" {
  vpc_id = aws_vpc.main.id

  # SSHポート（22番）を許可（管理者用）
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # 必要に応じて制限
  }

  # ALBからのHTTPリクエスト（80番ポート）を許可
  ingress {
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    security_groups = [aws_security_group.public_sg.id] # ALBのセキュリティグループを指定
  }

  # 全トラフィックの送信を許可（アウトバウンド）
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "Terraform-private-instance-sg"
  }
}

# プライベートサブネット1にEC2インスタンス作成
resource "aws_instance" "private_apache_ec2" {
  ami                         = "ami-0b6fe957a0eb4c1b9" # Amazon Linux 2 の AMI（要確認）
  instance_type               = "t2.micro"             # インスタンスタイプ
  subnet_id                   = aws_subnet.private1.id # プライベートサブネット1
  security_groups             = [aws_security_group.private_instance_sg.id] # セキュリティグループ

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "<html><body><h1>プライベートインスタンスでホスティング中</h1></body></html>" > /var/www/html/index.html
  EOF

  tags = {
    Name = "terraform-private-apache-ec2"
  }

  depends_on = [aws_security_group.private_instance_sg]
}

# パブリック用セキュリティグループ作成
resource "aws_security_group" "public_sg" {
  vpc_id = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "Terraform-public-sg"
  }
}

# アプリケーションロードバランサー(ALB)作成
resource "aws_lb" "main_alb" {
  name               = "terraform-main-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.public_sg.id]
  subnets            = [aws_subnet.public1.id, aws_subnet.public2.id]

  enable_deletion_protection = false

  tags = {
    Name = "terraform-main-alb"
  }
}

# ターゲットグループ作成
resource "aws_lb_target_group" "main_target_group" {
  name     = "terraform-main-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.main.id

  health_check {
    interval = 30
    path     = "/"
    protocol = "HTTP"
    timeout  = 5
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }

  stickiness {
    type            = "lb_cookie"
    enabled         = true
    cookie_duration = 86400
  }

  tags = {
    Name = "terraform-main-target-group"
  }
}

# ALBのリスナー作成
resource "aws_lb_listener" "http_listener" {
  load_balancer_arn = aws_lb.main_alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.main_target_group.arn
  }
}

# EC2インスタンスをターゲットグループに追加
resource "aws_lb_target_group_attachment" "ec2_attachment" {
  target_group_arn = aws_lb_target_group.main_target_group.arn
  target_id        = aws_instance.private_apache_ec2.id
  port             = 80
}
```

## まとめ
この記事は、自分用の備忘録としてまとめたものです。その点をご理解いただけると幸いです。

:::note info
***もし、この記事の内容が少しでも参考になれば嬉しく思います。***
:::

今後も同様の内容を継続して投稿していきますので、温かく見守っていただけるとありがたいです。

## おまけ
今回作成したALBのDNS名でアクセスすると、ブラウザで以下のように表示されることを確認できます。

![Screenshot 2025-01-22 at 11.10.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/28403fc5-ef13-3a49-529a-1abcbb2909a8.png)