🐈

terraform学習中のメモ

に公開

terraformの学習中のコードです。これはAIに生成してもらったwebサーバーの作成コードです。
場所を問わずどこでも学習できるように個人用にメモしているだけです。


# COnfigure the AWS Privider
provider "aws"{
    region = "ap-northeast-1"
}

#############################################
# ① VPC(仮想ネットワークの作成)
#############################################
# AWS上でネットワークを分離する“仮想データセンター”。
# CIDRブロックはプライベートIP範囲(例:10.0.0.0/16)
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

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

#############################################
# ② インターネットゲートウェイ(IGW)
#############################################
# VPCをインターネットに接続するための“出口”。
# 無いと外部通信(dnf updateなど)ができない。
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

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

#############################################
# ③ ルートテーブル(経路情報)
#############################################
# VPC内のトラフィックルールを定義。
# デフォルトルート(0.0.0.0/0)をIGWに向けることで外部通信が可能。
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }

  tags = {
    Name = "terraform-public-rt"
  }
}

#############################################
# ④ サブネット(VPCの中の小さなネットワーク)
#############################################
# EC2を置く“区画”。
# map_public_ip_on_launch = true にすると、
# EC2起動時に自動でPublic IPが割り当てられる。
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true # 自動でPublic IP付与

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

#############################################
# ⑤ サブネットとルートテーブルの紐付け
#############################################
# このサブネット内のインスタンスが外部に出るときは
# このルートテーブルを使う(IGW経由)。
resource "aws_route_table_association" "public_assoc" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public_rt.id
}

#############################################
# ⑥ セキュリティグループ(仮想ファイアウォール)
#############################################
# EC2への通信を制御。
# 今回はSSH(22)、HTTP(80)、HTTPS(443)を許可。
resource "aws_security_group" "web_sg" {
  name        = "terraform-web-sg"
  description = "Allow SSH, HTTP, HTTPS"
  vpc_id      = aws_vpc.main.id

  ingress {
    description = "SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # 本番では制限すべき
  }

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

  ingress {
    description = "HTTPS"
    from_port   = 443
    to_port     = 443
    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-web-sg"
  }
}

#############################################
# ⑦ Elastic IP(固定のPublic IP)
#############################################
# Public IPは再起動で変わるが、EIPは固定。
# 本番環境やSSH接続で安定した通信が必要なときに使う。
resource "aws_eip" "web_eip" {
  domain = "vpc" # 新仕様。vpc=trueの代わり。
  
  tags = {
    Name = "terraform-web-eip"
  }
}

#############################################
# ⑧ EC2インスタンス(Webサーバー)
#############################################
# 実際の仮想サーバーを起動する部分。
# AMI: Amazon Linux 2023、t3.microは無料枠対象。
resource "aws_instance" "web" {
  ami                         = "ami-0b89c1d8a8c1e1d6e" # Amazon Linux 2023(東京)
  instance_type               = "t3.micro"
  subnet_id                   = aws_subnet.public.id
  vpc_security_group_ids      = [aws_security_group.web_sg.id]
  key_name                    = "my-keypair" # AWSコンソールで事前に作成
  associate_public_ip_address = true # EIPもあるが学習用にtrue

  #############################################
  # 起動時にWebサーバーを自動インストール
  #############################################
  # ここはLPICで学ぶようなLinuxコマンドを自動実行する部分。
  # EC2内部でroot権限で動くbashスクリプト。
  user_data = <<-EOF
    #!/bin/bash
    dnf update -y
    dnf install -y httpd
    systemctl enable httpd
    systemctl start httpd
    echo "<h1>Hello from Terraform Web Server</h1>" > /var/www/html/index.html
  EOF

  #############################################
  # ディスク設定(EBS:EC2にアタッチされるストレージ)
  #############################################
  # root_block_device はルートディスクの設定。
  # 必須ではないが、サイズや削除ポリシーを制御できる。
  root_block_device {
    volume_size           = 8
    volume_type           = "gp3"
    delete_on_termination = true # EC2削除時にEBSも削除
  }

  #############################################
  # IGWが存在しないと user_data の dnf update が失敗するため、
  # 明示的に依存関係を指定
  #############################################
  depends_on = [aws_internet_gateway.igw]

  tags = {
    Name        = "terraform-web"
    Environment = "dev"
    Owner       = "student"
  }
}

#############################################
# ⑨ EIPとEC2の紐付け
#############################################
# allocation_id(eipalloc-xxxx形式)はEIPの内部識別子。
# public_ipではなくIDで関連付けるのが正しい。
resource "aws_eip_association" "web_assoc" {
  allocation_id = aws_eip.web_eip.id
  instance_id   = aws_instance.web.id
}

#############################################
# 🔟 出力(apply後にIPを表示)
#############################################
# terraform apply完了後にEIPのPublic IPを表示する。
# ブラウザアクセスやSSH接続確認に便利。
output "ec2_public_ip" {
  description = "アクセス用のパブリックIPアドレス"
  value       = aws_eip.web_eip.public_ip
}


# TerraformでEC2 Webサーバーを構築する流れ(自分の理解メモ)

---

## **① VPCの作成**
- AWS上でリソースをまとめるための仮想ネットワークを作成する。  
- CIDRブロック(例:10.0.0.0/16)でIPアドレス範囲を指定。  
- すべてのネットワークリソース(サブネット、IGW、SGなど)の基盤になる。

---

## **② インターネットゲートウェイ(IGW)の作成**
-VPCと紐づける    
- IGWがないと、EC2などのリソースは外部通信できない。
---

## **③ ルートテーブルの作成とルート設定**
- サブネットがどの通信経路を通って通信するかを設定  
- VPCに関連付ける。  
- ルートの設定として外部通信ができるように「0.0.0.0/0 → IGW」と設定する。

---

## **④ サブネットの作成**  
- VPCに関連付けてCIDRブロック(例:10.0.1.0/24)を指定。  
- `map_public_ip_on_launch` を設定して以下を決める:  
  - `true` → 自動でPublic IPを付与(パブリックサブネット)  
  - `false` → 自動付与なし。EIPを後で明示的に割り当てる必要あり。

---

## **⑤ サブネットとルートテーブルの紐付け**
- サブネットをどのルートテーブル経由で通信させるかを決める。  
- 紐付けることで、サブネット内のインスタンスがインターネットへアクセス可能になる。

---

## **⑥ セキュリティグループ(SG)の作成**
- EC2への通信を制御するファイアウォールを作成。  
- VPCに紐づける。  
- ingress(インバウンド)と egress(アウトバウンド)を設定:  
  - ingress:SSH(22)、HTTP(80)、HTTPS(443)を許可  
  - egress:全通信許可(0.0.0.0/0)

---

## **⑦ EIP(Elastic IP)の作成**
- 固定のPublic IPを作成する。  
- `map_public_ip_on_launch = false` にしたサブネットで外部通信したい場合に必要。  
- 実務ではほぼEIPを使用する(Public IPは再起動で変わるため)。

---

## **⑧ EC2インスタンスの作成**
- amiで仮想サーバー(Amazon Linux 2023など)を作成。  
- サブネットとセキュリティグループを紐づける。  
- `depends_on = [aws_internet_gateway.igw]` を指定し、IGWが先に作成されるよう順序を明示。  
- `user_data` にApacheの自動インストール用Linuxコマンドを記述。  
- `root_block_device` はEC2にアタッチされるEBSの設定。  
  - デフォルトで問題ない場合は省略可能。  
  - サイズや削除ポリシーを変えたいときのみ記述する。

---

## **⑨ EIPとEC2インスタンスの紐付け**
- `allocation_id` を使ってEIPをEC2に関連付ける。  
- 紐付けることで固定IPでのアクセスが可能になる。

---

## **⑩ 出力(output)の設定**
- `terraform apply` 実行後に、EIPのPublic IPを表示。  
- SSH接続やブラウザでアクセス確認をする際に便利。

---

## **補足まとめ**
- `map_public_ip_on_launch = false` にした場合は、外部通信にはEIPが必要。  
- 実務ではEIPを使うのが基本(IPの固定・再現性・監査のため)。  
- `depends_on` はTerraformの自動依存関係で不足する部分を明示するために使う。  
- `user_data` はEC2の中で実行されるLinuxコマンド(Apacheなどを自動構築)。  
- `root_block_device` はEBS(EC2のディスク)の設定。変更が必要な場合だけ記述。  
- `output` はapply後の確認用出力。Terraformの結果をすぐに確認できる。

---

Discussion