パーソル&サーバーワークス

ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

【Terraform】EC2をプライベートサブネットに構築&NATゲートウェイでインターネット通信

この記事を共有する

目次

はじめに

皆さんこんにちは!パーソル&サーバーワークスの榎本です。
今回はプライベートサブネットにEC2を構築し、パブリックサブネットにNATゲートウェイを構築することでEC2がNATゲートウェイ経由でインターネット接続できる環境をTerraformで構築しましたのでそのコードや手順を整理しました。

本ハンズオンの目的

プライベートサブネットにEC2を構築し、NATゲートウェイ経由でインターネットに接続できる構成をTerraformで構築できるようになること

前提

  • 構築用のEC2にTerraformインストール済み
  • 構築対象のEC2はWebサーバーを想定して作成し、構築時にApacheをインストールする
  • AmazonSSMManagedInstanceCoreポリシーが許可されているIAMロール(本ハンズオンではterraform-handson-iamroleという名前)を事前作成

本ハンズオン概要

  • Terraformのコードを記載し、以下構成図のようなVPC、EC2、NATゲートウェイをTerraformで構築する
  • 最終的にはEC2とNATゲートウェイが構築できて、SSMセッションマネージャー経由でEC2にログインし、インターネット接続ができることを確認する

構成図

2層構造NATゲートウェイ版.png

構築環境

  • AWS
  • 東京リージョン(ap-northeast-1)
  • AvailabilityZone(ap-northeast-1a、ap-northeast-1c)

構築対象

  • VPC ×1
  • EC2 ×2(プライベートサブネットの各AZに1つずつ)
  • EC2用セキュリティグループ ×1
  • NATゲートウェイ ×2(パブリックサブネットの各AZに1つずつ)
  • Elastic IP ×4(各AZのNATゲートウェイ、EC2に1つずつ)
  • IAMインスタンスプロファイル ×1

ハンズオン手順

1. 構築用のEC2にログインし、以下コマンドで作業用ディレクトリに移動する

# terraform/handsonディレクトリに移動
cd terraform/handson/

2. 移動したディレクトリ配下に、構築に必要なファイルを作成する

# provider.tfファイルを新規作成
touch provider.tf
# vpc.tfファイルを新規作成
touch vpc.tf
# ec2.tfファイルを新規作成
touch ec2.tf

3. 作成したprovider.tfファイル内に以下記載して保存する

# プロバイダー指定 AWSの東京リージョンを使用することを定義
provider "aws" {
  region = "ap-northeast-1"
}

4. 作成したvpc.tfファイルに以下記載して保存する

# VPC作成
resource "aws_vpc" "main_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name = "terraform-handson-vpc"
  }
}
# インターネットゲートウェイ作成
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main_vpc.id
  tags = {
    Name = "terraform-handson-igw"
  }
}
# NATゲートウェイElasticIP作成
resource "aws_eip" "nat_eip" {
  domain = "vpc"
  tags = {
    Name = "terraform-handson-ngw-ip"
  }
}
# NATゲートウェイ作成
resource "aws_nat_gateway" "ngw" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = aws_subnet.public_subnet_a.id
  tags = {
    Name = "terraform-handson-ngw"
  }
}
# パブリックサブネットa作成 
resource "aws_subnet" "public_subnet_a" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.0.0/24"
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "terraform-handson-public-subnet-a"
  }
}
# パブリックサブネットc作成
resource "aws_subnet" "public_subnet_c" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-northeast-1c"
  tags = {
    Name = "terraform-handson-public-subnet-c"
  }
}
# プライベートサブネットa作成
resource "aws_subnet" "private_subnet_a" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.10.0/24"
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "terraform-handson-private-subnet-a"
  }
}
# プライベートサブネットc作成
resource "aws_subnet" "private_subnet_c" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.11.0/24"
  availability_zone = "ap-northeast-1c"
  tags = {
    Name = "terraform-handson-private-subnet-c"
  }
}
# パブリックルートテーブル作成
resource "aws_route_table" "route_table_public" {
  vpc_id = aws_vpc.main_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }
  tags = {
    Name = "terraform-handson-public-rt"
  }
}
# プライベートルートテーブル作成
resource "aws_route_table" "route_table_private" {
  vpc_id = aws_vpc.main_vpc.id
  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.ngw.id
  }
  tags = {
    Name = "terraform-handson-private-rt"
  }
}
# パブリックルートテーブルa関連付け
resource "aws_route_table_association" "route_table_association_public_a" {
  route_table_id = aws_route_table.route_table_public.id
  subnet_id      = aws_subnet.public_subnet_a.id
}
# パブリックルートテーブルc関連付け
resource "aws_route_table_association" "route_table_association_public_c" {
  route_table_id = aws_route_table.route_table_public.id
  subnet_id      = aws_subnet.public_subnet_c.id
}
# プライベートルートテーブルa関連付け
resource "aws_route_table_association" "route_table_association_private_a" {
  route_table_id = aws_route_table.route_table_private.id
  subnet_id      = aws_subnet.private_subnet_a.id
}
# プライベートルートテーブルc関連付け
resource "aws_route_table_association" "route_table_association_private_c" {
  route_table_id = aws_route_table.route_table_private.id
  subnet_id      = aws_subnet.private_subnet_c.id
}

5. 作成したec2.tfファイル内に以下記載して保存する

# EC2作成(Webサーバー1)
resource "aws_instance" "web1" {
  ami                  = "ami-023ff3d4ab11b2525"
  instance_type        = "t3.micro"
  subnet_id            = aws_subnet.private_subnet_a.id
  security_groups      = [aws_security_group.web_sg.id]
  iam_instance_profile = aws_iam_instance_profile.instance_profile.name
  # ユーザーデータを指定
  user_data = <<-EOT
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "<h1>Welcome to my website!</h1>" > /var/www/html/index.html
  EOT
  tags = {
    Name = "terraform-handson-ec2-web1"
  }
}
# EC2作成(Webサーバー2)
resource "aws_instance" "web2" {
  ami                  = "ami-023ff3d4ab11b2525"
  instance_type        = "t3.micro"
  subnet_id            = aws_subnet.private_subnet_c.id
  security_groups      = [aws_security_group.web_sg.id]
  iam_instance_profile = aws_iam_instance_profile.instance_profile.name
  # ユーザーデータを指定
  user_data = <<-EOT
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "<h1>Welcome to my website!</h1>" > /var/www/html/index.html
  EOT
  tags = {
    Name = "terraform-handson-ec2-web2"
  }
}
# EC2用セキュリティグループ作成
resource "aws_security_group" "web_sg" {
  vpc_id = aws_vpc.main_vpc.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-handson-web-sg"
  }
}
# web1にElasticIP付与
resource "aws_eip" "web1_eip" {
  domain   = "vpc"
  instance = aws_instance.web1.id
}
# web2にElasticIP付与
resource "aws_eip" "web2_eip" {
  domain   = "vpc"
  instance = aws_instance.web2.id
}
# IAMインスタンスプロファイル作成(SSMセッションマネージャ接続のために必要) 
resource "aws_iam_instance_profile" "instance_profile" {
  name = "terraform-handson-instance-profile"
  role = "terraform-handson-iamrole"
}

6. 以下コマンドを順番に実行する

# 必要なモジュールをインストール
terraform init
# 実行内容を事前確認
terraform plan
# 構築実行
terraform apply

7. マネジメントコンソールを開き、EC2とNATゲートウェイが新規作成されていることを確認する

8. SSMセッションマネージャーを開き、EC2に接続できることを確認する

セッションマネージャー接続前画面.png

9. EC2で以下コマンドを実行し、インターネット接続できていることを確認する

#ec2-userにユーザー変更
sudo su - ec2-user
# Googleが提供するGoogle Public DNSのIPに対して疎通確認
ping 8.8.8.8

※確認でき次第[Ctrl+C]で疎通確認停止する

ping.png

10. 作成されていることを確認できたら、以下コマンドを実行して作成した環境を削除する

#環境を削除
terraform destroy

まとめ

マネジメントコンソールからEC2構築すると、どこかの設定を間違えてSSMセッションマネージャーでEC2に接続できないなどのミスが起きる可能性がありますが、Terraformで構築するとそのようなミスをする可能性が無く安心感があります!
設定ミスをして、原因を切り分けて解決する時間がないだけで心理的にもタイムパフォーマンス的にもTerraformは素晴らしいと改めて感じました!

この記事は私が書きました

榎本 将希

2024 Japan AWS All Certifications Engineers   サッカー観戦とサウナが好きです!   機械学習を勉強中です!

榎本 将希

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。