🌐
【Terraform】 VPC/EC2のよくある構成を作ってみた
前書き
今回はTerraformを使ってよくある以下の構成リソースを作ってみました。
TerraformのインストールやAWSのクレデンシャルの設定等は割愛しています。
もし設定されていない方は以下をご参照ください。
作ったファイルは以下の5ファイルです。
本当はsubnetとかroutetableもファイルとして分けたほうが良いのだけど横着して一緒に書いてますがご了承ください。
- backend.tf
a. tfのstateを置くバケットの記載 - main.tf
a. バージョンとかproviderの設定記載 - variable.tf
a. 各ファイルで使用する変数の設定記載 - ec2.tf
a. ec2とsecuritygroup等々の設定記載 - vpc.tf
a. vpcとかsubnetとかgateway周り等々の設定記載
backend.tf
もし東京リージョン使っていないよという方はregionもよしなに変更ください。
terraform {
backend "s3" {
bucket = "編集箇所:ここにtf.stateを配置したいバケット名。例)dev-tf-backend-ryuko"
key = "編集箇所:ここにtf.stateを配置したいキー名。例)dev/state"
region = "ap-northeast-1"
}
}
main.tf
ここは使用しているバージョンによって必要であれば変更します。
terraform {
// terraformのバージョンを指定
required_version = ">= 1.5.1"
// awsプロバイダーのバージョンを指定
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
}
// awsプロバイダーの設定
provider "aws" {
// regionを指定
region = "ap-northeast-1"
}
variable.tf
locals {
vpc_name = "編集箇所:VPCの名前"
vpc_cidr = {
dev = "10.0.0.0/16"
}
aws_id = "編集箇所:ここはAWSのアカウントID"
name_prefix = "編集箇所:各リソースにつけたいプレフィックスを指定"
region = "ap-northeast-1"
Environment = "編集箇所:devとかstgとかprodとか"
}
variable "private_subnet" {
description = "Parameter for private subnet"
type = string
default = "編集箇所:例)10.0.128.0/24"
}
variable "public_subnet" {
description = "Parameter for public subnet"
type = string
default = "編集箇所:例)10.0.127.0/24"
}
variable "default_instance_type" {
default = "t2.micro"
}
ec2.tf
####################
# 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.vpc.id
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [
"10.0.0.0/16"
]
}
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"
}
vpc.tf
####################
# vpc
####################
resource "aws_vpc" "vpc" {
cidr_block = local.vpc_cidr.dev
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = local.vpc_name
}
}
####################
# subnet
####################
# private作成
resource "aws_subnet" "private_1a" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.private_subnet
availability_zone = "ap-northeast-1a"
tags = {
Name = "${local.name_prefix}-${local.Environment}-private-1a"
}
}
# public作成
resource "aws_subnet" "public_1a" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.public_subnet
availability_zone = "ap-northeast-1a"
tags = {
Name = "${local.name_prefix}-${local.Environment}-public-1a"
}
}
####################
# route table
####################
# private_ルートテーブル作成
resource "aws_route_table" "private_1a" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${local.name_prefix}-${local.Environment}-private-1a"
}
}
# private_ルートテーブル紐づけ
resource "aws_route_table_association" "private_1a" {
subnet_id = aws_subnet.private_1a.id
route_table_id = aws_route_table.private_1a.id
}
# public_ルートテーブル作成
resource "aws_route_table" "public_1a" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${local.name_prefix}-${local.Environment}-public-1a"
}
}
# public_ルートテーブル紐づけ
resource "aws_route_table_association" "public_1a" {
subnet_id = aws_subnet.public_1a.id
route_table_id = aws_route_table.public_1a.id
}
# public subnetとinternet gatewayの紐づけ
resource "aws_route" "public_igw_a" {
route_table_id = aws_route_table.public_1a.id
gateway_id = aws_internet_gateway.main.id
destination_cidr_block = "0.0.0.0/0"
}
# private subnetとnat gatewayの紐づけ
resource "aws_route" "public_natgw_a" {
route_table_id = aws_route_table.private_1a.id
nat_gateway_id = aws_nat_gateway.nat_1a.id
destination_cidr_block = "0.0.0.0/0"
}
####################
# internet gateway
####################
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${local.name_prefix}-${local.Environment}-igw"
}
}
####################
# nat gateway
####################
# Elastic IP
resource "aws_eip" "nat_1a" {
vpc = true
tags = {
Name = "${local.name_prefix}-${local.Environment}-natgw-1a"
}
}
# NAT Gateway
resource "aws_nat_gateway" "nat_1a" {
subnet_id = aws_subnet.public_1a.id # NAT Gatewayを配置するSubnetを指定
allocation_id = aws_eip.nat_1a.id # 紐付けるElastic IP
tags = {
Name = "${local.name_prefix}-${local.Environment}-1a"
}
}
####################
# vpc endpoint
####################
resource "aws_vpc_endpoint" "ssm" {
vpc_id = aws_vpc.vpc.id
service_name = "com.amazonaws.${local.region}.ssm"
vpc_endpoint_type = "Interface"
security_group_ids = [aws_security_group.main.id]
subnet_ids = [aws_subnet.private_1a.id]
private_dns_enabled = true
tags = {
Name = "${local.name_prefix}-${local.Environment}-ssm"
}
}
resource "aws_vpc_endpoint" "ec2messages" {
vpc_id = aws_vpc.vpc.id
service_name = "com.amazonaws.${local.region}.ec2messages"
vpc_endpoint_type = "Interface"
security_group_ids = [aws_security_group.main.id]
subnet_ids = [aws_subnet.private_1a.id]
private_dns_enabled = true
tags = {
Name = "${local.name_prefix}-${local.Environment}-ec2messages"
}
}
resource "aws_vpc_endpoint" "ssmmessages" {
vpc_id = aws_vpc.vpc.id
service_name = "com.amazonaws.${local.region}.ssmmessages"
vpc_endpoint_type = "Interface"
security_group_ids = [aws_security_group.main.id]
subnet_ids = [aws_subnet.private_1a.id]
private_dns_enabled = true
tags = {
Name = "${local.name_prefix}-${local.Environment}-ssmmessages"
}
}
cidr_blockやsubnetのIPなどはもし自身の環境で他リソースに使用されていたら適宜変えてみてください。
terraform plan
で作成されるリソースを確認して terraform apply
してみるとリソースができます。
ちゃんと作れているかの確認としては、AWSコンソールで対象のEC2を開く→セッションマネージャーで接続してみてちゃんとつながることを確認→curl http://abehiroshi.la.coocan.jp/
とかでnatgateway経由でネットに繋がることを確認するで良いと思います。もちろんpingでも。
Discussion