Terraformで以下のような構成のVPCを作成します。
VPCのデフォルトのルートテーブル、ネットワークACL、DHCP オプションセット、セキュリティーグループを利用するようにしています。
ディレクトリ構成
-| environment
| |- dev
| |- main.tf
| |- provider.tf
|- modules
|- main.tf
|- data.tf
|- variables.tf
ソース
environment/dev/provider.tf
terraform {
required_version = "~> 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.8.0"
}
}
cloud {
organization = "urushibata-org"
workspaces {
name = "aws-develop-terraform"
}
}
}
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
ManagedBy = "terraform"
}
}
}
locals {
environment = "dev"
}
module "vpc" {
source = "../../modules/vpc"
environment = local.environment
vpc_cidr = "192.168.0.0/24"
}
# 現在のリージョンを取得します。
data "aws_region" "current" {}
variable "environment" {
type = string
}
variable "vpc_cidr" {
type = string
}
VPCを作成するとAWSが強制的にデフォルトのルートテーブル、ネットワークACL、DHCP オプションセット、セキュリティーグループを作成します。
デフォルトのルートテーブル、ネットワークACL、セキュリティーグループは1つのVPCと1:1です。つまり、VPCを作成する毎に新しく作成されます。ですが、DHCP オプションセットについてはリージョンで1つです。既にデフォルトDHCP オプションセットが存在していたら作成されません。ここではそれらデフォルトのリソースを利用するように記述しています。
デフォルトのリソースaws_default_network_acl
、aws_default_security_group
、aws_default_route_table
、aws_default_vpc_dhcp_options
は特殊でAWSが自動作成したものの設定を上書きするという動きをします。正直すこし使いにくいので、ハマりたくない人はaws_network_acl
といった通常のリソースを使用しましょう。
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
instance_tenancy = "default"
tags = {
Name = "main"
}
}
resource "aws_subnet" "subnets" {
count = 2
vpc_id = aws_vpc.main.id
# cidrsubnet関数を使ってCIDRを分割します。第2引数はビット数なので注意。
cidr_block = cidrsubnet(var.vpc_cidr, 1, count.index)
tags = {
Name = "subnet-${count.index}"
}
}
resource "aws_internet_gateway" "igw" {
# ここでVPCを指定しておくと aws_internet_gateway_attachment でアタッチする必要がなくなります。
# どちらで書いても大丈夫です。
vpc_id = aws_vpc.main.id
tags = {
Name = "igw"
}
}
resource "aws_default_network_acl" "default_acl" {
# 自動で作成されたネットワークACLのIDを渡します。
default_network_acl_id = aws_vpc.main.default_network_acl_id
ingress {
protocol = -1
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
egress {
protocol = -1
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
tags = {
Name = "default-acl"
}
}
resource "aws_default_security_group" "default_sg" {
# ここはVPCのID。うーん、わかりにくい。
vpc_id = aws_vpc.main.id
ingress {
protocol = -1
self = true
from_port = 0
to_port = 0
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "default-sg"
}
}
resource "aws_default_route_table" "public_rt" {
# 自動で作成されたルートテーブルのIDを渡します。
default_route_table_id = aws_vpc.main.default_route_table_id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "default-rt"
}
}
resource "aws_route_table" "private_rt" {
vpc_id = aws_vpc.main.id
tags = {
Name = "private-rt"
}
}
resource "aws_route_table_association" "rt_asso" {
subnet_id = aws_subnet.subnets[1].id
route_table_id = aws_route_table.private_rt.id
}
resource "aws_default_vpc_dhcp_options" "default_dhcp_op" {
# リージョンで1つなのでIDを渡さなくても判定できる。
tags = {
Name = "default-dhcp-op"
}
}
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${data.aws_region.current.name}.s3"
tags = {
Name = "s3-vpc-endpoint"
}
}
resource "aws_vpc_endpoint_route_table_association" "example" {
route_table_id = aws_route_table.private_rt.id
vpc_endpoint_id = aws_vpc_endpoint.s3.id
}