Deploy Two Tier Architecture in AWS using Terraform

In this article, we are going to cover Deploy Two Tier Architecture in AWS using Terraform.

We will introduce Terraform, an infrastructure-as-code tool, and demonstrate its use to deploy a two-tier architecture in AWS.

Create a MySQL RDS Database Instance with Terraform 4

We will architect a Two Tier Architecture that consists of the following:

  • A VPC with 2 public subnets and 2 private subnets.
  • A load balancer that will direct traffic to the public subnets and 1 EC2 instance in each public subnet.
  • An RDS MySQL instance in one of the subnets.

What is AWS Two Tier Architecture?

AWS two-tier architecture is a common deployment pattern used for web applications in the cloud. It consists of two main components or tiers:

  1. Web Server Tier: This tier is responsible for serving web pages and handling user requests. It typically includes load balancers, web servers, and application servers. Let’s take a closer look at each of these components:
  • Load Balancers: A load balancer distributes incoming traffic to multiple web servers, improving the performance and availability of the application. AWS provides two types of load balancers: Application Load Balancers and Network Load Balancers.
  • Web Servers: Web servers are responsible for serving web pages to the user’s browser. They can handle static content such as HTML, CSS, and JavaScript. Web servers can also execute dynamic content, such as PHP, Python, or Ruby on Rails.

2. Database Tier: This tier is responsible for storing and managing data used by the web application. It typically includes a database server and associated storage. Let’s take a closer look at each of these components:

  • Database Server: A database server stores and manages data used by the application. AWS provides a variety of database options, including Amazon Relational Database Service (RDS), Amazon DynamoDB, and Amazon Aurora.
  • Storage: Storage is used by the database server to store data. AWS provides various storage options, such as Amazon Elastic Block Store (EBS), Amazon Simple Storage Service (S3), and Amazon Elastic File System (EFS).

The two tiers are separated by a firewall or security group to restrict access to the database server from the internet. This architecture is highly scalable, and fault-tolerant, and provides a separation of concerns between the web and database tiers.

Why do we use Two Tier Architecture?

Two-Tier Architecture is employed for web applications in the cloud due to several advantages:

  1. Simplicity: The architecture is straightforward with two distinct tiers (web and database), making it easier to design, deploy, and manage compared to more complex architectures.
  2. Scalability: The separation of the web and database tiers allows for independent scaling. This means that if the demand on the web servers increases, you can scale that tier without necessarily affecting the database tier, and vice versa.
  3. Performance: Load balancing in the web server tier enhances performance by distributing incoming traffic across multiple servers. This ensures efficient utilization of resources and improved response times for users.
  4. Fault Tolerance: The isolation of the web and database tiers contributes to fault tolerance. If one tier experiences issues or failures, the other can continue to function, minimizing the impact on the overall application.
  5. Security: By placing a firewall or security group between the web and database tiers, access to the sensitive database server from the internet is restricted, enhancing the overall security posture of the application.

Difference between AWS Two Tier and Three-Tire architecture:

FeatureTwo-Tier ArchitectureThree-Tier Architecture
Number of TiersTwo: Web Server Tier and Database TierThree: Web Server Tier, Application (Logic) Tier, and Database Tier
Responsibilities– Web Tier: Serves web pages and handles user requests
– Database Tier: Stores and manages data
– Web Tier: Handles user interface and presentation logic
– Application Tier: Manages business logic
– Database Tier: Stores and manages data
ScalabilityIndependent scaling of web and database tiersIndependent scaling of web, application, and database tiers
FlexibilityLimited separation of concerns between presentation and dataClear separation of presentation, business logic, and data layers
ComplexitySimpler design and management due to fewer tiersMore complex design but with added flexibility and scalability
PerformanceLoad balancing improves performance in the web tierBetter optimization of performance with separate application tier
Use CasesSuitable for simpler applications with fewer scalability and flexibility requirementsSuited for complex applications with varying scalability needs and a clear separation of concerns
Example AWS Services– EC2 instances for web servers
– RDS or DynamoDB for databases
– EC2 instances for web servers
– ECS or Lambda for application tier
– RDS, DynamoDB, or other databases for data storage
SecurityFirewall separates web and database tiers for access controlFirewall can be implemented between each tier for fine-grained access control
Fault ToleranceIsolation of tiers provides some fault toleranceBetter fault tolerance with separate application layer
MaintenanceEasier to manage due to fewer componentsRequires more careful management of three distinct layers
Difference Between Two-Tier and Three-Tier Architecture

Two Tier Architecture:

image 35

This two-tier architecture will contain the following components:

  • Deploy a VPC with CIDR 10.0.0.0/16
  • Within the VPC we will have 2 public subnets with CIDR 10.0.1.0/24 and 10.0.2.0/24. Each public subnet will be in a different Availability Zone for high availability
  • Create 2 private subnets with CIDR ‘10.0.3.0/24’ and ‘10.0.4.0/24’ and each will be in a different Availability Zone
  • Deploy RDS MySQL instance.
  • An Application load balancer that will direct traffic to the public subnets.
  • Deploy one EC2 instance in each public subnet for high availability.
  • Internet Gateway and Elastic IPs for EC2 instance.

Prerequisites:

  • Install AWS CLI
  • AWS Account
  • Code Editor (I have used VS Code for this deployment)

Steps for Implementation Two Tier Architecture in AWS using Terraform

Summary view of the terraform files in VS code:

Screenshot 2023 11 28 152555

Step 1:- Create provider.tf file

The provider.tf file in Terraform is a configuration file that specifies the cloud provider and its corresponding plugin that Terraform will use to manage resources in that provider.

Provider.tf file is used for the following:-

  • Provider Declaration: Declares the cloud or infrastructure provider, such as AWS or Azure.
  • Authentication Details: Includes credentials (e.g., access and secret keys) for connecting to the chosen provider.
  • Region Specification: Specifies the geographic region where resources will be provisioned.
  • Version Constraints: Optionally sets constraints on the provider version for compatibility.
  • Additional Settings: May include other provider-specific configurations, like endpoints or custom parameters.
provider.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
}

# Configure provider
provider "aws" {
  region  = "ap-south-1"
  profile="default"
}
Screenshot 2023 11 28 145401

Step 2:- Create network resources.tf file

In Terraform projects, the network_resources.tf file plays a crucial role as it holds the configuration for the essential network infrastructure required by your application. This encompasses defining a Virtual Private Cloud (VPC) to establish an isolated network environment, configuring subnets, setting up an internet gateway, defining route tables, and orchestrating load balancers.


The network_resources.tf file is integral in a Terraform project, allowing the definition of two public and two private subnets, each tailored with unique configurations. Public subnets enable inbound internet traffic, while private subnets restrict inbound access to within the VPC.

This file extends its functionality to configure an internet gateway facilitating traffic between the VPC and the internet. It also outlines the setup of route tables and their associations, critical for routing traffic between subnets within the VPC.

Incorporating a load balancer with a listener and target group is another facet of network_resources.tf. This load balancer efficiently directs traffic to specific instances within the VPC, with the file specifying the attachment of a target group to the load balancer.

Additionally, network_resources.tf accommodates the configuration of an RDS database subnet group, designating subnets for RDS instances. This ensures proper isolation of RDS instances from other VPC resources.

network_resources.tf 
# Create VPC
resource "aws_vpc" "vpc" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "vpc-project"
  }
}

# Create internet gateway
resource "aws_internet_gateway" "ig" {
  vpc_id = aws_vpc.vpc.id
  
  tags = {
    Name = "ig-project"
  }
}

# Create 2 public subnets
resource "aws_subnet" "public_1" {
  vpc_id     = aws_vpc.vpc.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-south-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-1"
  }
}

resource "aws_subnet" "public_2" {
  vpc_id     = aws_vpc.vpc.id
  cidr_block = "10.0.2.0/24"
  availability_zone = "ap-south-1b"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-2"
  }
}

# Create 2 private subnets
resource "aws_subnet" "private_1" {
  vpc_id     = aws_vpc.vpc.id
  cidr_block = "10.0.3.0/24"
  availability_zone = "ap-south-1a"
  map_public_ip_on_launch = false

  tags = {
    Name = "private-1"
  }
}

resource "aws_subnet" "private_2" {
  vpc_id     = aws_vpc.vpc.id
  cidr_block = "10.0.4.0/24"
  availability_zone = "ap-south-1b"
  map_public_ip_on_launch = false

  tags = {
    Name = "private-2"
  }
}
Screenshot 2023 11 28 145345

Step 3:- Create security resources.tf file

The security_resources.tf file in Terraform is vital for configuring application security, focusing on security groups for EC2 instances and load balancers. Within this file, you define security group configurations for EC2 instances, specifying open ports and allowed protocols for inbound and outbound traffic.

For instance, you might permit HTTP and SSH traffic on ports 80 and 22, ensuring internet access for web traffic and SSH access from your local machine.

Additionally, security_resources.tf configures a security group for the load balancer, detailing rules for traffic between the load balancer and EC2 instances.

Proper configuration of this file is essential for a secure application, controlling traffic flow within and outside the VPC. This minimizes security risks, ensuring compliance with relevant regulations and standards.

security_resource.tf
# Security group for ALB
resource "aws_security_group" "alb_sg" {
  name        = "alb-sg"
  description = "security group for alb"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    from_port   = "0"
    to_port     = "0"
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = "0"
    to_port     = "0"
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Create ALB
resource "aws_lb" "project_alb" {
  name               = "alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb_sg.id]
  subnets            = [aws_subnet.public_1.id, aws_subnet.public_2.id]
}

# Create ALB target group
resource "aws_lb_target_group" "project_tg" {
  name     = "project-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.vpc.id

  depends_on = [aws_vpc.vpc]
}

# Create target attachments
resource "aws_lb_target_group_attachment" "tg_attach1" {
  target_group_arn = aws_lb_target_group.project_tg.arn
  target_id        = aws_instance.web1.id
  port             = 80

  depends_on = [aws_instance.web1]
}

resource "aws_lb_target_group_attachment" "tg_attach2" {
  target_group_arn = aws_lb_target_group.project_tg.arn
  target_id        = aws_instance.web2.id
  port             = 80

  depends_on = [aws_instance.web2]
}

# Create listener
resource "aws_lb_listener" "listener_lb" {
  load_balancer_arn = aws_lb.project_alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.project_tg.arn
  }
}

Step 4:- Create routetable_resource.tf file

The routetable_resource.tf file in Terraform is responsible for configuring route tables, crucial for directing network traffic within a Virtual Private Cloud (VPC). By creating a route table to route traffic through the internet gateway we will give internet access to the VPC.

Key aspects include:

  1. Route Table Definition:
    • Defines route tables to specify how network traffic is directed between subnets in the VPC.
  2. Route Associations:
    • Associates route tables with specific subnets, determining how traffic flows within the VPC.
  3. Routing Rules:
    • Specifies routing rules for each route table, determining the next hop for traffic based on destination CIDR blocks.
  4. Internet and Gateway Routes:
    • Configures routes for internet-bound traffic, often involving an internet gateway, ensuring connectivity outside the VPC.

Proper configuration of the routetable_resource.tf file is essential for effective network routing within an AWS VPC, ensuring traffic is directed accurately between subnets and external destinations.

routetable_resource.tf
# Create route table to internet gateway
resource "aws_route_table" "project_rt" {
  vpc_id = aws_vpc.vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.ig.id
  }
    tags = {
    Name = "project-rt"
  }
}

# Associate public subnets with route table
resource "aws_route_table_association" "public_route_1" {
  subnet_id      = aws_subnet.public_1.id
  route_table_id = aws_route_table.project_rt.id
}

resource "aws_route_table_association" "public_route_2" {
  subnet_id      = aws_subnet.public_2.id
  route_table_id = aws_route_table.project_rt.id
}

# Create security groups
resource "aws_security_group" "public_sg" {
  name        = "public-sg"
  description = "Allow web and ssh traffic"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    from_port        = 80
    to_port          = 80
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }
  ingress {
    from_port         = 22
    to_port           = 22
    protocol          = "tcp"
    cidr_blocks       = ["0.0.0.0/0"]
  }
  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]

  }
}

resource "aws_security_group" "private_sg" {
  name        = "private-sg"
  description = "Allow web tier and ssh traffic"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    from_port        = 3306
    to_port          = 3306
    protocol         = "tcp"
    cidr_blocks      = ["10.0.0.0/16"]
    security_groups = [ aws_security_group.public_sg.id ]
  }
  ingress {
    from_port         = 22
    to_port           = 22
    protocol          = "tcp"
    cidr_blocks       = ["0.0.0.0/0"]
  }
  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]

  }
}

Step 5:- Create ec2-resources.tf file

The ec2-resources.tf file in Terraform serves as a configuration file specifically designed for defining and provisioning AWS EC2 instances. Key components of this file include:

  1. Instance Configuration:
    • Defines the characteristics of EC2 instances, such as instance types based on application requirements.
    • Specifies the Amazon Machine Image (AMI) for launching instances, detailing the operating system and any additional software or configurations needed.
  2. Elastic IP Allocation:
    • Allocates Elastic IPs, providing static public IP addresses for EC2 instances.
    • Useful for scenarios requiring a consistent IP address, such as DNS records or firewall configurations.
  3. NGINX Web Server Configuration:
    • Configures EC2 instances with NGINX web servers to serve web pages to users.
    • Includes installation of NGINX software and necessary configurations for web page serving.
  4. Network Settings:
    • Ensures proper network settings, connectivity, and accessibility from the internet for EC2 instances.
ec2_resources.tf
# Create ec2 instances
resource "aws_instance" "web1" {
  ami           = "ami-0287a05f0ef0e9d9a"
  instance_type = "t2.micro"
  key_name        = "twotier-key-pair"
  availability_zone = "ap-south-1a"
  vpc_security_group_ids      = [aws_security_group.public_sg.id]
  subnet_id                   = aws_subnet.public_1.id
  associate_public_ip_address = true
  tags = {
    Name = "web1_instance"
  }
}

resource "aws_instance" "web2" {
  ami           = "ami-0287a05f0ef0e9d9a"
  instance_type = "t2.micro"
  key_name        = "twotier-key-pair"
  availability_zone = "ap-south-1b"
  vpc_security_group_ids      = [aws_security_group.public_sg.id]
  subnet_id                   = aws_subnet.public_2.id
  associate_public_ip_address = true
  tags = {
    Name = "web2_instance"
  }
}
Use the below Linux Commands to Install Nginx On Both Ubuntu Instance Created:- 

sudo apt update -y
sudo apt install nginx
sudo systemctl enable nginx
sudo systemctl start nginx
Screenshot 2023 11 28 162849
Screenshot 2023 11 28 151815

Step 6:- Create db-resources.tf file

Thedb-resources.tf file in Terraform is crucial for provisioning an RDS database in AWS. It configures a MySQL RDS database, specifying the instance class, allocated storage, and backup window. This file allows customization of database instance classes, storage types, and backup schedules to optimize performance, durability, and availability. Proper configuration is vital for ensuring the reliability, scalability, and data integrity of your application.

db_resources.tf
# Database subnet group
resource "aws_db_subnet_group" "db_subnet"  {
    name       = "db-subnet"
    subnet_ids = [aws_subnet.private_1.id, aws_subnet.private_2.id]
}

# Create database instance
resource "aws_db_instance" "project_db" {
  allocated_storage    = 5
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t2.micro"
  identifier           = "db-instance"
  db_name              = "project_db"
  username             = "admin"
  password             = "password"
  db_subnet_group_name = aws_db_subnet_group.db_subnet.id
  vpc_security_group_ids = [aws_security_group.private_sg.id]  
  publicly_accessible = false
  skip_final_snapshot  = true
}
Screenshot 2023 11 28 152056

Step 7:- Let’s deploy!

  • terraform init

The terraform init the command is used to initialize a new or existing Terraform configuration. This command downloads the required provider plugins and sets up the backend for storing state.

Screenshot 2023 11 28 144107
  • terraform plan

The terraform plan the command is used to create an execution plan for the Terraform configuration. This command shows what resources Terraform will create, modify, or delete when applied.

Screenshot 2023 11 28 144155
Screenshot 2023 11 28 144218
  • terraform apply

The terraform apply the command is used to apply the Terraform configuration and create or modify resources in the target environment.

Screenshot 2023 11 28 144256
Screenshot 2023 11 28 153301
  • terraform destroy

The primary purpose of terraform destroy is to remove all the resources that were created by the Terraform configuration. 

Screenshot 2023 11 28 170534
Screenshot 2023 11 28 171013

Step 8:- Go to the AWS console and verify

  1. VPC and Network resources
Screenshot 2023 11 28 153828

2. EC2 instances

Screenshot 2023 11 28 154123

3. Load Balancer

Screenshot 2023 11 28 154251

4. Target Group

Screenshot 2023 11 28 161121

5. RDS MYSQL Database

Screenshot 2023 11 28 155300

6. EC2 NGINX web server is also working fine

Screenshot 2023 11 28 160707
Screenshot 2023 11 28 160737

7. Security Groups

Screenshot 2023 11 28 160927

8. Create your own Html Page and try to reload the Url generated from the Load Balancer then you will find both the instance created are running successfully.

http://alb-313231715.ap-south-1.elb.amazonaws.com/

Screenshot 2023 11 28 161620
Screenshot 2023 11 28 161633

Conclusion:

Deploying a Two Tier Architecture in AWS with Terraform streamlines web application infrastructure. The separation of web and database tiers, orchestrated through Terraform’s declarative approach, enhances scalability and resilience. This efficient deployment ensures optimal resource allocation and accelerates the development lifecycle.

Reference:-

For reference visit the official website TerraformRegistry.

Any queries pls contact us @Devopshint.

Related Articles:

Terraform State File Management | Terraform Local State File | Terraform Remote State

About Akash Bhujbal

Hey, I am Akash Bhujbal, I am an aspiring DevOps and Cloud enthusiast who is eager to embark on a journey into the world of DevOps and Cloud. With a strong passion for technology and a keen interest in DevOps and Cloud based solutions, I am driven to learn and contribute to the ever-evolving field of DevOps and Cloud.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Share via
Copy link