0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TerraformでAWSの基礎ネットワーク構築をしてみる

Last updated at Posted at 2025-08-25

構築概要

使用技術:Terraform, AWS
リージョン:東京(ap-northeast-1)
構成図
image.png

ディレクトリ構成例:

NETWORK/
├── .terraform/
│   └── modules/
│       └── network/
│           ├── ec2.tf
│           ├── iam.tf
│           ├── igw.tf
│           ├── output.tf
│           ├── route_table_association.tf
│           ├── route_table.tf
│           ├── security_group.tf
│           ├── subnet.tf
│           ├── variables.tf
│           ├── vpc.tf
├── main.tf
├── output.tf


実装のステップ

  1. SSH鍵の作成と登録
  2. VPC・サブネット・IGWの構築
  3. EC2インスタンスの起動
  4. SSH接続と通信確認

各ファイルの中身

CIDR構成の理由

VPC:10.0.0.0/16
VCP全体なので大きめのアドレス空間を確保(最大 65,536 IP)
万が一後からサブネットを追加しても平気なようにしている

Public Subnet:10.0.1.0/24
Public Subnetは 10.0.1.0/24 に固定することで、構成図やログ上でも識別しやすくしています(最大254 IP)

Private Subnet:10.0.101.0/24
Publicと明確に番号を分けることで混乱を防止

変数定義をここ(variables.tf)にまとめておく

// variables.tf
variable "vpc_cidr_block" {
  type = string
}

variable "public_subnet_cidr" {
  type = string
}

variable "private_subnet_cidr" {
  type = string
}
VPCの作成
// vpc.tf
resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr_block
  // /main.tfで定義したvpc_cidr_blockを使用

  tags = {
    Name = "main-vpc"
  }
}
Subnetの作成
// Subnet.tf
resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = var.public_subnet_cidr
  availability_zone = "ap-northeast-1a"
  map_public_ip_on_launch = true
  // 「 map_public_ip_on_launch = true」はサブネット内で起動するEC2インスタンスに自動的にパブリックIPを割り当てる

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

resource "aws_subnet" "private" {
  vpc_id     = aws_vpc.main.id
  cidr_block = var.private_subnet_cidr
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "private-subnet"
  }
}
internet gatewayの作成
// igw.tf
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main-igw"
  }
}
route tableの作成
// route_table.tf
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.main.id

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

# IGW経由のルート追加(0.0.0.0/0)
resource "aws_route" "public_internet" {
  route_table_id         = aws_route_table.public_rt.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}

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

  route {
    cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat.id
  }

  tags = {
    Name = "private-rt"
  }
  
}
サブネットにルートテーブルを紐づけ
// route_table_association.tf
resource "aws_route_table_association" "public_assoc" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public_rt.id
}

resource "aws_route_table_association" "private_assoc" {
  subnet_id = aws_subnet.private.id
  route_table_id = aws_route_table.private_rt.id
}
セキュリティグループの作成
// security_group.tf
resource "aws_security_group" "web_sg" {
  name        = "dev-web-sg"
  description = "Allow SSH and HTTP"
  vpc_id      = aws_vpc.main.id // アタッチするvpcを指定

// session manegerを使用する場合は22番ポートを開ける必要はないため削除する
  ingress { //インバウンドのポート22(SSH)を許可
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress { //インバウンドのポート80(HTTP)を許可
    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"]
  }
}
cidr_blocksについて

このセキュリティグループでは、SSH(22)とHTTP(80)のインバウンド通信を許可し、アウトバウンドは全許可しています。cidr_blocks = ["0.0.0.0/0"] は全世界からのアクセスを意味するため、開発環境ではこれでもいいですが、本番環境ではIPを特定のものだけにすることが大事

EC2インスタンスの作成
resource "aws_instance" "web" {
  ami = "ami-07faa35bbd2230d90" // 東京リージョンのAmazon Linux
  instance_type = "t2.micro"
  subnet_id = aws_subnet.public.id
  security_groups = [aws_security_group.web_sg.id]
  iam_instance_profile   = aws_iam_instance_profile.ssm_profile.name

    tags = {
    Name = "dev-web-server"
  }
}

resource "aws_instance" "private_web" {
  ami = "ami-07faa35bbd2230d90" // 東京リージョンのAmazon Linux
  instance_type = "t2.micro"
  subnet_id = aws_subnet.private.id
  associate_public_ip_address = false
  security_groups = [aws_security_group.web_sg.id]
  iam_instance_profile   = aws_iam_instance_profile.ssm_profile.name

  tags = {
  Name = "private-web-server"
  }
}
module内output.tf
output "ec2_public_ip" {
  value = aws_instance.web.public_ip
}
main.tfの作成
// /main.tf

// awsを使用してリージョンは東京を使用
provider "aws" {
  region = "ap-northeast-1"
}


module "network" {
  source             = "./modules/network"
  vpc_cidr_block     = "10.0.0.0/16"
  public_subnet_cidr = "10.0.1.0/24"
  private_subnet_cidr = "10.0.101.0/24"
}
ルート内のoutput.tf
output "ec2_public_ip" {
  value = module.network.ec2_public_ip
}
2つのoutput.tf ・ ec2を作成する際に、自動でパブリックサブIPが割り当てられるようになっている ・ モジュール内のoutput.tfで先ほどのパブリックIPを外部に公開する ・ ルート内main.tfでモジュールを呼び出す ・ルート内output.tfでモジュールから受け取った値を再出力

モジュール内とルートモジュールで output.tf を分けることで、構成の責務が明確になります。

コードの記述が完了したら、実際にAWS上に作成していきます
terraform init
// 最初の一回だけ初期化を行います

terraform plan
// 記述したものでどのようなリソースが作成されるか確認します

terraform apply
// 記述したものを実際に作成します

terraform destroy
// EC2やElastic IPなど、料金が発生するリソースも含まれるため、不要になったら terraform destroy で確実に削除することをおすすめします。
applyしてからの流れ
main.tf → modules/network/
  ├── variables.tf
  ├── vpc.tf
  ├── subnet.tf
  ├── igw.tf
  ├── route_table.tf
  ├── route_table_association.tf
  ├── key_pair.tf
  ├── security_group.tf
  ├── ec2.tf
  └── output.tf
↓
output.tf(ルート)
  • Terraformではまずmain.tfを読み込み、providerのaws の設定とmoduleのnetwork の呼び出します
  • 次にsource = "./modules/network" により、モジュールディレクトリの読み込みが始まります
感想

まだまだ改善できる部分はあると思いますが、まずはこの構成でTerraformによるネットワークの基礎を押さえることができました。ここから先は、用途に応じて少しずつカスタマイズしていきたいと思います。

次は、private subnetからの外部通信(NAT Gateway構成)について行っていきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?