Tiers Aren’t Just for Cakes: The AWS 3-Tier Architecture
Tiers aren’t just for cakes. Tiers are, however, an important part of providing a robust foundation for building scalable, maintainable, secure, and modular applications. But first, what exactly is a three-tier architecture?
A three-tier architecture in AWS refers to a design pattern where an application or system is divided into three distinct layers or tiers: presentation, application, and data. Each tier performs specific functions and communicates with the others to deliver the desired functionality.
- Presentation Tier (Front-end): This is the user interface layer where the application’s presentation logic resides. It handles user interactions, displays information, and collects user inputs. In AWS, this tier typically consists of web servers, content delivery networks (CDNs), and client-side technologies like HTML, CSS, and JavaScript.
- Application Tier (Middle-tier): This layer contains the business logic and application processing logic. It handles the application’s core functionalities and processes user requests received from the presentation tier. In AWS, this tier often involves application servers, load balancers, and server-side technologies like Node.js, Java, or .NET.
- Data Tier (Back-end): This layer is responsible for managing data storage and retrieval. It stores application data in databases or data stores and provides data manipulation and querying capabilities. In AWS, this tier typically involves database services such as Amazon RDS, DynamoDB, or Amazon S3 for object storage.
Join me as I dive deeper into building out each layer of this intriguing architecture. The best way to learn is to get your hands dirty, so let’s get baking!
Part I- Web Tier Objectives:
- Create two public subnets with a minimum of two EC2 instances with an OS of your choice (free tier) in an Auto Scaling Group.
- Create an EC2 Web Server Security Group that allows inbound permission from the internet.
- Create a boot strap static web page or a custom AMI that already includes the static web page.
- Create a public route table and associate the two public subnets.
Step 1: Create your VPC and subnets
In AWS, access the VPC console and click Create VPC. Give your VPC a name and assign a CIDR block. We’ll be using 10.0.0.0/16 for this example. Click Create VPC.
Once your VPC is created, select Edit VPC settings from the Actions menu. Then, check the box to Enable DNS hostnames and click Save.
Click on Subnets in the sidebar and click Create subnet. Chose the VPC you just created from the dropdown. We’ll be creating multiple subnets, so be sure to name your subnets in such a way to ensure that you know the difference in public and private subnets and also to which tier they belong.
Since we are creating two subnets for each tier, one subnet should be in availability zone A and the other in B.
When creating your CIDR blocks, it is helpful to use an online tool such as CIDR.xyz to provide you with a range of IP addresses, or you can simply change the third octet to 1, 2, 3, etc. to ensure there is no overlap. Click Add new subnet and repeat these steps to create your next subnet. Once you have created all six, click Create subnet.
Select one of your public subnets and click Actions and Edit Subnet Settings.
Click the box to enable auto-assign public IPv4 address, then click Save. Repeat this step for your other public subnet.
Step 2: Create a security group
Click on Security groups on the left. Then, click Create security group. Give your web tier security group a name. Add a description and chose your VPC from the dropdown.
Configure the inbound rules to allow all traffic from HTTP, HTTPS, and SSH. Leave the default outbound rules to allow all traffic. We will come back later to adjust these rules to only allow traffic from our bastion host. Click Create security group.
Step 3: Create an internet gateway and attach to VPC
In the sidebar, click on Internet gateway and then click Create internet gateway. Name your gateway and click Create internet gateway.
To attach your VPC to the internet gateway, you have one of two options. You may either click Actions and Attach to VPC or you can click Attach to a VPC in the green banner.
Select your VPC from the Available VPCs dropdown menu and click Attach internet gateway.
Step 4: Create a route table
Click on Route tables in the sidebar. Identify the route table associated with your VPC by selecting the route table and scrolling down to check the Subnet associations tab. You should see your public subnets listed under subnets without explicit associations.
Give this route table a name so that you can easily identify it.
Next, click Actions and Edit routes.
Select Add route. Select 0.0.0.0/0 under Destination and Internet gateway from the Target dropdowns. Find your gateway and Save changes.
Step 5: Create a NAT gateway
In the sidebar, select NAT gateways. Click Create NAT gateway and give your gateway a name. Associate one of your public subnets to create the NAT gateway. Next, click Allocate Elastic IP to assign an Elastic IP address to the NAT gateway. Then, click Create NAT gateway.
Step 6: Create a launch template
Access the EC2 console by typing EC2 in the AWS search bar. Click on Launch Templates in the sidebar and then Create launch template. Give your launch template a name and check the Auto Scaling guidance box which provides guidance to help us set up a template that we can use with EC2 Auto Scaling.
Scroll down to choose the AMI you want to use, but ensure it is free tier eligible.
Under instance type, select t2.micro. You may create a new key pair or use one that is already created.
Under Network settings, select existing security group. Chose the web tier security group you created earlier.
Under Advanced network configuration, select Enable from the Auto-assign public IP dropdown.
Scroll down to Advanced details and input the following script to run Apache in the User data field. Then, click Create launch template.
#!/bin/bash
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
echo "<html><body><h1>Welcome Bakers!!!</h1></body><html>" > /var/www/html/index.html
Step 7: Create an Auto Scaling Group
Scroll down to Auto Scaling Groups in the left sidebar. Click Create Auto Scaling group. Name your Auto Scaling group and select the Launch template you created earlier. Scroll down and click Next.
Under Network, chose your VPC and both of your web tier (public) subnets. Click Next.
Under Load balancing, we are going to leave it as No load balancer. We will create our load balancer a little later. Scroll down and click Next.
Under Group size, set the desired capacity at 2, minimum capacity at 2, and maximum capacity at 5. Scroll down and click Next.
There will be no changes on the next two pages, so it’s ok to click Skip to review. Verify all of your information is correct on the Review page and click Create Auto Scaling group.
Step 8: Create Bastion host
Since we are creating a multi-tier application where different parts of the application are deployed on different servers, we will use a bastion host to manage access between these tiers.
What exactly is a bastion host? A bastion host is a specially designated server that acts as a secure gateway between the public internet and your private network. It is the primary entry point for accessing the internal resources of the private network, such as servers and databases. This ensures secure communication between the different layers so that they are not directly exposing to the internet.
To create the bastion host, go to EC2 dashboard and click Launch instance. Name your instance, select Amazon Linux 2 AMI, t2.mirco Instance type, and then choose your key pair.
Under Network settings, chose your VPC and one of your public subnets. Under Firewall, click Create security group and give it a name and a description. Then change the inbound SSH security group rules so that the source type is your IP address. Then click Launch instance.
Once the bastion host is launched, we will need to obtain the public IP address. Select your bastion host EC2 instance and scroll down to copy the public IP address. Then click on Security groups in the sidebar and select your web tier security group. Click Actions and Edit inbound rules. For the SSH rule, we will change the source to reflect the public IP address of the bastion host. This will only allow SSH traffic from the bastion host to our web tier.
Time to move on to our application tier.
Part II- Application Tier Objectives:
- Create two private subnets with a minimum of two EC2 instances with an OS of your choice (free tier) in an Auto Scaling Group.
- Create an EC2 Application Server Security Group that allows inbound permission from the Web Server Security Group.
- Associate with a private route table.
Step 1: Create a security group
Click on Security groups on the left. Then, click Create security group. Give your application tier security group a name. Add a description and chose your VPC from the dropdown.
Configure the ICMP and HTTP inbound rules to allow traffic from the web-tier security group as the source. Create a rule for SSH traffic with the security group of the bastion host as the source. Leave the default outbound rules to allow all traffic. Click Create security group.
Step 2: Create a route table
Click on Route tables in the sidebar and click Create route table. Give your application tier route table a name and attach it to your VPC. Click Create route table.
Click Actions and Edit subnet associations.
Select the private subnets for your application tier and click Save associations.
We need to provide internet access to the private route table through the NAT Gateway. While still in the private route table, click on Routes and Edit routes. Click Add route, select the CIDR 0.0.0.0/0, and set target to the NAT gateway. Save changes.
Step 3: Create a launch template
Access the EC2 console by typing EC2 in the AWS search bar. Click on Launch Templates in the sidebar and then Create launch template. Give your application tier launch template a name.
Chose the same AMI, instance type, key pair. Chose the app tier security group. Click Create launch template.
Step 4: Create an Auto Scaling Group
Scroll down to Auto Scaling Groups in the left sidebar. Click Create Auto Scaling group. Name your Auto Scaling group and select the app tier Launch template you just created. Scroll down and click Next.
Under Network, chose your VPC and your application tier (private) subnets. Click Next.
We will keep the remainder of the settings the same as our web tier auto scaling group. When you reach the end, verify that all of your information is correct on the Review page and click Create Auto Scaling group.
On to our database tier!
Part III- Database Tier Objectives:
- Create a free Tier MySql RDS Database.
- Create and configure a Database Security Group that allows inbound traffic for MySQL from the Application Server Security Group.
- Create 2 private subnets and associate them with a private route table.
Note: No need to use Multi-AZ but be sure to document how you would add it
Step 1: Associate database subnets to private route table
Click on Route tables in the sidebar and select your private route table. Add the database subnets to the private route table by clicking Actions and then Edit subnet associations. Select your database subnets and click Save associations. If you check your resource map, it should look similar to the image below.
Step 2: Create database subnet group
Return to the AWS console and search for the RDS service. On this page you will need to scroll down and click on Subnet groups and Create DB subnet group. Give your group a name and select your VPC.
Next, chose your two availability zones and the remaining subnets for our database tier. Click Create.
Notice the message that states “For Multi-AZ DB clusters, you must select 3 different Availability Zones.” If we were creating multi-availability zone DB clusters, we would need to select three subnets in three different availability zones. However, we will not be doing that for this project so we are only selecting our two subnets.
Step 3: Create your database
To begin, click on Create database. We will select Standard create and the MySQL engine type.
Under templates, choose the free tier.
Enter a name for your database. Then, you can either leave the default “admin” username or create a new master username and password.
Leave the current instance configurations and storage settings. Under Connectivity you will need to select your VPC. Select the DB subnet group you previously created. Public access should be set as “No” since we will only access the database through the Application Tier.
It’s time to create our security group. Select Create new security group, give it a name, then click Create database.
Step 4: Edit security group rules
After your database is created, navigate to the Connectivity & security tab and click on your security group.
Scroll down and click Edit inbound rules. Initially when I tried to select the application tier security group as the source, I received this error message.
To resolve this issue, I deleted this rule in it’s entirety and then recreated it with the same information. Next, hit Save rules.
We’re almost done baking! However, no great baker would serve their dessert without giving it a taste test first, so it’s time to test out how our architecture is functioning!
Part IV- Testing, testing, testing
To verify that your website can be reached successfully, you will need one of the Public IPv4 addresses. Return to the Instances page in EC2 and select a public instance. Under Details, copy the Public IPv4 address and paste it into a web browser.
And the moment you’ve all been waiting for…. Success!!
Now, let’s see if we can SSH into our bastion host. This part definitely gave me a run for my money because I am using a Windows computer. Apparently this was one of those times when having a Mac was a better choice, and I don’t say that often (No offense to those ride or die Apple fanatics, don’t come for me!) The biggest struggle I faced was getting my key pair to the bastion host so that it can SSH into another instance. I ended up getting this accomplished by using SSH agent forwarding, but it definitely took me a few hours to figure out how to do this. Let me make your life easier by attaching the directions on how to complete this step here.
So here we go….First, I will SSH into my bastion host.
Next, I am going SSH into one of my web tier instances using this command:
ssh ec2-user@<Public_IP_Address>
Before we move any further, we need to verify the connectivity between the first two layers. Let’s ping the private IP4 by running:
ping [privateIP4]
Perfect! We have reached the private IP successfully, so now we can add load balancers before our web and application tiers.
Part V- Add Load Balancers
Step 1: Create Target Groups
Since we need to tell the load balancer where to send traffic, we will start by creating target groups. In the sidebar, scroll down to Target Group and then click Create target group. Leave the target type as Instances.
Input a Target group name and select your VPC from the dropdown. Then, click Next.
We will go ahead and register targets by selecting the web tier instances and clicking the button that says “Include as pending below”. Scroll down and click Create target group.
Repeat these steps to create a second target group for the application tier.
Step 2: Create Load Balancers
In the sidebar, select Load Balancers and then Create load balancer. Choose the Application Load Balancer and click Create.
Give your load balancer a name and leave the default scheme and IP address type.
Under Network mapping be sure to chose your VPC. Under Mappings, select the checkbox next to each of your subnets. The load balancer will route traffic to targets in these Availability Zones only.
Under Security groups, click the link to create your security group. Since this is our web tier load balancer, we will set an inbound rule for all HTTP traffic.
Under Listener HTTP:80, change the default action to forward to the target group you created. Scroll down and click Create load balancer.
Repeat these steps to create a load balancer for your application tier. A few things to keep in mind as you create this load balancer:
- Choosing the subnets and target group for your app tier
- When you choose your Scheme, be sure to select Internal instead of Internet-facing (Trust me, you do not want to forget this step. It will make your entire cake fall).
- When you create your security group for this load balancer, set the source of your ICMP and HTTP as the web tier security group.
Step 3: Edit inbound security group rules
Before testing our connectivity, we will need to update our security group rules. Click on Security groups in the sidebar and select the security group belonging to your web tier. Click Actions and then Edit inbound rules. Delete the current HTTP rule and create a new one with the Source being the security group of the web-tier load balancer. Click Save rules.
Next, select your application tier’s security group and delete the ICMP and HTTP rules. Create new rules for both by selecting the security group for the application tier load balancer as the Source. Click Save rules.
Step 4: Verify the site can be reached
Since we are using load balancers, we will test connectivity by copying and pasting the web-tier load balancer DNS name into the browser. You should be able to see your website if everything is set-up correctly.
Next, we’re going to copy and paste the application tier load balancer DNS and use that to ping to ensure that the application tier is working correctly.
If this works for you on the first try, congratulations!! I had to go back to ensure that my security groups were set up correctly the first time I tested connectivity. But alas, everything is now working correctly! Time to enjoy the success of creating your first three-tier architecture!
Be sure to check out some of my other projects on my way to becoming a DevOps Engineer!