Terraform による簡易検証環境テンプレートの紹介

Terraform による簡易検証環境テンプレートの紹介

2025.07.31

こんにちは!コンサルティング部のくろすけです!

AWS での検証作業において、迅速に環境構築とスクラップ・アンド・ビルドを行いたいという場面が多々あります。
そこで今回は、私が普段使用している簡単な検証環境構築用の Terraform コードをご紹介します。
私は特にネットワーク関連の簡単な検証を行う際にこのコードを使用しています。

目次

概要

今回ご紹介するは、以下の要素で構成された AWS 検証環境用の Terraform コードです

  • VPC: パブリック・プライベートサブネットを持つ基本的なネットワーク構成
  • SSM VPC エンドポイント: NAT Gateway の代わりに AWS Systems Manager 経由でインスタンスアクセス
  • EC2 インスタンス: プライベートサブネット内に配置、Session Manager でアクセス可能

構成

アーキテクチャ構成

VPC
├── パブリックサブネット
│   ├── ap-northeast-1a
│   └── ap-northeast-1c
├── プライベートサブネット
│   ├── ap-northeast-1a ← EC2 配置
│   └── ap-northeast-1c
└── VPC エンドポイント (Interface型)
    ├── com.amazonaws.ap-northeast-1.ssm
    ├── com.amazonaws.ap-northeast-1.ssmmessages
    └── com.amazonaws.ap-northeast-1.ec2messages

特徴

この構成には以下のような特徴があります

  • 検証に必要な最小構成でコストを抑制
    • お高めなNAT Gatewayを使用せず、VPCエンドポイントを使用
  • EC2インスタンスは完全にプライベートサブネット内に配置
    • VPNなどの閉域網の疎通確認用にプライベートサブネットに配置
  • SSMセッションマネージャーによるアクセスの簡易化

※ モジュールは Terraform Registry のものだと variables.tf がちょっと気に入らなかったので自作しています(個人の感想です)

Terraform コードの詳細

ディレクトリ構成

classmethod/infra/
├── services/
│   └── vpc-ssmvep-ec2/${ENV}/      # 実行環境
│       ├── providers.tf            # AWSプロバイダーの設定
│       ├── variables.tf            # 入力変数の定義
│       ├── terraform.tfvars        # 変数の実際の値
│       ├── vpc_ssmvep.tf           # VPCとSSM VPCエンドポイントの定義
│       └── single_ec2.tf           # EC2インスタンスとセキュリティグループの定義
└── modules/                        # 再利用可能なモジュール群
    ├── vpc/                        # VPCモジュール
    │   ├── main.tf                 # VPC、サブネット、ルートテーブルの定義
    │   ├── variables.tf            # VPC関連の変数定義
    │   └── outputs.tf              # VPC ID、サブネット情報などの出力
    ├── vpc-endpoint/               # VPCエンドポイントモジュール
    │   ├── main.tf                 # VPCエンドポイントとセキュリティグループの定義
    │   ├── variables.tf            # エンドポイント関連の変数定義
    │   └── outputs.tf              # エンドポイント情報の出力
    └── single-ec2/                 # EC2インスタンスモジュール
        ├── main.tf                 # EC2インスタンス、IAMロール、SGの定義
        ├── variables.tf            # EC2関連の変数定義
        └── outputs.tf              # インスタンス情報の出力

モジュールを modules/ ディレクトリに配置し、実際の環境構築用のコードを services/vpc-ssmvep-ec2/${ENV}/ に配置しています。各モジュールの役割は以下の通りです

各モジュールの役割

  • vpcモジュール: VPC、サブネット、ルートテーブル、インターネットゲートウェイを一括で作成
  • vpc-endpointモジュール: Interface型VPCエンドポイントとその専用セキュリティグループを作成
  • single-ec2モジュール: EC2インスタンス、IAMロール(SSM用)、セキュリティグループを作成

vpcモジュール

main.tf
################################################################################
# VPC                                                                          #
################################################################################
resource "aws_vpc" "common" {
  assign_generated_ipv6_cidr_block     = var.assign_generated_ipv6_cidr_block
  cidr_block                           = var.cidr_block
  enable_dns_hostnames                 = var.enable_dns_hostnames
  enable_dns_support                   = var.enable_dns_support
  enable_network_address_usage_metrics = var.enable_network_address_usage_metrics
  instance_tenancy                     = var.instance_tenancy
  ipv4_ipam_pool_id                    = var.ipv4_ipam_pool_id
  ipv4_netmask_length                  = var.ipv4_netmask_length
  ipv6_cidr_block                      = var.ipv6_cidr_block
  ipv6_cidr_block_network_border_group = var.ipv6_cidr_block_network_border_group
  ipv6_ipam_pool_id                    = var.ipv6_ipam_pool_id
  ipv6_netmask_length                  = var.ipv6_netmask_length

  tags = {
    Name   = var.name
    Module = "vpc"
    Env    = var.env
  }
}

################################################################################
# Internet Gateway                                                             #
################################################################################
resource "aws_internet_gateway" "common" {
  vpc_id = aws_vpc.common.id

  tags = {
    Name   = var.igw.name
    Module = "vpc"
    Env    = var.env
  }
}

################################################################################
# Public Subnet                                                                #
################################################################################
resource "aws_subnet" "public" {
  for_each                                       = var.public_subnets
  assign_ipv6_address_on_creation                = each.value.assign_ipv6_address_on_creation
  availability_zone                              = each.value.availability_zone
  cidr_block                                     = each.value.cidr_block
  customer_owned_ipv4_pool                       = each.value.customer_owned_ipv4_pool
  enable_dns64                                   = each.value.enable_dns64
  enable_lni_at_device_index                     = each.value.enable_lni_at_device_index
  enable_resource_name_dns_aaaa_record_on_launch = each.value.enable_resource_name_dns_aaaa_record_on_launch
  enable_resource_name_dns_a_record_on_launch    = each.value.enable_resource_name_dns_a_record_on_launch
  ipv6_cidr_block                                = each.value.ipv6_cidr_block
  ipv6_native                                    = each.value.ipv6_native
  map_customer_owned_ip_on_launch                = each.value.map_customer_owned_ip_on_launch
  map_public_ip_on_launch                        = each.value.map_public_ip_on_launch
  outpost_arn                                    = each.value.outpost_arn
  private_dns_hostname_type_on_launch            = each.value.private_dns_hostname_type_on_launch
  vpc_id                                         = aws_vpc.common.id

  tags = {
    Name   = each.value.name
    Module = "vpc"
    Env    = var.env
  }
}

resource "aws_route_table" "public" {
  vpc_id           = aws_vpc.common.id
  propagating_vgws = var.public_subnets_route_table.propagating_vgws

  tags = {
    Name   = var.public_subnets_route_table.name
    Module = "vpc"
    Env    = var.env
  }
}

resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.common.id
}

resource "aws_route_table_association" "public" {
  for_each       = aws_subnet.public
  route_table_id = aws_route_table.public.id
  subnet_id      = aws_subnet.public[each.key].id
}

################################################################################
# Private Subnet                                                               #
################################################################################
resource "aws_subnet" "private" {
  for_each                                       = var.private_subnets
  assign_ipv6_address_on_creation                = each.value.assign_ipv6_address_on_creation
  availability_zone                              = each.value.availability_zone
  cidr_block                                     = each.value.cidr_block
  customer_owned_ipv4_pool                       = each.value.customer_owned_ipv4_pool
  enable_dns64                                   = each.value.enable_dns64
  enable_lni_at_device_index                     = each.value.enable_lni_at_device_index
  enable_resource_name_dns_aaaa_record_on_launch = each.value.enable_resource_name_dns_aaaa_record_on_launch
  enable_resource_name_dns_a_record_on_launch    = each.value.enable_resource_name_dns_a_record_on_launch
  ipv6_cidr_block                                = each.value.ipv6_cidr_block
  ipv6_native                                    = each.value.ipv6_native
  map_customer_owned_ip_on_launch                = each.value.map_customer_owned_ip_on_launch
  map_public_ip_on_launch                        = each.value.map_public_ip_on_launch
  outpost_arn                                    = each.value.outpost_arn
  private_dns_hostname_type_on_launch            = each.value.private_dns_hostname_type_on_launch
  vpc_id                                         = aws_vpc.common.id

  tags = {
    Name   = each.value.name
    Module = "vpc"
    Env    = var.env
  }
}

resource "aws_route_table" "private" {
  for_each         = var.private_subnets_route_tables
  vpc_id           = aws_vpc.common.id
  propagating_vgws = each.value.propagating_vgws

  tags = {
    Name   = each.value.name
    Module = "vpc"
    Env    = var.env
  }
}

resource "aws_route_table_association" "private" {
  for_each       = var.private_subnets
  route_table_id = aws_route_table.private[each.key].id
  subnet_id      = aws_subnet.private[each.key].id
}
variables.tf
################################################################################
# VPC                                                                          #
################################################################################
variable "name" {
  description = "The name of the VPC"
  type        = string
}

variable "assign_generated_ipv6_cidr_block" {
  description = "A boolean flag to enable/disable the assignment of an IPv6 CIDR block"
  type        = bool
  default     = null
}

variable "cidr_block" {
  description = "The CIDR block for the VPC"
  type        = string
  default     = null
}

variable "enable_dns_hostnames" {
  description = "A boolean flag to enable/disable DNS hostnames in the VPC"
  type        = bool
  default     = true
}

variable "enable_dns_support" {
  description = "A boolean flag to enable/disable DNS support in the VPC"
  type        = bool
  default     = null
}

variable "enable_network_address_usage_metrics" {
  description = "A boolean flag to enable/disable network address usage metrics in the VPC"
  type        = bool
  default     = null
}

variable "instance_tenancy" {
  description = "The tenancy of instances launched into the VPC"
  type        = string
  default     = null
}

variable "ipv4_ipam_pool_id" {
  description = "The ID of the IPv4 IPAM pool"
  type        = string
  default     = null
}

variable "ipv4_netmask_length" {
  description = "The netmask length for the IPv4 CIDR block"
  type        = number
  default     = null
}

variable "ipv6_cidr_block" {
  description = "The IPv6 CIDR block"
  type        = string
  default     = null
}

variable "ipv6_cidr_block_network_border_group" {
  description = "The network border group for the IPv6 CIDR block"
  type        = string
  default     = null
}

variable "ipv6_ipam_pool_id" {
  description = "The ID of the IPv6 IPAM pool"
  type        = string
  default     = null
}

variable "ipv6_netmask_length" {
  description = "The netmask length for the IPv6 CIDR block"
  type        = number
  default     = null
}

################################################################################
# Internet Gateway                                                             #
################################################################################
variable "igw" {
  description = "The Internet Gateway"
  type = object({
    name = string
  })
}

################################################################################
# Public Subnet                                                                #
################################################################################
variable "public_subnets" {
  description = "The public subnets"
  type = map(object({
    name                                           = string
    assign_ipv6_address_on_creation                = optional(bool, null)
    availability_zone                              = string
    cidr_block                                     = string
    customer_owned_ipv4_pool                       = optional(string, null)
    enable_dns64                                   = optional(bool, null)
    enable_lni_at_device_index                     = optional(number, null)
    enable_resource_name_dns_aaaa_record_on_launch = optional(bool, null)
    enable_resource_name_dns_a_record_on_launch    = optional(bool, null)
    ipv6_cidr_block                                = optional(string, null)
    ipv6_native                                    = optional(bool, null)
    map_customer_owned_ip_on_launch                = optional(bool, null)
    map_public_ip_on_launch                        = optional(bool, null)
    outpost_arn                                    = optional(string, null)
    private_dns_hostname_type_on_launch            = optional(string, null)
  }))

  validation {
    condition     = length(keys(var.public_subnets)) > 0
    error_message = "At least one public subnet must be defined"
  }
  validation {
    condition = alltrue([
      for key in keys(var.public_subnets) : can(regex("pbsb_[a-d]", key))
    ])
    error_message = "The public subnets must be key prefixed with 'pbsb_' followed by a letter between 'a' and 'd'"
  }
}

variable "public_subnets_route_table" {
  description = "The route table"
  type = object({
    name             = string
    propagating_vgws = optional(list(string), null)
  })
}

################################################################################
# Private Subnet                                                               #
################################################################################
variable "private_subnets" {
  description = "The private subnets"
  type = map(object({
    name                                           = string
    assign_ipv6_address_on_creation                = optional(bool, null)
    availability_zone                              = string
    cidr_block                                     = string
    customer_owned_ipv4_pool                       = optional(string, null)
    enable_dns64                                   = optional(bool, null)
    enable_lni_at_device_index                     = optional(number, null)
    enable_resource_name_dns_aaaa_record_on_launch = optional(bool, null)
    enable_resource_name_dns_a_record_on_launch    = optional(bool, null)
    ipv6_cidr_block                                = optional(string, null)
    ipv6_native                                    = optional(bool, null)
    map_customer_owned_ip_on_launch                = optional(bool, null)
    map_public_ip_on_launch                        = optional(bool, null)
    outpost_arn                                    = optional(string, null)
    private_dns_hostname_type_on_launch            = optional(string, null)
  }))

  validation {
    condition     = length(keys(var.private_subnets)) > 0
    error_message = "At least one private subnet must be defined"
  }
  validation {
    condition = alltrue([
      for key in keys(var.private_subnets) : can(regex("pvsb_[a-d]", key))
    ])
    error_message = "The private subnets must be key prefixed with 'pvsb_' followed by a letter between 'a' and 'd'"
  }
}

variable "private_subnets_route_tables" {
  description = "The route table"
  type = map(object({
    name             = string
    propagating_vgws = optional(list(string), null)
  }))
}

################################################################################
# Others                                                                       #
################################################################################
variable "env" {
  description = "The environment"
  type        = string
  default     = "dev"
}
outputs.tf
output "vpc" {
  description = "The VPC"
  value       = aws_vpc.common
}

output "igw_id" {
  description = "The ID of the Internet Gateway"
  value       = aws_internet_gateway.common.id
}

output "public_subnets" {
  description = "The public subnets"
  value       = aws_subnet.public
}

output "private_subnets" {
  description = "The private subnets"
  value       = aws_subnet.private
}

vpc-endpointモジュール

main.tf
################################################################################
# VPC Endpoint                                                                 #
################################################################################
resource "aws_vpc_endpoint" "common" {
  vpc_id = var.vpc_id

  auto_accept         = var.auto_accept
  policy              = var.policy
  private_dns_enabled = var.private_dns_enabled
  ip_address_type     = var.ip_address_type
  route_table_ids     = var.route_table_ids
  security_group_ids  = [aws_security_group.vep_sg.id]
  service_name        = var.service_name
  subnet_ids          = var.subnet_ids
  vpc_endpoint_type   = var.vpc_endpoint_type

  tags = {
    Name   = var.vpc_endpoint_name
    Module = "vpc-endpoint"
    Env    = var.env
  }
}

resource "aws_security_group" "vep_sg" {
  name        = var.vep_sg_name
  description = var.vep_sg_description
  vpc_id      = var.vpc_id

  tags = {
    Name   = var.vep_sg_name
    Module = "vpc-endpoint"
    Env    = var.env
  }
}

resource "aws_security_group_rule" "vep_ingress" {
  cidr_blocks       = [var.vpc_cidr_block]
  type              = "ingress"
  from_port         = 443
  to_port           = 443
  security_group_id = aws_security_group.vep_sg.id
  protocol          = "tcp"
}

resource "aws_security_group_rule" "vep_egress" {
  cidr_blocks       = ["0.0.0.0/0"]
  type              = "egress"
  from_port         = 0
  to_port           = 0
  security_group_id = aws_security_group.vep_sg.id
  protocol          = -1
}
variables.tf
################################################################################
# VPC Endpoint Variables                                                       #
################################################################################
variable "vpc_endpoint_name" {
  description = "The name of the VPC endpoint"
  type        = string
}

variable "vpc_id" {
  description = "The ID of the VPC"
  type        = string
}

variable "auto_accept" {
  description = "Whether the VPC endpoint is automatically accepted"
  type        = bool
  default     = null
}

variable "policy" {
  description = "The policy document for the VPC endpoint"
  type        = string
  default     = null
}

variable "private_dns_enabled" {
  description = "Whether private DNS is enabled for the VPC endpoint"
  type        = bool
  default     = false
}

variable "ip_address_type" {
  description = "The IP address type for the VPC endpoint"
  type        = string
  default     = "ipv4"
}

variable "route_table_ids" {
  description = "The IDs of the route tables associated with the VPC endpoint"
  type        = list(string)
  default     = []
}

variable "service_name" {
  description = "The name of the service for the VPC endpoint"
  type        = string
}

variable "subnet_ids" {
  description = "The IDs of the subnets associated with the VPC endpoint"
  type        = list(string)
  default     = []
}

variable "vpc_endpoint_type" {
  description = "The type of the VPC endpoint"
  type        = string
  default     = "Interface"
}

variable "vep_sg_name" {
  description = "The name of the security group for the VPC endpoint"
  type        = string
}

variable "vep_sg_description" {
  description = "The description of the security group for the VPC endpoint"
  type        = string
}

variable "vpc_cidr_block" {
  description = "The CIDR block of the VPC"
  type        = string
}

variable "env" {
  description = "The environment"
  type        = string
  default     = "dev"
}
outputs.tf
# 現在は空ファイル

single-ec2モジュール

main.tf
################################################################################
# EC2                                                                          #
################################################################################
resource "aws_security_group" "ec2" {
  name                   = var.sg_name
  name_prefix            = var.sg_name_prefix
  description            = var.sg_description
  revoke_rules_on_delete = var.sg_revoke_rules_on_delete
  vpc_id                 = var.sg_vpc_id

  tags = {
    Name   = var.sg_name
    Module = "single-ec2"
  }
}

resource "aws_instance" "ec2" {
  ami                         = var.ec2_ami
  associate_public_ip_address = var.ec2_associate_public_ip_address
  availability_zone           = var.ec2_availability_zone
  iam_instance_profile        = aws_iam_instance_profile.ec2.name
  instance_type               = var.ec2_instance_type
  subnet_id                   = var.ec2_subnet_id
  vpc_security_group_ids      = [aws_security_group.ec2.id]

  tags = {
    Name   = var.ec2_name
    Module = "single-ec2"
  }
}

################################################################################
# IAM                                                                          #
################################################################################
resource "aws_iam_role" "ec2" {
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
  description        = var.iam_role_description
  name               = var.iam_role_name

  tags = {
    Name   = var.iam_role_name
    Module = "single-ec2"
  }
}

data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy_attachment" "ec2_ssm" {
  role       = aws_iam_role.ec2.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_iam_role_policy_attachment" "ec2_cloudwatch" {
  role       = aws_iam_role.ec2.name
  policy_arn = "arn:aws:iam::aws:policy/CloudWatchFullAccessV2"
}

resource "aws_iam_instance_profile" "ec2" {
  name = "${var.iam_role_name}-instance-profile"
  role = aws_iam_role.ec2.name

  tags = {
    Name   = "${var.iam_role_name}-instance-profile"
    Module = "single-ec2"
  }
}
variables.tf
################################################################################
# EC2                                                                          #
################################################################################
variable "sg_name" {
  description = "The name of the security group"
  type        = string
}

variable "sg_name_prefix" {
  description = "The name prefix of the security group"
  type        = string
  default     = null
}

variable "sg_description" {
  description = "The description of the security group"
  type        = string
  default     = null
}

variable "sg_revoke_rules_on_delete" {
  description = "A boolean flag to revoke rules on delete"
  type        = bool
  default     = null
}

variable "sg_vpc_id" {
  description = "The ID of the VPC"
  type        = string
}

variable "ec2_name" {
  description = "The name of the EC2 instance"
  type        = string
}

variable "ec2_ami" {
  description = "The AMI of the EC2 instance"
  type        = string
  default     = "ami-0a6fd4c92fc6ed7d5" # Amazon Linux 2023
}

variable "ec2_associate_public_ip_address" {
  description = "A boolean flag to associate a public IP address"
  type        = bool
  default     = null
}

variable "ec2_availability_zone" {
  description = "The availability zone of the EC2 instance"
  type        = string
}

variable "ec2_instance_type" {
  description = "The instance type of the EC2 instance"
  type        = string
  default     = "t2.micro"
}

variable "ec2_subnet_id" {
  description = "The ID of the subnet"
  type        = string
}

################################################################################
# IAM                                                                          #
################################################################################
variable "iam_role_description" {
  description = "The description of the IAM role"
  type        = string
  default     = null
}

variable "iam_role_name" {
  description = "The name of the IAM role"
  type        = string
}
outputs.tf
output "security_group" {
  description = "The ID of the security group"
  value       = aws_security_group.ec2
}

output "instance" {
  description = "The ID of the EC2 instance"
  value       = aws_instance.ec2
}

output "iam_role" {
  description = "The Arn of the IAM role"
  value       = aws_iam_role.ec2
}

実際の環境構築用のコード

vpc_ssmvep.tf
module "vpc" {
  source     = "../../../modules/vpc"
  name       = "${var.sys_name}-${var.env}-vpc"
  cidr_block = var.vpc_cidr_block

  igw = {
    name = "${var.sys_name}-${var.env}-igw"
  }

  public_subnets = {
    pbsb_a = {
      name              = "${var.sys_name}-${var.env}-pbsb-a"
      cidr_block        = var.pbsb_a_cidr_block
      availability_zone = "ap-northeast-1a"
    },
    pbsb_c = {
      name              = "${var.sys_name}-${var.env}-pbsb-c"
      cidr_block        = var.pbsb_c_cidr_block
      availability_zone = "ap-northeast-1c"
    }
  }
  public_subnets_route_table = {
    name = "${var.sys_name}-${var.env}-public-rtb"
  }

  private_subnets = {
    pvsb_a = {
      name              = "${var.sys_name}-${var.env}-pvsb-a"
      cidr_block        = var.pvsb_a_cidr_block
      availability_zone = "ap-northeast-1a"
    },
    pvsb_c = {
      name              = "${var.sys_name}-${var.env}-pvsb-c"
      cidr_block        = var.pvsb_c_cidr_block
      availability_zone = "ap-northeast-1c"
    }
  }
  private_subnets_route_tables = {
    pvsb_a = {
      name = "${var.sys_name}-${var.env}-pvsb-a-rtb"
    },
    pvsb_c = {
      name = "${var.sys_name}-${var.env}-pvsb-c-rtb"
    }
  }

  env = var.env
}

module "ssm_vpc_endpoint" {
  source              = "../../../modules/vpc-endpoint"
  vpc_endpoint_name   = "${var.sys_name}-${var.env}-ssm-vep"
  vpc_id              = module.vpc.vpc.id
  service_name        = "com.amazonaws.ap-northeast-1.ssm"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = values(module.vpc.private_subnets)[*].id
  private_dns_enabled = true
  vep_sg_name         = "${var.sys_name}-${var.env}-ssm-vep-sg"
  vep_sg_description  = "Security group for SSM endpoint ${var.sys_name}-${var.env}-ssm-vep"
  vpc_cidr_block      = module.vpc.vpc.cidr_block
  env                 = var.env
}

module "ssmmsg_vpc_endpoint" {
  source              = "../../../modules/vpc-endpoint"
  vpc_endpoint_name   = "${var.sys_name}-${var.env}-ssmmsg-vep"
  vpc_id              = module.vpc.vpc.id
  service_name        = "com.amazonaws.ap-northeast-1.ssmmessages"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = values(module.vpc.private_subnets)[*].id
  private_dns_enabled = true
  vep_sg_name         = "${var.sys_name}-${var.env}-ssmmsg-vep-sg"
  vep_sg_description  = "Security group for SSM messages endpoint ${var.sys_name}-${var.env}-ssmmsg-vep"
  vpc_cidr_block      = module.vpc.vpc.cidr_block
  env                 = var.env
}

module "ec2msg_vpc_endpoint" {
  source              = "../../../modules/vpc-endpoint"
  vpc_endpoint_name   = "${var.sys_name}-${var.env}-ec2msg-vep"
  vpc_id              = module.vpc.vpc.id
  service_name        = "com.amazonaws.ap-northeast-1.ec2messages"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = values(module.vpc.private_subnets)[*].id
  private_dns_enabled = true
  vep_sg_name         = "${var.sys_name}-${var.env}-ec2msg-vep-sg"
  vep_sg_description  = "Security group for EC2 messages endpoint ${var.sys_name}-${var.env}-ec2msg-vep"
  vpc_cidr_block      = module.vpc.vpc.cidr_block
  env                 = var.env
}
single_ec2.tf
module "ec2" {
  source                          = "../../../modules/single-ec2"
  sg_name                         = "${var.sys_name}-${var.env}-ec2-sg"
  sg_description                  = "Security group for ec2 ${var.sys_name}-${var.env}-ec2"
  sg_vpc_id                       = module.vpc.vpc.id
  ec2_name                        = "${var.sys_name}-${var.env}-ec2"
  ec2_instance_type               = "t2.micro"
  ec2_subnet_id                   = module.vpc.private_subnets.pvsb_a.id
  ec2_availability_zone           = module.vpc.private_subnets.pvsb_a.availability_zone
  ec2_associate_public_ip_address = false
  iam_role_name                   = "${var.sys_name}-${var.env}-ec2-role"
  iam_role_description            = "IAM role for ${var.sys_name}-${var.env}-ec2"
}

resource "aws_security_group_rule" "ec2_icmp_ingress" {
  cidr_blocks       = [module.vpc.vpc.cidr_block]
  type              = "ingress"
  from_port         = -1
  to_port           = -1
  security_group_id = module.ec2.security_group.id
  protocol          = "icmp"
}

resource "aws_security_group_rule" "ec2_egress" {
  cidr_blocks       = ["0.0.0.0/0"]
  type              = "egress"
  from_port         = 0
  to_port           = 0
  security_group_id = module.ec2.security_group.id
  protocol          = "-1"
}
variables.tf
variable "sys_name" {
  description = "The system name"
  type        = string
}

variable "vpc_cidr_block" {
  description = "The CIDR block for the VPC"
  type        = string
}

variable "pbsb_a_cidr_block" {
  description = "The CIDR block for the public subnet a"
  type        = string
}

variable "pbsb_c_cidr_block" {
  description = "The CIDR block for the public subnet c"
  type        = string
}

variable "pvsb_a_cidr_block" {
  description = "The CIDR block for the private subnet a"
  type        = string
}

variable "pvsb_c_cidr_block" {
  description = "The CIDR block for the private subnet c"
  type        = string
}

variable "env" {
  description = "The environment"
  type        = string
}

使用方法

1. 変数設定 (参考)

sys_name = "vpc-ssmvep-ec2"

vpc_cidr_block    = "172.16.0.0/16"
pbsb_a_cidr_block = "172.16.0.0/24"
pbsb_c_cidr_block = "172.16.1.0/24"
pvsb_a_cidr_block = "172.16.16.0/24"
pvsb_c_cidr_block = "172.16.17.0/24"

env = "${ENV}"

2. デプロイ実行

terraform init
terraform plan
terraform apply -auto-approve

3. EC2 インスタンスへの接続

デプロイ完了後、AWS コンソールの Systems Manager > Session Manager から、作成された EC2 インスタンスに直接接続できます。

あとがき

今回のような構成パターンを Terraform モジュールとして標準化しておくことで、検証作業の立ち上げスピードが格段に向上します!
皆さんも必要があれば、自分なりの検証環境テンプレートを作ってみてください!

以上、くろすけでした!

この記事をシェアする

facebookのロゴhatenaのロゴtwitterのロゴ

© Classmethod, Inc. All rights reserved.