Three-tier architecture: Web Tier, Application Tier, and Database Tier
This tutorial will show how to create a web tier on a public subnet running public EC2 instances. The public EC2 instances are then connected to private EC2 instances. The private EC2 instances will host our Database connection. Let’s get started.
Prerequisites:
AWS account, basic knowledge of how VPC’s, subnets, auto-scaling groups, and load balancers work.
What we will accomplish in this tutorial:
- Create a VPC with two public subnets, and two private subnets.
- Create 2 EC2 instances on public and private subnets with security groups
- Create a static site on public subnets
- Create a Database that is only accessible from our private EC2 instance
We will create our VPC first, I suggest using the “VPC and more” option this allows you to create all of the subnets, the amount of availability zones (AZ’s), Internet gateway, and NAT gateway. Our VPC will reside in the 10.10.0.0/16 CIDR block.
We will allow for two AZ’s, one in us-east1a and us-east1b, two public subnets, and two private subnets.
Our Public subnets will be 10.10.1.0/24 and 10.10.2.0/24, and our private subnets will reside in the 10.10.3.0/24 and 10.10.4.0/24 CIDR block. We will also create a NAT gateway. Amazon allows for ease of use if you select this route, however, you can create the VPC, subnets, Internet Gateway (IGW), and NAT gateway.
AWS provides you with a resource map flow, allowing us to view the connections flow.
Let’s allow for AWS to create our VPC network.
Once created we need to “Assign public IP4 address” to each public subnet.
We will save time and not have to configure the route tables, IGW, and NAT gateways. Here’s all the steps we can skip by allowing AWS to configure our settings with selecting “VPC and more” in the initial VPC creation.
- Creating a routing table for our private subnets.
2. Attach the VPC to our route table.
3. Edit subnet associations for our route table and save associations for our private subnets
5. Attaching our IGW to our VPC, and adding routes to our public subnets
6. Creating a NAT gateway and attaching it to a public subnet and allocating Elastic IP’s
7. Add the NAT gateway to our private route table
Let’s get on with our project and create our Web Tier. Here’s what we will accomplish.
Web Tier
- Minimum of 2 EC2 instances with an OS of your choice (free tier) in an Auto Scaling Group.
- EC2 Web Server Security Group allowing inbound permission from the internet.
- Boot strap static web page or create a custom AMI that already includes the static web page.
Let’s create an EC2 launch template, this will allow us to use an Auto-Scaling Group to use this template, allowing us to keep our EC2 instances persistent. Go to our EC2 dashboard and create launch template.
- Select Amazon Linux
- t2.micro
- Select your key pair or create one
- Create security group or use existing group
- Select the VPC we created earlier add security group roles
- SSH
- HTTP
We can also take care of the DB port number and allow the incoming traffic for our DB, even though this is our public subnet we will use the same security group for both sets of subnets.
We will allow all traffic to port 3306.
We will also need to assign public IP’s to our public subnet. Let’s enable this option.
In the advanced drop down we can scroll all the way down and under user data we will enter the following commands, and we will create our launch template.
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
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
Next we will create an Auto-Scaling group, which will allow persistence with our EC2 instances, if one instance goes down our ASG will automatically launch and boot another instance based on our template.
- Name the ASG
- Select the Launch Template we just created
- We can select our VPC and
- Select our public subnets
- Next create a new load balancer, this will help spread our incoming traffic to our static web site
- Select Application Load Balancer
- The wizard will name it for you
- Select Internet-facing
- Create a target group and the wizard will name it for you
Let’s configure the group size, we will select 2 for desired capacity and minimum capacity, with a maximum of 5.
Let’s look at the overview of our group.
Now we will have to change the security group created earlier with our EC2 instance to our Application Load Balancer. We should now see two instances running in our EC2 dashboard.
Let’s head oveer to our Load balancer option in our EC2 Dashboard and select our DNS name, copy it and paste this in the address bar of a new browser page.
We can see that as we refresh the screen we see the traffic being spread between AZ’s 1a and 1b.
The Application tier
We will create another launch template for our private subnet EC2 instances, this will be the same process as the Web tier portion, with some changes.
We will now create an ASG for our private EC2 instances.
Now that we have completed the ASG and our ALB for our private EC2’s, we should have two new instances running. We now have a total of four instances, two public and two private.
Let’s try and connect to our private instance via the command line, lets first connect to our public instance via SSH. It’s a private connection so if I try SSH’ing from my local machine then I wont be able to connect.
Exactly what we thought, there is no connections allowed to our private instance from outside our VPC.
Now let’s try and PING our private instance from our public instance. We will SSH into our public EC2 and since we have allowed a internet connection via our NAT gateway, we should be able to see the private EC2, and it should be reachable.
We can establish our private EC2 instance can connect to our public instance, now lets 1) ssh from our public instance into our private instance and try and connect to the internet. For this since I am using a keypair that already existed, I had to create it in the public instance and change mode (chmod) to my key pair. 2) ping google.com to check internet connectivity and 3) success, we can see that we were able to connect out of our instance via the internet.
Ok! I was having trouble connecting my private instance, because I forgot to attach the security group, “if there is something not working, it’s always permissions” -Zaire Ali
Now lets create a Database. I will briefly go over the setup, however, here’s the link directly from AWS. We will select in the following order:
- Standard Create
- MySQL
- Free tier
- password and confirm password
- Burstable classes (db.t3.micro)
- Connect to an EC2 compute resource and Choose an EC2 instance
Public Access = no, this will allow us to stay private and not allow access to our database - Choose existing VPC security group
Select our Availability Zone
Create database
Here is an overview of the entire setup.
Let’s head over to the Amazon RDS and assure that we created the DB correct.
- Select our Databases
- Connectivity & Security
- Check the VPC and subnets
- We can see the “rds-ec2” security group created select the group and a new window will pop-up
We can see our rds-ec2 security group and check the inbound rules.
Let’s head back to the console and SSH back into our private instance. So first I have to SSH into my public instance and then SSH into my private instance as shown before. First lets copy our Endpoint from our database.
From the private EC2 lets enter the following commands.
sudo yum install mariadb
mysql -h endpoint -P 3306 -u admin -p
You should be prompted for your password and hopefully we connect.
Congratulations! Database connected to a secure and private EC2 instance. You can deconstruct everything down otherwise you will be billed for the NAT gateway, the elastic IP’s, and the Database. I suggest deleting everything in reverse: Database, ASG, Load Balancers, NAT Gateway, Detach IGW form VPC, VPC, Elastic IP’s in the EC2 dashboard.