My Cloud Journey — Week 6 | Advanced AWS Part 2 | Application Load Balancer deployment using CloudFormation

Adekunle Adesanmi
4 min readJun 6, 2024

--

In my previous post, I covered some important concepts that I found interesting during my exploration of advanced AWS topics. In this post, I will go into a specific exercise I completed using AWSCloudFormation, with subsequent posts focusing on additional exercises.

The task in this exercise is to set up a web infrastructure with an Application Load Balancer (ALB) distributing traffic across two EC2 instances in separate Availability Zones (AZs).

Here is the CloudFormation template that I used, written in YAML format.

The template sets up a Virtual Private Cloud (VPC) with public and private subnets across two Availability Zones (AZs), an Internet Gateway, routing tables, and an Application Load Balancer (ALB) with two target EC2 instances.

AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudFormation for ALB'

Resources:
# My VPC
MyVPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: '172.16.0.0/16'
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: MyVPC

# Public Subnet in AZ 1
PublicSubnet1A:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '172.16.1.0/24'
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet1A

# App Private Subnet in AZ 1
AppPrivateSubnet1A:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '172.16.2.0/24'
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: AppPrivateSubnet1A

# Data Private Subnet in AZ 1
DataPrivateSubnet1A:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '172.16.3.0/24'
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: DataPrivateSubnet1A

# Public Subnet in AZ 2
PublicSubnet2B:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '172.16.4.0/24'
AvailabilityZone: !Select [1, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet2B

# App Private Subnet in AZ 2
AppPrivateSubnet2B:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '172.16.5.0/24'
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: AppPrivateSubnet2B

# Data Private Subnet in AZ 2
DataPrivateSubnet2B:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref MyVPC
CidrBlock: '172.16.6.0/24'
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: DataPrivateSubnet2B

# Internet Gateway IGW
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Name
Value: MyVPC-IGW

# Attach Gateway
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref InternetGateway

# Route Table
PublicRouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: PublicRouteTable

# Public Route
PublicRoute:
Type: 'AWS::EC2::Route'
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: '0.0.0.0/0'
GatewayId: !Ref InternetGateway

# Public Subnet Association
PublicSubnet1ARouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref PublicSubnet1A
RouteTableId: !Ref PublicRouteTable

# Application Load Balancer
MyLoadBalancer:
Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
Properties:
Subnets:
- !Ref PublicSubnet1A
- !Ref PublicSubnet2B
SecurityGroups:
- !Ref WebServerSecurityGroup

# Target Group for ALB
MyTargetGroup:
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
Properties:
Port: 80
Protocol: HTTP
VpcId: !Ref MyVPC
Targets:
- Id: !Ref WebServerInstance1A
Port: 80
- Id: !Ref WebServerInstance2B
Port: 80

# Listener for ALB
MyListener:
Type: 'AWS::ElasticLoadBalancingV2::Listener'
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref MyTargetGroup
LoadBalancerArn: !Ref MyLoadBalancer
Port: 80
Protocol: HTTP

# Web Server Security Group
WebServerSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: Enable HTTP access via port 80
VpcId: !Ref MyVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0

# WebServerInstance1A:
WebServerInstance1A:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: 'ami-0bb84b8ffd87024d8'
InstanceType: 't2.micro'
SubnetId: !Ref PublicSubnet1A
SecurityGroupIds:
- !Ref WebServerSecurityGroup
Tags:
- Key: Name
Value: WebServerInstance1A
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello World from WebServerInstance 1A" > /var/www/html/index.html

# WebServerInstance2B:
WebServerInstance2B:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: 'ami-0bb84b8ffd87024d8'
InstanceType: 't2.micro'
SubnetId: !Ref PublicSubnet2B
SecurityGroupIds:
- !Ref WebServerSecurityGroup
Tags:
- Key: Name
Value: WebServerInstance2B
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello World from WebServerInstance 2B" > /var/www/html/index.html

Here’s a breakdown of the key components:

  1. VPC and Subnets: The template creates a VPC with a CIDR block of 172.16.0.0/16. It then defines six subnets: two public subnets (one in each AZ), two private app subnets, and two private data subnets.
  2. Internet Gateway: An Internet Gateway is created and attached to the VPC, allowing resources in the public subnets to access the Internet.
  3. Route Tables: A public route table is created, and a route is added to send all internet-bound traffic (0.0.0.0/0) through the Internet Gateway. The public subnets are associated with this route table.
  4. Security Group: A security group is created to allow inbound HTTP traffic (port 80) from anywhere (0.0.0.0/0) to the web servers.
  5. Application Load Balancer (ALB): An ALB is created and placed in the public subnets. It listens for incoming HTTP traffic on port 80.
  6. Target Group: A target group is created for the ALB, which will route traffic to the registered targets (EC2 instances).
  7. EC2 Instances: Two EC2 instances are launched, one in each public subnet. These instances will serve as the web servers behind the ALB. The instances are configured with a User Data script that installs Apache HTTP Server and creates a simple “Hello World” index.html file.

Here’s a screenshot of the deployed stack.

Join me next time as I share more CloudFormation deployments!

Feel free to contact me to discuss Agile, cloud adoption, or anything tech-related. 🚀
You can also connect with me on LinkedIn.

--

--