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

【Terraform】VPCエンドポイント(インターフェース型)構築&SSMセッションマネージャーでEC2接続

この記事を共有する

目次

はじめに

皆さんこんにちは!パーソル&サーバーワークスの榎本です。
以前のブログではプライベートサブネットにEC2を構築、パブリックサブネットにNATゲートウェイを構築してEC2がNATゲートウェイ経由でインターネット接続できる環境をTerraformで構築しました。
今回はNATゲートウェイ経由ではなく、VPCエンドポイント(インターフェース型)経由でSystems Manager(以下、SSM)セッションマネージャーを使ってEC2に接続するためのコードや手順を整理しました。

本ハンズオンの目的

プライベートサブネットにあるEC2に対して、VPCエンドポイント(インターフェース型)経由でSSMセッションマネージャーを使用して接続できる構成をTerraformで構築できるようになること

前提

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

本ハンズオン概要

  • Terraformのコードを記載し、以下構成図のようにSSMセッションマネージャーからVPCエンドポイント経由でEC2に接続できる構成をTerraformで構築する

構成図

2層構造VPCエンドポイント版.png

構築環境

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

構築対象

  • VPC ×1
  • EC2 ×2(プライベートサブネットの各AZに1つずつ)
  • EC2用セキュリティグループ ×1
  • VPCエンドポイント ×2
  • IAMインスタンスプロファイル ×1

ハンズオン手順

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

# terraform-handson/vpceディレクトリ作成
mkdir -p terraform-handson/vpce
# terraform-handson/vpceディレクトリに移動
cd terraform-handson/vpce

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"
  }
}
# パブリックサブネット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
  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
}
# VPCエンドポイント用セキュリティグループ
resource "aws_security_group" "vpc_endpoint_sg" {
  name_prefix = "terraform-handson-ap1-vpce-sg"
  vpc_id      = aws_vpc.main_vpc.id
  ingress {
    from_port = 443
    to_port   = 443
    protocol  = "tcp"
    cidr_blocks = [
      "10.0.10.0/24",
      "10.0.11.0/24"
    ]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "terraform-handson-ap1-vpce-sg"
  }
}
# SSM用VPCエンドポイント(インターフェース型)
resource "aws_vpc_endpoint" "ssm_endpoint" {
  vpc_id              = aws_vpc.main_vpc.id
  service_name        = "com.amazonaws.ap-northeast-1.ssm"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.private_subnet_a.id, aws_subnet.private_subnet_c.id]
  security_group_ids  = [aws_security_group.vpc_endpoint_sg.id]
  private_dns_enabled = true
  tags = {
    Name = "terraform-handson-ap1-ssm-endpoint"
  }
}
# SSM Messages用VPCエンドポイント(インターフェース型)
resource "aws_vpc_endpoint" "ssmmessages_endpoint" {
  vpc_id              = aws_vpc.main_vpc.id
  service_name        = "com.amazonaws.ap-northeast-1.ssmmessages"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.private_subnet_a.id, aws_subnet.private_subnet_c.id]
  security_group_ids  = [aws_security_group.vpc_endpoint_sg.id]
  private_dns_enabled = true
  tags = {
    Name = "terraform-handson-ap1-ssmmessages-endpoint"
  }
}

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. マネジメントコンソールを開き、VPCエンドポイント(インターフェース型)が新規作成されていることを確認する

VPCエンドポイント作成確認.png

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

※作成してから接続できるようになるまで2分ほど時間がかかる可能性がありますので、
初めて開いた時に接続できなくても少し時間を空けて再度ご確認ください。

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

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

#環境を削除
terraform destroy

まとめ

NATゲートウェイは常時置いておく必要があり、コストが高くなる傾向にあります。
インターネット接続要件が無い場合や、コストを抑えたい場合などはVPCエンドポイント(インターフェース型)を使用することも選択肢となります。
ただVPCエンドポイント(インターフェース型)も場合によってはNATゲートウェイよりもコストが高くなりますので、ご注意ください。

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

榎本 将希

記事一覧

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

榎本 将希

この記事を共有する

クラウドのご相談

CONTACT

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

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

DOWNLOAD

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