Victor Leung
Victor Leung
BlogAI SolutionAlphaAlgoFlower shopFX CombineIEESushi ClassifierWealth Agile

Setting up a three-tier architecture on AWS

September 18, 2022

Today, I am going to demonstrate how to use Virtual Private Cloud (VPC) services to setting up a three-tier architecture on Amazon Web Service (AWS). The architecture diagram below shows the setup, which is mainly divided into three layers.


The first layer is the presentation layer. Users can directly access the public subnet through the gateway. The second layer is the logic layer, which mainly deals with business logic. In this layer, I put it on the private subnet to limit the access and put it behind the load balancer, which can be flexibly and horizontally expanded to handle different time periods with different traffic demands. The third layer is the data layer. In this private subnet, the MySQL database is deployed and only allowed access through the second layer. To improve availability, I deploy to two Availability Zones, and the database is backed up to the other Availability Zone, ensuring that in the event of a loss of one Availability Zone, application services can still be maintained.

First, I will create a VPC network, which I call victorleungtwdemo. According to the architecture diagram, I choose and my large subnet segment has been created successfully. Notice here /16 subnet has a number of IP addresses 65535. If I set the subnet to /24, that is only 256 IP addresses. If I set it to the /28 subnet, it would be only 16 IP addresses, which would not be enough for future expansion.


Next, I will create the subnets, I am going to create six subnets, the first subnet is called pub-subnet-1, and I must choose the previous created VPC, and then choose the right availability zone A. I first choose area A, then choose the right range of IP addresses. The VPC set-up as a /16 bit subnet and in order to consider scalability, I cannot block the subnet as it would have no scalability, therefore let me set a /24 subnet instead.


And so on and so forth, I create the remaining five subnets. You can take a look at the diagram below, I have created six subnets. You can see the public subnet 1, the public subnet 2, the private subnets 1, 2, 3 and 4 as well as the corresponding Availability zones.


Next, I would create the corresponding gateway. I create a new gateway victorleungtw-igw.


After it is created, I can assign it to my VPC. Which VPC should I choose? Let's choose victorleungtwdemo VPC.


Then you can take a look at the routing table. You can see that there is a default routing table after the VPC is created, which is the main routing table. You can click it and see the routing entries. When you create any route in the table, it has a default routing entry, which is also the first entry, that is to say, the subnets I create are all connected by default. You cannot delete or change this route.

Let's create a new routing table, the public pub-route can connect data to the public network and choose my victorleungtwdemo vpc, I will change the name of the original routing table to priv-route. For the subnet of the database, there should be no communication to this subnet from the Internet. Create another routing table, I call it nat-route, and I have chosen the right victorleungtwdemo VPC as well.


At the moment, I already have three routing tables. You can see that it has a default route after creation.


Let's specify the routes related to the public routing table pub-route and add a route to the internet. I refer it to target victorleungtw-igw and then click save. In other words, all machines in this subnet will be able to access the public internet.


Next, I am going to associate my public subnets. Which are my public subnets? Add pub-subnet-1 and pub-subnet-2.


Then I add nat-route, and NAT related to priv-subnet-1 and priv-subnet-2.


Lastly, I don’t need to worry about the remaining private routing table, since all subnets will go to the default routing table priv-route.

Then I will create a Network Address Translation (NAT) gateway. Let's choose a subnet and I choose priv-subnet-2. Because NAT must be allocated with Elastic IP (EIP), so I first create an EIP, and then we create a NAT gateway and add it to the routing table.


Which routing table do we have? It is called the NAT routing table, add from the nat gateway.


So far, I have almost completed the network architecture with about 70 per cent. Next step, let's set up all the related security group settings. The security group must be bound to my VPC. When I create a VPC, there is a default security group. For example, I am going to use security group for my bastion and load balancer. My bastion allows only specific IP to access SSH port 22, and then my load balancer provides HTTP services to the outside world, so I have to open port 80. Then my web service should be allowed to be accessed by the load balancer, and a security group should also be created for my web server. Finally, for my database layer, I do not allow the bastion to access directly, but only the web layer is allowed to access my database.

Create bastion-sg which allows for ssh. Since it's for development purpose, I am going to set a wider range to, if it's production use, you may want to whitelist to your own IP address only.


Create elb-sg which allows HTTP from anywhere.


Create web-sg which allows traffic from my trusted elb-sg and bastion-sg


Create db-sg which mysql 3306 traffic from web-sg only.


Next, I need to start the relevant machines. Go to EC2, and use AMI Linux. Select, my VPC, let's create the bastion first, and I need the subnet corresponding to the bastion, pub-subnet-1. Enable auto-assign public IP and select the bastion-sg security group as shown in the diagram below.


Create webserver1 in priv-subnet-1 with security group web-sg


Create webserver2 in priv-subnet-2 with security group web-sg


After creating all the web servers, I have to create an RDS server. Before creating the RDS server, I also need to create an RDS subnet group. Why? RDS is a little different from the EC2 setting we just set. When I create a new RDS, it does not allow me to choose which VPC. So we create another layer on existing subnet. Create victorleungtw-db subnet group, then select the subnet and as shown in the screenshot below.


Next, create the database server as shown in the diagram below, notice we select the right vpc and the db-sg security group.

diagram22 diagram23 diagram24 diagram25 diagram26

Coming back to the EC2 instances, only the bastion server got public IP for access, while webserver 1 and 2 have no public IP address. I need to setup the target group for the webservers. Create a new target group victorleungtw-tg and add the two web servers as shown in the diagram below:

diagram27 diagram28

Then I would create a load balancer. Select application load balancer with name victorleungtw-alb and map to pub-subnet-1 and pub-subnet-2

diagram29 diagram30 diagram31 diagram32

Finally, everything is set up, we can test it out. Open a new terminal, ssh to the bastion host. Then from the bastion host, you could further ssh to webserver 1 and webserver 2 respectively. Start the Nginx server, and open a browser to access the elb url. You can verify by refreshing the page and hitting to the 2 servers with load balancing. From the web server, you can further verify to access the database from the application layer, but not from the bastion server layer.

That's it for setting up a 3 layer architecture on AWS. Let me know if you got any questions, feel free to connect

About Victor Leung

Software development professional with expertise in application architecture, cloud solutions deployment, and financial products development. Possess a Master's degree in Computer Science and an MBA in Finance. Highly skilled in AWS (Certified Solutions Architect, Developer and SysOps Administrator), GCP (Professional Cloud Architect), Microsoft Azure, Kubernetes(CKA, CKAD, CKS, KCNA), and Scrum(PSM, PSPO) methodologies.

Happy to connect

Continuous improvement

Copyright © 2023.