Designing a 3-Tier Architecture in AWS
In a typical client-server application, you will have three layers talking to each other, i.e. the front-end, the back-end, and the database. Each of these layers does a specific task, and it's prudent to manage them differently. In architecture lingo, these layers are the presentation, business logic, and data storage layers.
AWS provides different cloud computing services that can be leveraged to achieve this architecture. In this article, we will use the following AWS services to create our architecture: EC2, ELB, ASG, VPC, SGs, and IGW.
But what does this 3-tier architecture solve as compared to a 2-tier architecture?
- Scalability: each tier can scale differently when you need them to. For instance, we can scale horizontally to increase computing resources. We can configure the ASG can help identify the load that is coming to our existing EC2 cluster, and if a threshold is reached or breached, an action will be triggered to add more resources (scale-out) or reduce the resources to a desired number in case of low traffic (scale-in). This can also help save money, as the setup does not have any idle resources.
- Modularity: Modularity results in independent components that are easier to scale, secure and manage. A modular application is made up of loosely coupled components. This type of architecture allows a team to make changes to different components quickly, and also recover from unexpected disasters just as easily.
- High Availability: AWS is a cloud provider that offers engineers an infrastructure that supports redundancy and fault tolerance. With Availability Zones (AZs)sitting in different geographical locations, our 3-tier application is safe from calamities such as earthquakes, flooding, or even power outage that may cause loss of service to our application. Additionally, load balancers to distribute load, and autoscaling groups can be used to ensure the services are not unavailable due to lack of computing resources.
- Security: security has to be baked into our design from the onset. AWS provides private IPs for this. Resources in a private subnet can only communicate within themselves. They do not have direct access to the internet. They require a NAT Gateway or NAT Instance for that. Users on the Internet can only reach the front end through the application load balancer (ALB).
Follow the steps below to set up your architecture. Some of the steps here are for reference only and can be intuitively followed directly from the particular AWS console, so I won’t be specifying the details but providing more of a checklist.:
- Set up the Virtual Private Network: This is a virtual network where your application will live. Choose an appropriate CIDR range that will not be too big or too small. A CIDR range of 10.0.0.0/16 will give you about 65,536 IP Addresses which will be enough for this test. Search for “VPC” in the search bar and click on it to create one.
Click on Create VPC, enter your CIDR Block, and click on Create VPC.
2. Setup the Internet Gateway: the Internet Gateway, or IGW, enables communication between applications in your VPC to the Internet. It is attached to your VPC. Search for Internet Gateway in the search bar and create it.
You will need to attach your VPC to this IGW for it to work. To do that,
- Select the IGW
- Click on Actions
- Select Attach
- Select the VPC to attach
.This will take a moment and should appear as Attached in your console, with a green tick.
3. Setup four subnets: A subnet is a section of a VPC used to group resources together with their own IP ranges that are within the VPC CIDR range. For this, you will need both public and private subnets. Public IPs can access the Internet while Private IPs cannot. Most secure parts of our applications need to live in private subnets.
In the VPC console, click on Subnets on the left menu. Click on Create Subnet
4. Setup routing table: Depending on how you configure routing for the subnets, the result is either a public or a private subnet. The public route table will define which subnets will have direct access to the internet ( ie public subnets) while the private route table will define which subnet goes through the NAT gateway (ie private subnet)
To make a subnet public or private you will need to associate these route tables with the particular subnet. To do this, select your route table, click on Actions, and then Edit Subnet Association. Select the subnet that you need to make private or public and associate it with the appropriate route table.
For the public route table, we will need to route traffic via the Internet gateway. This is how it will communicate with the rest of the world. To do this, select the public route table, click on actions, select Edit route, and
5. Setup a Nat gateway for private subnets: the NAT gateway is an AWS-managed service that enables private subnets to access the internet. it incurs a charge, so best to clean up after use. To create, Click on NAT Gateways on the VPC page, click on create. The next step will need the Subnet ID that you want it to live in. Be sure to check the name in the Select Subnet dropdown.
6. Setup the elastic load balancer: the use of the load balancer is to distribute load coming to the instances in the application. From our architecture, the front-end application will receive load via the load balancer, while the backend will receive traffic through another internal load balancer. We will need to create two load balancers to fulfill this.
a) From the search bar, search for EC2 and scroll down to the Load Balancing section at the bottom of the left menu.
b) Click on Create for the Application Load Balancer option of the “Compare and select load balancer type”.
c) Give the load balancer an appropriate name and select Internet facing for front-end applications, and internal for the backend applications. These will need private or public addresses and cannot be mixed up.
d) Under the Availability Zone, for the internet-facing Load Balancer, we will select the two public subnets while for our internal Load Balancer, we will select the two private subnets.
e) Under the Security Group, we only need to allow ports that the application needs. For instance, we need to allow HTTP port 80 and/or HTTPS port 443 on our internet-facing load balancer. For the internal load balancer, we only open the port that the backend runs on (eg: port 3000) and make the port only open to the security group of the front end. This will allow only the frontend to have access to that port within our architecture
7. Setup auto scaling group: an auto-scaling group allows us to automatically adjust the compute power serving our application based on needs.
a) Auto Scaling Group needs to have a common configuration that instances within it must have. This includes image settings, OS versions, Instance size (ec2 compute), storage and volumes, network settings, and even user data. This is made possible by a launch configuration or template. A Template is a more recent approach by AWS and allows us to have a living document that can be saved, edited, and even version controlled. Click on Create Launch Template to create one.
b) Once created click on refresh on this page and select your Template.
c) Select the VPC, AZs, and Subnets to use your ASG.
d) Under the group size you can specify the size of the Auto Scaling group by changing the desired capacity. You can also specify minimum and maximum capacity limits. Your desired capacity must be within the limit range set by the minimum and maximum capacity.
e) Under the Configure scaling policies, we want to instances when the average CPU utilization at 50%. We also want to scale down when utilization is below 50% or ‘normal’.
To do this we need to:
- Select Average CPU Utilization from the Metric type drop-down menu. (There are other config options in the drop-down, but that will depend on your config target as described in 7(e) above)
- Enter target value, in this case, 50
- Since we need to scale in too, ensure we do not check the ‘Disable scale-in to create only a scale-out policy’ option.
f) Go ahead and create this ASG
g) Follow the same procedure to create the second ASG for our backend services.
And that's it! Your three-tier application is ready for deployment. Find out here how to do this with AWS Beanstalk in a two-tier architecture.