【爆速】TerraformでプライベートサブネットのEC2へSession Managerからアクセス可能な環境を構築する: NAT Gateway編
はじめに
こんにちは、Shunです!
EC2を使った検証をする際に、プライベートサブネットにEC2を立てて、NATゲートウェイを作って、ルートテーブルを更新するなど、毎回環境を構築するのは面倒くさいですよね!
そこで、爆速かつセキュアにEC2を検証するTerraformテンプレートをご紹介します!
NATゲートウェイではなく、VPCエンドポイントを使った環境を作りたい方はこちら!
爆速で、CloudFront + S3の静的サイトホスティング環境を作りたい方はこちら!
構築するアーキテクチャ
今回、構築するシステム構成図です。
Session Managerからアクセスするために、Internet Gateway、NAT Gateway等を構築します。

terraformファイル構成
今回使用するtfファイルは以下の構成になっています。
├─ provider.tf ├─ vpc.tf └─ ec2.tf
1.providers.tf
locals内の変数を書き換えるだけで、利用可能です。
locals {
aws_id = "[アカウントID]"
name_prefix = "[名前]"
region = "[リージョン]"
Environment = "[環境名]"
}
terraform {
required_version = "~> 1.7.0"
backend "s3" {
key = "[S3のkey]"
bucket = "[バケット名]"
region = "[リージョン]"
}
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
variable "vpc" {
description = "Parameter for VPC"
type = string
default = "10.0.0.0/16"
}
variable "public_subnet" {
description = "Parameter for public subnet"
type = string
default = "10.0.0.0/24"
}
variable "private_subnet" {
description = "Parameter for private subnet"
type = string
default = "10.0.128.0/24"
}
variable "default_instance_type" {
default = "t2.micro"
}
2. vpc.tf
vpc.tfでは、3つのことを実施しています。
- VPC、サブネットなどネットワークの構築
- Internet GatewayとNAT Gatewayの作成
- Internet GatewayとNAT Gatewayへ疎通可能なルートテーブルの作成
####################
# vpc
####################
resource "aws_vpc" "main" {
cidr_block = var.vpc
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${local.name_prefix}-${local.Environment}-vpc"
}
}
####################
# subnet
####################
resource "aws_subnet" "public_1a" {
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet
availability_zone = "ap-northeast-1a"
tags = {
Name = "${local.name_prefix}-${local.Environment}-public-1a"
}
}
# プライベートサブネット作成
resource "aws_subnet" "private_1a" {
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet
availability_zone = "ap-northeast-1a"
tags = {
Name = "${local.name_prefix}-${local.Environment}-private-1a"
}
}
####################
# internet gateway
####################
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.name_prefix}-${local.Environment}-igw"
}
}
####################
# route table
####################
# public_ルートテーブル作成
resource "aws_route_table" "public_1a" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.name_prefix}-${local.Environment}-public-1a"
}
}
# private_ルートテーブル作成
resource "aws_route_table" "private_1a" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.name_prefix}-${local.Environment}-private-1a"
}
}
# public_ルート作成
resource "aws_route" "public_igw_1a" {
destination_cidr_block = "0.0.0.0/0"
route_table_id = aws_route_table.public_1a.id
gateway_id = aws_internet_gateway.main.id
}
# private_ルート作成
resource "aws_route" "nat_1a" {
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_1a.id
route_table_id = aws_route_table.private_1a.id
}
# public_ルートテーブル紐づけ
resource "aws_route_table_association" "public_1a" {
subnet_id = aws_subnet.public_1a.id
route_table_id = aws_route_table.public_1a.id
}
# private_ルートテーブル紐づけ
resource "aws_route_table_association" "private_1a" {
subnet_id = aws_subnet.private_1a.id
route_table_id = aws_route_table.private_1a.id
}
####################
# nat gateway
####################
# NATゲートウェイ(AZ-1a)に割り当てるEIPを作成
resource "aws_eip" "nat_1a" {
domain = "vpc"
tags = {
Name = "${local.name_prefix}-${local.Environment}-nat-1a"
}
}
# NATゲートウェイ(AZ-1a)作成
resource "aws_nat_gateway" "nat_1a" {
allocation_id = aws_eip.nat_1a.id
subnet_id = aws_subnet.public_1a.id
depends_on = [aws_internet_gateway.main]
tags = {
Name = "${local.name_prefix}-${local.Environment}-ngw-1a"
}
}
3. ec2.tf
ec2.tfでは、3つのことを実施しています。
- 最新のAmazon LinuxのAMIを取得し、EC2を構築
- インバウンドを許可しないセキュリティグループを作成
- Session Managerを使用するためのIAMを作成し、EC2へ付与
####################
# ami
####################
data "aws_ami" "latest_amazon_linux2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
}
####################
# ec2
####################
resource "aws_instance" "main" {
instance_type = var.default_instance_type
ami = data.aws_ami.latest_amazon_linux2.id
subnet_id = aws_subnet.private_1a.id
vpc_security_group_ids = [aws_security_group.main.id]
iam_instance_profile = aws_iam_instance_profile.example_profile.name
root_block_device {
volume_size = 8
volume_type = "gp3"
iops = 3000
throughput = 125
delete_on_termination = true
# EBSのNameタグ
tags = {
Name = "${local.name_prefix}-${local.Environment}"
}
}
lifecycle {
ignore_changes = [
ami,
]
}
tags = {
Name = "${local.name_prefix}-${local.Environment}"
}
}
####################
# security group
####################
resource "aws_security_group" "main" {
name = "${local.name_prefix}-${local.Environment}-sg"
vpc_id = aws_vpc.main.id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${local.name_prefix}-${local.Environment}-sg"
}
}
####################
# ec2 iam role
####################
# インスタンスプロファイルを作成
resource "aws_iam_instance_profile" "example_profile" {
name = "${local.name_prefix}-${local.Environment}-ssm"
role = aws_iam_role.ssm_role.name
}
resource "aws_iam_role" "ssm_role" {
name = "${local.name_prefix}-${local.Environment}-ssm"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
data "aws_iam_policy_document" "assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role_policy_attachment" "ssm_managed_instance_core" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
環境構築
今回は、CloudShellを用いて、Terraformを実行します。
CloudShellを開き、以下のコマンドを入力し、Terraformをインストールします。
$ cd ~ $ git clone https://github.com/tfutils/tfenv.git ~/.tfenv $ mkdir -p ~/.local/bin/ $ sudo ln -s ~/.tfenv/bin/* ~/.local/bin/ $ tfenv install 1.7.0 $ tfenv use 1.7.0
続いて、CloudShell内に適当なディレクトリを作成し、今回ご紹介したtfファイルを配置します。
作成したディクトリ配下へ移動し、以下のコマンドを入力します。
$ terraform init $ terraform fmt $ terraform plan
問題なければ、以下のコマンドを実行し、環境へデプロイします。
$ terraform apply
これで環境構築は完了です。
疎通確認
マネジメントコンソールからEC2の画面を開きます。
設定したインスタンスを選択し、セッションマネージャーから接続をします。

以下のように接続ができれば完了です!

さいごに
今回の記事では、プライベートサブネットのEC2へSession Managerからアクセス可能なTerraformテンプレートをご紹介しました!
このテンプレートを使用することで、爆速でセキュアな環境でEC2を利用することができます!
是非、テンプレートを活用し、セキュアなEC2ライフを送ってください!
最後まで読んでいただきありがとうございます!
Google Cloud Partner Top Engineer 2025、2024 AWS All Cert、ビール検定1冠
Recommends
こちらもおすすめ
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28

AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16


