[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を決めてあげてください。
。。。。以上です。
この記事がお役に立てば【 いいね 】のご協力をお願いいたします!