概要
今回はTerraformを使って
- VPC
- パブリックサブネットとプライベートサブネット
- IGW
- ルートテーブルおよびルーティングの設定
- Elastic IP
- NATゲートウェイ
を構築したいと思います
今回作成するインフラ構成は下記の図のようになります
前提
- 東京リージョンを使用
- AWSを使用
- main.tfとvariables.tfを設定済み
- ネットワークに関する基本的な知識をある程度持っている
上記のファイルをまだ作成していない方は下記の記事を参考にしてください
AWSにおけるネットワークの概要について知りたい方は以下の記事を参考にしてください
また、コンテナ経由でTerraformを使用すると複数ブロジェクトで使用する際にバージョンによる違いを意識せずに済みます
コンテナを使用したい方はこちらの記事も参考にしてみてください
ディレクトリ構成
構成は以下の通りです
tree
.
├── main.tf
├── network.tf
└── variables.tf
network.tfにネットワーク関連の設定を記載していきます
network.tf
# ------------------------------
# VPC Configuration
# ------------------------------
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
# DNSによる名前解決をサポートする
enable_dns_support = true
# パブリックIPアドレスを持つインスタンスが対応するDNSホスト名を取得できるよう明示する
enable_dns_hostnames = true
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-vpc" })
)
}
# ------------------------------
# Internert Gateway Configuration
# ------------------------------
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-igw" })
)
}
# ------------------------------
# Public Subnet Configuration
# ------------------------------
resource "aws_subnet" "public_a" {
cidr_block = "10.0.1.0/24"
# サブネットに配置されたインスタンスにパブリックIPアドレスが付与される
map_public_ip_on_launch = true
vpc_id = aws_vpc.main.id
availability_zone = "${data.aws_region.current.name}a"
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a" })
)
}
# ルートテーブルの設定
resource "aws_route_table" "public_a" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a-rt" })
)
}
# ルートテーブルをパブリックサブネットaと紐付ける
# タグをサポートしてないのでつけない
resource "aws_route_table_association" "public_a" {
subnet_id = aws_subnet.public_a.id
route_table_id = aws_route_table.public_a.id
}
# IGWへのルーティングを設定
# タグをサポートしてないのでつけない
resource "aws_route" "public_internet_access_a" {
route_table_id = aws_route_table.public_a.id
# インターネット(0.0.0.0/0)へのアクセスを許可
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
# NATゲートウェイ用のElasticIPをpublic_a内に作成
resource "aws_eip" "public_a" {
# EIPはVPC内に存在する
vpc = true
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a-eip" })
)
}
# NATゲートウェイ
resource "aws_nat_gateway" "public_a" {
# パブリックサブネットaに作成したElasticIPをNATに割り当てる(allocateする)
allocation_id = aws_eip.public_a.id
subnet_id = aws_subnet.public_a.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a-ngw" })
)
}
resource "aws_subnet" "public_c" {
cidr_block = "10.0.2.0/24"
# サブネットに配置されたインスタンスにパブリックIPアドレスが付与される
map_public_ip_on_launch = true
vpc_id = aws_vpc.main.id
availability_zone = "${data.aws_region.current.name}c"
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-c" })
)
}
resource "aws_route_table" "public_c" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-c-rt" })
)
}
resource "aws_route_table_association" "public_c" {
subnet_id = aws_subnet.public_c.id
route_table_id = aws_route_table.public_c.id
}
resource "aws_route" "public_internet_access_c" {
route_table_id = aws_route_table.public_c.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
resource "aws_eip" "public_c" {
vpc = true
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-c-eip" })
)
}
resource "aws_nat_gateway" "public_c" {
allocation_id = aws_eip.public_c.id
subnet_id = aws_subnet.public_c.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-c-ngw" })
)
}
# ------------------------------
# Private Subnet Configuration
# ------------------------------
resource "aws_subnet" "private_a" {
cidr_block = "10.0.11.0/24"
vpc_id = aws_vpc.main.id
availability_zone = "${data.aws_region.current.name}a"
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-private-a" })
)
}
resource "aws_route_table" "private_a" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-private-a-rt" })
)
}
resource "aws_route_table_association" "private_a" {
subnet_id = aws_subnet.private_a.id
route_table_id = aws_route_table.private_a.id
}
resource "aws_route" "private_a_internet_out" {
route_table_id = aws_route_table.private_a.id
# インターネットへのアウトバウンドアクセスを可能にするためにNATの設定を行う
nat_gateway_id = aws_nat_gateway.public_a.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_subnet" "private_c" {
cidr_block = "10.0.12.0/24"
vpc_id = aws_vpc.main.id
availability_zone = "${data.aws_region.current.name}c"
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-private-c" })
)
}
resource "aws_route_table" "private_c" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-private-c-rt" })
)
}
resource "aws_route_table_association" "private_c" {
subnet_id = aws_subnet.private_c.id
route_table_id = aws_route_table.private_c.id
}
resource "aws_route" "private_c_internet_out" {
route_table_id = aws_route_table.private_c.id
# インターネットへのアウトバウンドアクセスを可能にするためにNATの設定を行う
nat_gateway_id = aws_nat_gateway.public_c.id
destination_cidr_block = "0.0.0.0/0"
}
VPC
VPCには10.0.0.0/16
を割り当てます
また、
- DNSによる名前解決
- パブリックIPアドレスを持つインスタンスが対応するDNSホスト名を取得
する設定を有効化します
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
# DNSによる名前解決をサポートする
enable_dns_support = true
# パブリックIPアドレスを持つインスタンスが対応するDNSホスト名を取得できるよう明示する
enable_dns_hostnames = true
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-vpc" })
)
}
インターネットゲートウェイ
VPC内にインターネットゲートウェイがないとパブリックサブネットからインターネットへアクセスできないので作成します
その際にVPCのIDと紐付けます
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-igw" })
)
}
パブリックサブネット
今回は
- public_a
- public_c
の2種類のサブネットを作成します
構成は以下の通りです
パブリックサブネット | public_a | public_c |
---|---|---|
IPレンジ | 10.0.1.0/24 | 10.0.2.0/24 |
AZ | ap-northeast-1a | ap-northeast-1c |
AZ内にパブリックサブネットを作成し、サブネットをVPCのIDと紐付けます
resource "aws_subnet" "public_a" {
cidr_block = "10.0.1.0/24"
# サブネットに配置されたインスタンスにパブリックIPアドレスが付与される
map_public_ip_on_launch = true
vpc_id = aws_vpc.main.id
availability_zone = "${data.aws_region.current.name}a"
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a" })
)
}
パブリックサブネットのルーティングの設定
- aws_route_table
- aws_route_table_association
- aws_route
を設定します
ルートテーブルをどの
- サブネット
- VPC
- インタネットゲートウェイ
と紐づけるかと
- ルーティング(パブリックなのですべてのIPアドレスを許可)
を設定する必要があります
# ルートテーブルの設定
resource "aws_route_table" "public_a" {
vpc_id = aws_vpc.main.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a-rt" })
)
}
# ルートテーブルをパブリックサブネットaと紐付ける
# タグをサポートしてないのでつけない
resource "aws_route_table_association" "public_a" {
subnet_id = aws_subnet.public_a.id
route_table_id = aws_route_table.public_a.id
}
# IGWへのルーティングを設定
# タグをサポートしてないのでつけない
resource "aws_route" "public_internet_access_a" {
route_table_id = aws_route_table.public_a.id
# インターネット(0.0.0.0/0)へのアクセスを許可
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
NATの設定
NATゲートウェイはブライベートサブネットのインスタンスが使用するのでパブリックサブネット側で設定をします
パブリックサブネット内にNATゲートウェイとNATゲートウェイに割り当てるElasticIPを作成します
# NATゲートウェイ用のElasticIPをpublic_a内に作成
resource "aws_eip" "public_a" {
# EIPはVPC内に存在する
vpc = true
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a-eip" })
)
}
# NATゲートウェイ
resource "aws_nat_gateway" "public_a" {
# パブリックサブネットaに作成したElasticIPをNATに割り当てる(allocateする)
allocation_id = aws_eip.public_a.id
subnet_id = aws_subnet.public_a.id
tags = merge(
local.common_tags,
tomap({ "Name" = "${local.prefix}-public-a-ngw" })
)
}
プライベートサブネット
今回は
- private_a
- private_c
の2種類のサブネットを作成します
プライベートサブネットのホスト部を11からにしたのは今後パブリックサブネットを追加する際に
ホスト部の1から10までをパブリックサブネットにできて管理しやすいと思ったからです
構成は以下の通りです
プライベートサブネット | private_a | private_c |
---|---|---|
IPレンジ | 10.0.11.0/24 | 10.0.12.0/24 |
AZ | ap-northeast-1a | ap-northeast-1c |
パブリックサブネットでの設定を被る箇所が多いので違うところのみ解説します
プライベートサブネットのルーティングの設定
NATゲートウェイを通じたインターネットへのアウトバウンドアクセスのみ許可します
resource "aws_route" "private_a_internet_out" {
route_table_id = aws_route_table.private_a.id
# インターネットへのアウトバウンドアクセスを可能にするためにNATの設定を行う
nat_gateway_id = aws_nat_gateway.public_a.id
destination_cidr_block = "0.0.0.0/24"
}
tagの作成
こちらに関しては任意です
ハードコーディングしてもいいのですが今回はmain.tfで定義した変数を使用します
mergeを使ってmain.tfにあるlocal.common_tags変数に任意の変数を追加します
共通部分は繰り返し使用でき、なおかつ独自の変数を追加できるのでおすすめです
# ------------------------------
# Variables
# ------------------------------
# プリフィックスを設定
variable "prefix" {
default = "tf-pg"
}
# プロジェクトを識別する一意の識別子を設定
variable "project" {
default = "terraform-playground"
}
# プロジェクトのオーナーを設定
variable "owner" {
default = "shun198"
}
# ------------------------------
# Locals
# ------------------------------
locals {
# variables.tfから変数を取得
# terraformのworkspaceの一覧から該当するworkspace(dev,stg,prdなど)を取得
prefix = "${var.prefix}-${terraform.workspace}"
common_tags = {
Environmnet = terraform.workspace
Project = var.project
Owner = var.owner
ManagedBy = "Terraform"
}
}
実際に作成してみよう!
フォーマットの修正、validateやplanによる確認が終わったら以下のコマンドで適用します
terraform apply -auto-approve
作成されたか確認してみよう!
- VPC
- パブリックとサブネット
- インターネットげードウェイ
- ルートテーブル
- NATゲートウェイ
が作成および該当するタグが付けられていることを確認します
VPC
サブネット
インターネットゲートウェイ
ルートテーブル
ElasticIP
NATゲートウェイ
リソースの削除
使用しないリソースは以下のコマンドで削除しましょう
terraform destroy
まとめ
VPCをはじめとしてネットワークの設定をたった1コマンドで作成できるのは楽でいいですね
ただし、NACLやALBの設定などをしてなくて心もとないので別記事で作成したいと思います
参考