[terraform] AWSで3層ネットワーク構成を構築するmoduleを書いてみた

インフラエンジニアの寺岡です。
今回はterraformのmoduleについてのお話しです。
AWSのネットワークをPublic/DMZ/Privateの3層に分割する構成を一気に構築できる
かつどの案件でも使いまわせるようなmoduleを自作しましたのでまとめておきますー。
当記事に記載するコードを実行すると以下のような構成をAWS上にデプロイすることが出来ます。

マルチAZかつDMZのsubnetはNATGatewayを経由して外部と通信を行います。
Publicのsubnetは直接InternetGatewayと通信を行い
Privateのsubnetはローカル間通信のみとなっています。
一見複雑そうですが割とよく見る構成ではないでしょうか。
この構成をterraformでモジュール化した結果が以下のようになります。
■moduleに渡す値の変数を定義する
まずはmoduleに渡すための値をvariableで定義しておきます。
variable "vpc_config" {
default = {
project = "tf-moduletest"
environment = "stg"
cidr_block = "10.10.0.0/16"
}
}
variable "availability_zones" {
default = ["ap-northeast-1a","ap-northeast-1c"]
}
variable "public_subnets" {
default = ["10.10.0.0/20","10.10.16.0/20"]
}
variable "dmz_subnets" {
default = ["10.10.32.0/20","10.10.48.0/20"]
}
variable "private_subnets" {
default = ["10.10.64.0/20","10.10.80.0/20"]
}
■moduleを記述する
この部分が今回の本題です。
variableで定義した値を元にresourceを構築するだけなので
基本的にどの案件でも使いまわすことが出来ます。
######
# VPC
######
resource "aws_vpc" "vpc" {
cidr_block = "${var.vpc_config["cidr_block"]}"
tags {
Name = "vpc-${var.vpc_config["project"]}-${var.vpc_config["environment"]}"
}
}
################
# Public subnet
################
resource "aws_subnet" "public" {
count = "${length(var.public_subnets)}"
vpc_id = "${aws_vpc.vpc.id}"
cidr_block = "${element(var.public_subnets, count.index)}"
availability_zone = "${element(var.availability_zones, count.index)}"
map_public_ip_on_launch = "true"
tags {
Name = "subnet-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-public-${substr(element(var.availability_zones, count.index),-1,1)}"
}
}
################
# DMZ subnet
################
resource "aws_subnet" "dmz" {
count = "${length(var.dmz_subnets)}"
vpc_id = "${aws_vpc.vpc.id}"
cidr_block = "${element(var.dmz_subnets, count.index)}"
availability_zone = "${element(var.availability_zones, count.index)}"
tags {
Name = "subnet-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-dmz-${substr(element(var.availability_zones, count.index),-1,1)}"
}
}
################
# Private subnet
################
resource "aws_subnet" "private" {
count = "${length(var.private_subnets)}"
vpc_id = "${aws_vpc.vpc.id}"
cidr_block = "${element(var.private_subnets, count.index)}"
availability_zone = "${element(var.availability_zones, count.index)}"
tags {
Name = "subnet-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-private-${substr(element(var.availability_zones, count.index),-1,1)}"
}
}
###############################
# Public routes and association
###############################
resource "aws_route_table" "public" {
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "rtb-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-public"
}
}
resource "aws_internet_gateway" "internet_gateway" {
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "igw-${var.vpc_config["project"]}-${var.vpc_config["environment"]}"
}
}
resource "aws_route" "public_internet_gateway" {
route_table_id = "${aws_route_table.public.id}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.internet_gateway.id}"
}
resource "aws_route_table_association" "public" {
count = "${length(var.public_subnets)}"
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
route_table_id = "${aws_route_table.public.id}"
}
############################
# DMZ routes and association
############################
resource "aws_route_table" "dmz" {
count = "${length(var.dmz_subnets)}"
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "rtb-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-dmz-${substr(element(var.availability_zones, count.index),-1,1)}"
}
}
resource "aws_eip" "nat" {
count = "${length(var.dmz_subnets)}"
vpc = true
}
resource "aws_nat_gateway" "nat_gateway" {
count = "${length(var.dmz_subnets)}"
allocation_id = "${element(aws_eip.nat.*.id, count.index)}"
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
tags {
Name = "nat-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-public-${substr(element(var.availability_zones, count.index),-1,1)}"
}
}
resource "aws_route" "dmz_nat_gateway" {
count = "${length(var.dmz_subnets)}"
route_table_id = "${element(aws_route_table.dmz.*.id, count.index)}"
destination_cidr_block = "0.0.0.0/0"
gateway_id = "${element(aws_nat_gateway.nat_gateway.*.id, count.index)}"
}
resource "aws_route_table_association" "dmz" {
count = "${length(var.dmz_subnets)}"
subnet_id = "${element(aws_subnet.dmz.*.id, count.index)}"
route_table_id = "${element(aws_route_table.dmz.*.id, count.index)}"
}
################################
# Private routes and association
################################
resource "aws_route_table" "private" {
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "rtb-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-private"
}
}
resource "aws_route_table_association" "private" {
count = "${length(var.private_subnets)}"
subnet_id = "${element(aws_subnet.private.*.id, count.index)}"
route_table_id = "${aws_route_table.private.id}"
}
■記述したmoduleを呼び出す
terraformでmoduleを呼びだす場合は以下のような記述をします。
sourceでmoduleを記述した.tfファイルを格納しているディレクトリを指定して
variableで指定したmoduleを実行するために必要な変数を渡すだけです。
module "vpc" {
source = "../modules/network/vpc/"
vpc_config = "${var.vpc_config}"
availability_zones = "${var.availability_zones}"
public_subnets = "${var.public_subnets}"
dmz_subnets = "${var.dmz_subnets}"
private_subnets = "${var.private_subnets}"
}
たったこれだけです、後は必殺のterraform applyを決めてあげてください。
。。。。以上です。
この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
0