DEV Community

Jay Watson
Jay Watson

Posted on • Edited on

Standup Serverless Jenkins on Fargate with Terraform - Part 1: Networking

We need to set up our network before we get into ECS and Jenkins. We'll stamp out a VPC, public subnets, private subnets, an Internet Gateway, NAT Gateways, and route tables. Let's get started!
Simple AWS network stamp out
First, create variables.tf. This file allows us to define the variables we need—a VPC CIDR block, private subnets, and public subnets.

variable "vpc_cidr_block" { description = "CIDR of vpc" type = string } variable "public_subnets" { description = "Map of public subnets that should be created" type = map(object({ cidr_block = string availability_zone = string })) } variable "private_subnets" { description = "Map of private subnets that should be created" type = map(object({ cidr_block = string availability_zone = string })) } variable "application_name" { description = "Name of the application" type = string } 
Enter fullscreen mode Exit fullscreen mode

Next, we'll provide the variable definitions in terraform.tfvars.

vpc_cidr_block = "10.0.0.0/24" public_subnets = { subnet_1 = { cidr_block = "10.0.0.0/26" availability_zone = "us-east-1a" } subnet_2 = { cidr_block = "10.0.0.64/26" availability_zone = "us-east-1b" } } private_subnets = { subnet_1 = { cidr_block = "10.0.0.128/26" availability_zone = "us-east-1a" } subnet_2 = { cidr_block = "10.0.0.192/26" availability_zone = "us-east-1b" } } application_name = "serverless-jenkins-on-ecs" 
Enter fullscreen mode Exit fullscreen mode

Now, create vpc.tf and create the VPC first. An AWS VPC (Virtual Private Cloud) is a virtual network logically isolated from other virtual networks in the AWS Cloud, providing you with control over IP addresses, subnets, route tables, and network gateways.

# VPC resource "aws_vpc" "this" { cidr_block = var.vpc_cidr_block enable_dns_hostnames = true tags = { Name = var.application_name } } 
Enter fullscreen mode Exit fullscreen mode

Create the public subnets. What makes these subnets public is that they will have a route to an Internet Gateway (IGW), which allows resources within the subnet to communicate directly with the Internet.

# Public Subnets resource "aws_subnet" "public" { for_each = var.public_subnets vpc_id = aws_vpc.this.id cidr_block = each.value.cidr_block availability_zone = each.value.availability_zone map_public_ip_on_launch = true tags = { Name = format("public-%s-%s", var.application_name, each.value.availability_zone) } } 
Enter fullscreen mode Exit fullscreen mode

Create the IGW and associate it with the VPC. We'll reference it later in our route table that we'll connect to our public subnets.

# IGW resource "aws_internet_gateway" "this" { vpc_id = aws_vpc.this.id } 
Enter fullscreen mode Exit fullscreen mode

Create a route table for your public subnet and add a route to funnel traffic through the IGW. After which, create the route table association to wire up the IGW with the public subnets.

# Public Route Table resource "aws_route_table" "public" { vpc_id = aws_vpc.this.id tags = { Name = "public" } } # Add IGW Route resource "aws_route" "public" { route_table_id = aws_route_table.public.id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.this.id } # Associate Route Table with Subnet resource "aws_route_table_association" "public" { for_each = aws_subnet.public subnet_id = each.value.id route_table_id = aws_route_table.public.id } 
Enter fullscreen mode Exit fullscreen mode

Next, create the private subnets. As the name implies, these subnets are inaccessible from the outside world.

# Private Subnets resource "aws_subnet" "private" { for_each = var.private_subnets vpc_id = aws_vpc.this.id cidr_block = each.value.cidr_block availability_zone = each.value.availability_zone tags = { Name = format("private-%s-%s", var.application_name, each.value.availability_zone) } } 
Enter fullscreen mode Exit fullscreen mode

Now, let's create an Elastic IP (EIP) and a NAT Gateway. We need the EIP, as AWS requires one as part of the NAT Gateway creation. The NAT Gateway is necessary as that's how the private subnets can communicate with the Internet (egress only). Imagine that you have RHEL EC2s that need to receive yum updates. You'll need a NAT Gateway.

# EIP for NAT Gateway resource "aws_eip" "this" { for_each = aws_subnet.private } # NAT Gateway resource "aws_nat_gateway" "this" { for_each = aws_subnet.private subnet_id = aws_subnet.public[each.key].id allocation_id = aws_eip.this[each.key].id tags = { Name = format("private-%s-%s", var.application_name, each.value.availability_zone) } } 
Enter fullscreen mode Exit fullscreen mode

Next, we'll create the route table, the route to associate the NAT Gateway to the private subnets, and the route table association.

# Private Route Table resource "aws_route_table" "private" { for_each = aws_subnet.private vpc_id = aws_vpc.this.id tags = { Name = format("private-%s-%s", var.application_name, each.value.availability_zone) } } # Add Route - Private Subnets to NAT Gateway resource "aws_route" "private" { for_each = aws_subnet.private route_table_id = aws_route_table.private[each.key].id destination_cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.this[each.key].id } # Associate Private RT with Private Subnets resource "aws_route_table_association" "private" { for_each = aws_subnet.private subnet_id = each.value.id route_table_id = aws_route_table.private[each.key].id } 
Enter fullscreen mode Exit fullscreen mode

You are ready. Run the following commands.

# Initialize Terraform terraform init # Check and see what will be created terraform plan # Let's do this! terraform apply 
Enter fullscreen mode Exit fullscreen mode

Now, navigate to the AWS console and search for VPC.
AWS VPC
Scroll down to the VPC resource map.
VPC resource map
Click on subnets next.
AWS Subnets
Also, check out your Route Tables, Internet Gateways, NAT Gateways, and Elastic IPs.

Fin 👏

If you need it, here's the GitHub repo.

Top comments (0)