[Osaka/Yokohama/Tokushima] Looking for infrastructure/server side engineers!

[Osaka/Yokohama/Tokushima] Looking for infrastructure/server side engineers!

[Deployed by over 500 companies] AWS construction, operation, maintenance, and monitoring services

[Deployed by over 500 companies] AWS construction, operation, maintenance, and monitoring services

[Successor to CentOS] AlmaLinux OS server construction/migration service

[Successor to CentOS] AlmaLinux OS server construction/migration service

[For WordPress only] Cloud server “Web Speed”

[For WordPress only] Cloud server “Web Speed”

[Cheap] Website security automatic diagnosis “Quick Scanner”

[Cheap] Website security automatic diagnosis “Quick Scanner”

[Reservation system development] EDISONE customization development service

[Reservation system development] EDISONE customization development service

[Registration of 100 URLs is 0 yen] Website monitoring service “Appmill”

[Registration of 100 URLs is 0 yen] Website monitoring service “Appmill”

[Compatible with over 200 countries] Global eSIM “Beyond SIM”

[Compatible with over 200 countries] Global eSIM “Beyond SIM”

[If you are traveling, business trip, or stationed in China] Chinese SIM service “Choco SIM”

[If you are traveling, business trip, or stationed in China] Chinese SIM service “Choco SIM”

[Global exclusive service] Beyond's MSP in North America and China

[Global exclusive service] Beyond's MSP in North America and China

[YouTube] Beyond official channel “Biyomaru Channel”

[YouTube] Beyond official channel “Biyomaru Channel”

[terraform] I wrote a module to build a 3-layer network configuration on AWS

My name is Teraoka and I am an infrastructure engineer.

This time we will talk about the terraform module.


I created a module that allows you to build a configuration that divides the AWS network into three layers: Public/DMZ/Private at once, and

By executing the code described in this article, you can deploy the following configuration on AWS.

Multi-AZ and DMZ subnets communicate with the outside world via NATGateway.

Public subnets communicate directly with InternetGateway, and
Private subnets only communicate locally.

It may seem complicated at first glance, but I think it's a fairly common structure.

The result of modularizing this configuration using terraform is as follows.

■Define variables for values ​​to be passed to module

First, define the value to be passed to the module as a 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"] }

■Describe the module

This part is the main topic of this article.

Since you just construct a resource based on the value defined in variable, you
can basically reuse it in any project.

###### # 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}" }

■Call the described module

When calling a module with terraform, write the following code.

Just specify the directory containing the .tf file that describes the module in source and
pass the variables necessary to execute the module specified in variable.

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}" }

That's all you need to do, then do the deadly terraform apply.

. . . . That's it.

If you found this article helpful , please give it a like!
0
Loading...
0 votes, average: 0.00 / 10
3,518
X facebook Hatena Bookmark pocket
[2025.6.30 Amazon Linux 2 support ended] Amazon Linux server migration solution

[2025.6.30 Amazon Linux 2 support ended] Amazon Linux server migration solution

[Osaka/Yokohama] Actively recruiting infrastructure engineers and server side engineers!

[Osaka/Yokohama] Actively recruiting infrastructure engineers and server side engineers!

The person who wrote this article

About the author

Yuki Teraoka

Joined Beyond in 2016 and is currently in his 6th year as an Infrastructure Engineer
MSP, where he troubleshoots failures while
also designing and building infrastructure using public clouds such as AWS.
Recently, I
have been working with Hashicorp tools such as Terraform and Packer as part of building container infrastructure such as Docker and Kubernetes and automating operations, and I
also play the role of an evangelist who speaks at external study groups and seminars.

・GitHub
https://github.com/nezumisannn

・Presentation history
https://github.com/nezumisannn/my-profile

・Presentation materials (SpeakerDeck)
https://speakerdeck.com/nezumisannn

・Certification:
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect