CloudFormation is most important aspect infrastructure as a code provided by AWS that aids in the infrastructure deployment, rollback, infrastructure automation and configuration management of your AWS resources so that you may spend more time concentrating on your AWS-based applications and less time managing those resources. The AWS resources you require (such as Amazon EC2 instances or Amazon RDS DB instances) are listed in a template that you build, and CloudFormation handles the provisioning and configuration of those resources on your behalf. CloudFormation takes care of the creation, configuration, and identification of the dependencies between AWS resources, so you don’t have to.
In this blog, we will write a AWS CloudFormation template to create a three-tier architecture in AWS.
The three-tier architecture, which includes the web tier, application tier, and database tier, is the most often used in implementation of a multi-tier architecture in AWS Services.
The web layer is with which end-users interact. The application layer contains the code or logic. It interacts with the web and data layer to respond to client requests. The database layer manages the data. The three-tier architecture helps in creating a secure, scalable, and highly available infrastructure.
Parameters:
EnvironmentName:
Type: String
Description: Enter Environment Name
myVPCcidrblock:
Type: String
Default: 10.192.0.0/16
myPublicSubnet1cidr:
Type: String
Default: 10.192.1.0/24
myPublicSubnet2cidr:
Type: String
Default: 10.192.2.0/24
myPrivateSubnet1cidr:
Type: String
Default: 10.192.3.0/24
myPrivateSubnet2cidr:
Type: String
Default: 10.192.4.0/24
myDBSubnet1cidr:
Type: String
Default: 10.192.5.0/24
myDBSubnet2cidr:
Type: String
Default: 10.192.6.0/24
myAMIID:
Type: String
Default: ami-0f924dc71d44d23e2
InstanceType:
Type: String
Default: t2.micro
KeyName:
Type: String
Default: dell-ohio-keypair
Resources:
myVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref myVPCcidrblock
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref myVPC
myPublicWebSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref myVPC
CidrBlock: !Ref myPublicSubnet1cidr
MapPublicIpOnLaunch: true
AvailabilityZone: !Select [ 0, !GetAZs '' ]
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet (AZ1)
myPublicWebSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref myVPC
CidrBlock: !Ref myPublicSubnet2cidr
MapPublicIpOnLaunch: true
AvailabilityZone: !Select [ 1, !GetAZs '' ]
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet (AZ2)
myPrivateAppSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref myVPC
CidrBlock: !Ref myPrivateSubnet1cidr
AvailabilityZone: !Select [ 0, !GetAZs '' ]
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet (AZ1)
myPrivateAppSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref myVPC
CidrBlock: !Ref myPrivateSubnet2cidr
AvailabilityZone: !Select [ 1, !GetAZs '' ]
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet (AZ2)
myPrivateDBSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref myVPC
CidrBlock: !Ref myDBSubnet1cidr
AvailabilityZone: !Select [ 0, !GetAZs '' ]
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} DB Subnet (AZ1)
myPrivateDBSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref myVPC
CidrBlock: !Ref myDBSubnet2cidr
AvailabilityZone: !Select [ 1, !GetAZs '' ]
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} DB Subnet (AZ2)
myPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref myVPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Route Table
myPrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref myVPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Route Table
myRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref myPublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
myPublicWebSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: myPublicWebSubnet1
RouteTableId:
Ref: myPublicRouteTable
myPublicWebSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: myPublicWebSubnet2
RouteTableId:
Ref: myPublicRouteTable
myPrivateAppSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: myPrivateAppSubnet1
RouteTableId:
Ref: myPrivateRouteTable
myPrivateAppSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: myPrivateAppSubnet2
RouteTableId:
Ref: myPrivateRouteTable
myPrivateDBSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: myPrivateDBSubnet1
RouteTableId:
Ref: myPrivateRouteTable
myPrivateDBSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: myPrivateDBSubnet2
RouteTableId:
Ref: myPrivateRouteTable
NATGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NATGatewayEIP.AllocationId
SubnetId: !Ref myPublicWebSubnet1
Tags:
- Key: Name
Value: !Ref EnvironmentName
NATGatewayEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
RouteNATGateway:
DependsOn: NATGateway
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref myPrivateRouteTable
DestinationCidrBlock: '0.0.0.0/0'
NatGatewayId: !Ref NATGateway
BastionHostSG:
Type: AWS::EC2::SecurityGroup
DependsOn: myVPC
Properties:
GroupDescription: Bastion sg to talk to web and app tier
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
ApplicationLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
DependsOn: myVPC
Properties:
GroupDescription: http traffic to web tier
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
InternalLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
DependsOn: myVPC
Properties:
GroupDescription: Web tier traffic to app tier
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref WebtierSG
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref WebtierSG
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
WebtierSG:
Type: AWS::EC2::SecurityGroup
DependsOn: myVPC
Properties:
GroupDescription: ApplicationLoadBalancer to web tier
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ApplicationLoadBalancerSG
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref BastionHostSG
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
AppTierSG:
Type: AWS::EC2::SecurityGroup
DependsOn: myVPC
Properties:
GroupDescription: Internal Load Balancer to AppTier
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref InternalLoadBalancerSG
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref BastionHostSG
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
DatabaseSG:
Type: AWS::EC2::SecurityGroup
DependsOn: myVPC
Properties:
GroupDescription: Apptier to database tier
VpcId: !Ref myVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref AppTierSG
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
BastionHostEC2:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref myAMIID
SecurityGroupIds:
- !GetAtt BastionHostSG.GroupId
InstanceType: !Ref InstanceType
SubnetId: !Ref myPublicWebSubnet1
KeyName: !Ref KeyName
myLaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !Ref myAMIID
InstanceType: !Ref InstanceType
SecurityGroups:
- !Ref WebtierSG
KeyName: !Ref KeyName
UserData:
Fn::Base64: |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo 'Checkmate Global Technologies' > /var/www/html/index.html
myASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
LaunchConfigurationName: !Ref myLaunchConfig
MaxSize: '1'
MinSize: '1'
DesiredCapacity: '1'
VPCZoneIdentifier:
- !Ref myPublicWebSubnet1
- !Ref myPublicWebSubnet2
TargetGroupARNs:
- Ref: WebTierALBTargetGroup
WebTierLoadBalancer:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Subnets:
- !Ref myPublicWebSubnet1
- !Ref myPublicWebSubnet2
SecurityGroups:
- !GetAtt ApplicationLoadBalancerSG.GroupId
WebTierListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref WebTierALBTargetGroup
LoadBalancerArn: !Ref WebTierLoadBalancer
Port: "80"
Protocol: HTTP
WebTierALBTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Port: 80
Protocol: HTTP
UnhealthyThresholdCount: 5
VpcId: !Ref myVPC
AppTierASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
LaunchConfigurationName: !Ref AppTierLaunchConfig
MaxSize: '1'
MinSize: '1'
DesiredCapacity: '1'
VPCZoneIdentifier:
- !Ref myPrivateAppSubnet1
- !Ref myPrivateAppSubnet2
TargetGroupARNs:
- Ref: AppTierTargetGroup
AppTierLaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !Ref myAMIID
SecurityGroups:
- !Ref AppTierSG
InstanceType:
!Ref InstanceType
KeyName: !Ref KeyName
AppTierLoadBalancer:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Subnets:
- !Ref myPrivateAppSubnet1
- !Ref myPrivateAppSubnet2
SecurityGroups:
- !GetAtt InternalLoadBalancerSG.GroupId
AppTierListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref AppTierTargetGroup
LoadBalancerArn: !Ref AppTierLoadBalancer
Port: "80"
Protocol: HTTP
AppTierTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Port: 80
Protocol: HTTP
UnhealthyThresholdCount: 5
VpcId: !Ref myVPC
Database:
Type: AWS::RDS::DBInstance
Properties:
VPCSecurityGroups:
- !Ref DatabaseSG
AllocatedStorage: '20'
PubliclyAccessible: 'true'
DBInstanceClass: db.t2.micro
Engine: MySQL
MasterUsername: MyName
MasterUserPassword: MyPassword
DBSubnetGroupName: !Ref DatabaseSubnetGroup
AvailabilityZone: !Select [ 0, !GetAZs '' ]
DatabaseSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: subnet group
SubnetIds:
- !Ref myPrivateDBSubnet1
- !Ref myPrivateDBSubnet2
- Next login to your AWS account and navigate to the CloudFormation console.
- Click Create Stack.
- Upload your template.

- Give Stack name and Environment name. Click Next and Create Stack.
- The stack will be created in a few minutes.

Author Detail
This blog is written by Checkmate Global Technologies cloud engineering team. Please contact with our technical consultants if you have anything related to cloud infrastructure, DevOps operation management and SaaS based product engineering to be discussed.
