Deploying a highly available 3-tier architecture in AWS
Tags: aws, ec2, database, vpc
Published: 2022-10-16 22:21:02

As per Amazon "The 3-tier architecture is the most popular implementation of a multi-tier architecture and consists of a single web tier, an application tier (logic tier), and data tier."

In this article, I am going to show how to build a highly available, fault-tolerance 3-tier architecture consisting of the above 3 tiers with a custom VPC and its components.

You can find all the projects related to EC2, in my [GitHub Repository](https://github.com/awsmine/EC2_projects).

**Web tier**

2 Public subnets
2 Availability zones
Public Route Table
Internet Gateway
Web server Security Group
Nat Gateway
Application Load Balancer - internet facing
Auto-Scaling Group with
  2 EC2 instances with a boot strap static web page

**Application tier**

2 Private subnets
2 Availability zones
Private Route Table
Application server Security Group
Application Load Balancer - internal facing
Auto-Scaling Group with
  2 EC2 instances 
  

**Data or database tier**

2 Private subnets
2 Availability zones
Private Route Table
Database server Security Group
Database RDS

## Objectives:


## Pre-requisites:

- Access to Amazon Management Console with an AWS IAM user Account 
  (not root account).
- Appropriate IAM with Admin permissions



## Resources Used:
 
Know how to create [EC2 instances](url), [Sub Groups](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html), and [Key pairs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html).

I have referred the AWS documentation to create [Custom VPCs](https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html) and [setting up Auto-scaling coupled with Application Load Balancer](https://docs.aws.amazon.com/autoscaling/ec2/userguide/tutorial-ec2-auto-scaling-load-balancer.html).



**_Let's get started!_**


## Steps for implementation to this project: 

- Create a VPC and its components — 6 Subnets (2 each in 2 
availability zones for 3 tiers — Public and Private ), Internet Gateway, NAT Gateway, 3 Route tables (1 Public and 2 Private).
- Create 3 Security Groups (for 3 tiers).
- Create 2 Application load balancers, 1 for the Web tier 
  (Internet-facing) and an another for Application tier (Internal).
- Create Launch Templates for the Web Tier (WebLT) and an Application Tier (AppLT).
- Create the Web tier and an Application tier with 2 EC2 Instances with Auto-scaling groups.
- Create a DB subnet from RDS page. Create the Database tier using RDS (free tier). Configure 3rd Security group to accept traffic from Application Tier Security Group.
- Verify the Web tier access from the Internet and ping the Application tier. You can also SSH into it via Bastion Host (jump host).
- Cleanup
- What we have done so far




## Create a VPC and its components — 6 Subnets (2 each in 2 availability zones for 3 tiers — Public and Private ), Internet Gateway, Nat Gateway, 3 Route tables (1 Public and 2 Private)



**Create a VPC**
VPC dashboard
Name tag - project-VPC
IPv4 CIDR - 10.0.0.0/16
Click Create VPC


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0d5mqy4x3nvt8dfu0n2h.png)




## Create 6 Subnets - WebPubSub1a, WebPubSub1b, AppPriSub1a, AppPriSub1b, DBPriSub1a and DBPriSub1b

Go to Subnets
Create Subnets
Select - myVPC
Subnet name - WebPubSub1a
Availability Zone - us-east-1a
IPv4 CIDR block - 10.0.1.0/24

Add new subnet
Subnet name - WebPubSub2b
Availability Zone - us-east-1b
IPv4 CIDR block - 10.0.2.0/24

Add new subnet
Subnet name - AppPriSub1a
Availability Zone - us-east-1a
IPv4 CIDR block - 10.0.11.0/24

Add new subnet
Subnet name - AppPriSub2b
Availability Zone - us-east-1b
IPv4 CIDR block - 10.0.21.0/24

Add new subnet
Subnet name - DBPriSub1a
Availability Zone - us-east-1a
IPv4 CIDR block - 10.0.12.0/24

Add new subnet
Subnet name - DBPriSub2b
Availability Zone - us-east-1b
IPv4 CIDR block - 10.0.22.0/24

Create subnet


**Web Public Subnets (WebPubSub1a, WebPubSub1b) to Enable auto-assign public IPv4 address**

Modify the following settings to Auto-assign IP settings which enables you to automatically request a public IPv4 or IPv6 address.

Click WebPubSub1a
Actions
Edit subnet settings 
Enable auto-assign public IPv4 address - check
Save

Repeat for WebPubSub1b



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/01tuo6mg74o4uva8x8bl.png)



**Internet Gateway**
Attach this to newly created VPC and verify.

Go to Internet gateways
Create internet gateway
Name tag - IGW
Create internet gateway

Actions
Attach to VPC - myVPC
Attach internet gateway


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m21bnn29og42nw53tg2m.png)



**Create a NAT Gateway (NatGW) with Elastic IPv4 address in Web Public Subnet 1a (WebPubSub1a)** 
Create NAT gateway
Name - NatGW
Subnet - WebPubSub1a
Click Allocate Elastic IP
Create NAT gateway


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nztg0d645745lquwrgj1.png)



**3 Route tables — Public (PubRT) and 2 Private (AppRT and DBRT)**

Go to Route tables
Create route table
**Name - PubRT**
VPC - project-VPC
Create route table

- Add an Inbound rule to Public Route Table (PubRT) to allow Traffic from the Internet — attach the Internet Gateway (IGW).

Click PubRT
Routes
Edit routes
Destination - 0.0.0.0/0
Target - IGW
Save Changes


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4n9j4fgmhkafhmiyhtlx.png)



- Associate the Public Subnets (WebPubSub1a, WebPubSub1b) to the Public Route Table (PubRT).

Click PubRT
Subnet associations
Edit subnet associations
Check - WebPubSub1a, WebPubSub1b
Save associations


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bqfc5zpighi9gm6ywtj2.png)

=====

Go to Route tables
Create route table
**Name - AppRT**
VPC - project-VPC
Create route table


- Add an Inbound rule to attach NAT Gateway (NatGW) to the Private Route Table (AppRT). Thus, instances in the private subnet can send requests to the internet through the NAT gateway over IPv4 (for example, for software updates and patches).


Click AppRT
Routes
Edit routes
Destination - 0.0.0.0/0
Target - NatGW
Save Changes


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdosnfjjjvidra19o8zr.png)




- Associate the Private Subnets (AppPriSub1a, AppPriSub1b, DBPriSub1a, DBPriSub1b) to the Private Route Table (AppRT).




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wpqzn2q9chgoj6oega8.png)


=====

Go to Route tables
Create route table
**Name - DBRT**
VPC - project-VPC
Create route table


The DBRT allows communication within the VPC. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9sglkwcz9m38dxb87i96.png)




- Associate the Private Subnets (DBPriSub1a, DBPriSub1b) to the Private Route Table (DBRT).



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbbk0daajsqmvq3gg1bn.png)


## Create 3 Security Groups (for 3 tiers).


**A security group** acts as a virtual firewall to an EC2 instance, it controls the inbound and outbound traffic for the instance.

Configure 2 Security groups, 1 for the Web tier only to accept traffic from the ALB (Application Load Balancer), and the other for Application tier to accept traffic from the Web tier security group.

- WebPubSG - Create Web Security Group (WebPubSG) and add an Inbound Rule to allow any IPv4 traffic through port 80 (HTTP) from outside world and port 22 (SSH) in your network.

Go to Security groups
Create security group
Security group name - WebSubSG
VPC - project-VPC

Inbound rules
SSH - Port 22 - 0.0.0.0/0
HTTP - Port 80 - 0.0.0.0/0

Create security group


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/siafthazf6yvd5ygdmrs.png)


- AppPriSG - the other for Application tier and add an Inbound 
Rule to allow Echo Request (ping) thru ICMP and SSH thru port 22 thru TCP Protocol from Web Server Group (WebPubSG) and outbound rule to database Security group (DBPriSG)


Go to Security groups
Create security group
Security group name - AppPriSG
VPC - project-VPC

Inbound rules
SSH - Port 22 - WebPubSG
All ICMP-IPv4 - Port All - WebPubSG

Outbound rules
SSH - Port 22 - DBPriSG
All ICMP-IPv4 - Port All - WebPubSG

Create security group


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sckc33uf06105ojyay2x.png)


- DBPubSG - Create Database Security Group (DBPubSG) and add an Inbound Rule to allow RDP access thru port 3306 from App Server Group (AppPriSG).

Go to Security groups
Create security group
Security group name - DBPriSG
VPC - project-VPC

Inbound rules
SSH - Port 22 - AppPubSG

Create security group


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eayqr31gqjj6nasugi9k.png)


## Create 2 Application load balancers, 1 for the Web tier (Internet-facing) and an another for Application tier (Internal).

**Creating Web Load Balancer (WebALB) with Internet-Facing**

On EC2 Dashboard in the AWS Management Console
Load Balancing
Load Balancers
Create Load Balancer
Application Load Balancer
Create
Under Basic Configuration
Load balancer name - WebALB
Scheme — select “Internet-facing”
IP address type - select IPv4.
Under Network mapping
VPC - project-VPC
Under Mappings

select Availability Zones and Public Subnets — WebPubSub1a, WebPubSub1b

Security groups — WebPubSG
Listeners and Routing — Protocol HTTP Port 80

Click **Create a Target Group** (This will open a new tab)
create a Target Name **WebALBTG**
Protocol — HTTP, Port — 80, VPC — project-VPC 
Take all defaults 
Next
Click Create Target Group


Next — on Load Balancer page 
refresh for Target group 
select WebALBTG
Create Load Balancer

It takes 3-4 min to become active


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6wuptx1wnhx7fqh1d7w.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcazijngzaray4qssq5k.png)


**Creating App Load Balancer (AppALB) with Internal**

On EC2 Dashboard in the AWS Management Console
Load Balancing
Load Balancers
Create Load Balancer
Application Load Balancer
Create
Under Basic Configuration
Load balancer name - AppALB
Scheme — select “Internal”
IP address type - select IPv4.
Under Network mapping
VPC - project-VPC
Under Mappings

select Availability Zones and Public Subnets — WebPubSub1a, WebPubSub1b

Security groups — AppPriSG
Listeners and Routing — Protocol HTTP Port 80

Click **Create a Target Group** (This will open a new tab)
create a Target Name **AppTG**
Protocol — HTTP, Port — 80, VPC — project-VPC 
Take all defaults 
Next
Click Create Target Group


Next — on Load Balancer page 
refresh for Target group 
select AppTG
Create Load Balancer

It takes 3-4 min to become active




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hraa1gqze0bci82m55l.png)






![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y44irzao1hkjptd25dnz.png)



## Create Launch Templates for the Web Tier (WebLT) and an Application Tier (AppLT).

Please refer to my [previous article](https://dev.to/aws-builders/highly-available-web-site-with-ec2-custom-vpc-in-3-public-subnets-33kb) about creating a similar set-up with extensive diagrams. But I will walk you thru the setup here again.

**Creating a Launch Template for Web Tier (WebLT)**
    
On EC2 Dashboard in the AWS Management Console
Under Instances
Launch Templates
Create Launch Template
Launch Template Name — WebLT
Template version description — WebLT
Click Quick Start / Amazon Linux AWS 
AMI — ami-026b57f3c383c2eec
Instance Type — t2.micro
Key pair name — NVirKey
Under Network Settings — 
Subnet - WebPubSub1a
Select existing security group — WebPubSG
Under Advanced network configuration 
Network Interface 1 — 
Auto assign Public IP — Enable
Advance details 

Userdata — paste the Bootstrap Script to install Apache Web Server with your customized message

```
#!/bin/bash
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
EC2AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
echo '<center><h1>This Amazon EC2 instance is located in Availability Zone:AZID </h1></center>' > /var/www/html/index.txt
sed"s/AZID/$EC2AZ/" /var/www/html/index.txt > /var/www/html/index.html
```

Create Launch Template


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trfkdwqix5xp4iekxry3.png)


**Create Launch Templates for an Application Tier (AppLT)**

On EC2 Dashboard in the AWS Management Console
Under Instances
Launch Templates
Create Launch Template
Launch Template Name — AppLT
Template version description — AppLT
Click Quick Start / Amazon Linux AWS 
AMI — ami-026b57f3c383c2eec
Instance Type — t2.micro
Key pair name — NVirKey
Under Network Settings — 
Subnet - AppPriSub1a
Select existing security group — AppPriSG
Under Advanced network configuration 
Network Interface 1 — 
Auto assign Public IP — Enable 
Create Launch Template


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ffez5ly1i3p8thlqsns.png)




## Create Auto-scaling groups for the Web tier and an Application tier with 2 EC2 Instances.

**Create Auto-scaling groups for the Web tier with 2 EC2 Instances.**

On EC2 Dashboard in the AWS Management Console
Auto scaling
Auto scaling groups 
**Create auto scaling group**
**Name — WebASG**
Launch Template / Refresh
select — WebLT
Next
Under Network
VPC
select - project-VPC
Availability Zones and subnets
select WebPubSub1a, WebPubSub1b
Next
Under Configure advanced options
Load balancing
Attach to an existing load balancer
Existing load balancer target groups
Refresh and select WebALBTG
Next
Group size
Desired capacity — 2
Minimum capacity — 2
Maximum capacity — 3
Target scaling policies
Name - Target scaling policy
Take default settings
Next, Next, and Next
Review 
Create auto scaling group


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/guq761dzjl6agj5v7st5.png)


**Create Auto-scaling groups for an Application tier with 2 EC2 Instances.**

On EC2 Dashboard in the AWS Management Console
Auto scaling
Auto scaling groups 
**Create auto scaling group**
**Name — AppASG**
Launch Template / Refresh
select — AppLT
Next
Under Network
VPC
select - project-VPC
Availability Zones and subnets
select AppPriSub1a, AppPriSub1b
Next
Under Configure advanced options
Load balancing
Attach to an existing load balancer
Existing load balancer target groups
Refresh and select AppTG
Next
Group size
Desired capacity — 2
Minimum capacity — 2
Maximum capacity — 3
Target scaling policies
Name - Target scaling policy
Take default settings
Next, Next, and Next
Review 
Create auto scaling group


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ri9fz93pxipxtm7nbie.png)


## Create a DB subnet from RDS page. Create the Database tier using RDS (free tier). Configure 3rd Security group to accept traffic from Application Tier Security Group.

**Create a DB subnet from RDS page.**

A DB subnet group designate for your DB instance

Om Amazon RDS Dashboard
Subnet groups
Create DB subnet group
Under Subnet group details
Name
DBSub
Descripton
DBSub
VPC
project-VPC
Availability Zones
us-east-1a, us-east-1b
Subnets
DBPriSub1a, DBPriSub1b


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a90jrgj5m4rxaxbi0spw.png)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ksfe01qyxfcq8ykwjwc.png)






**Create a RDS Database with MySQL engine**

On RDS Dashboard
Create database
Select - Standard Create 
Create the RDS Database 
Engine options
MySQL
Templates
Free tier
defaults
Master username as Master password123
Defaults
VPC - project-VPC
VPC security group
Choose existing
Existing VPC security groups
DBPriSG
Availability Zone
us-east-1a



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihytplw1bdqz4iqmgjr0.png)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/436pan5kxv9a2f4wmof7.png)





with options shown in the diagram.

Note: VPC — myVPC, DB subnet group — dbsub, Security Group — DBPriSG having inbound traffic from AppPriSG ONLY, Availability zone and Subnets — DBPriSub1a, DBPriSub1b




## Verify the Web tier access from the Internet and ping the Application tier. 

copy one of the Public IP of Web Instance
54.208.92.121
Log into it using SSH Client with this command

**`ssh -i "NVirKey.pem" ec2-user@54.208.92.121`**

ping the Application tier

**`[ec2-user@ip-10-0-1-35 ~]$ ping 10.0.11.221`**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9w3up3ytebtwzq219d90.png)



## Cleanup:


Delete all the AWS resources 

Delete Autoscaling Group
Application Load balancer
Tatget Group
VPCs
Terminate EC2



## What we have done so far:
Created a highly available, fault-tolerance 3-tier architecture consisting of the Web tier, Application tier, and Database tier with a custom VPC and its components.