0
0
AWScloud~5 mins

Multi-tier architecture patterns in AWS - Commands & Configuration

Choose your learning style9 modes available
Introduction
Multi-tier architecture splits an application into layers to improve organization and security. It separates the user interface, application logic, and data storage into different parts that work together.
When you want to keep your web servers separate from your database servers for better security.
When you need to scale the application logic independently from the user interface.
When you want to update one part of your app without affecting others.
When you want to protect your database by placing it in a private network.
When you want to improve fault tolerance by isolating failures to one layer.
Config File - main.tf
main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_vpc" "main_vpc" {
  cidr_block = "10.0.0.0/16"
  tags = { Name = "main-vpc" }
}

resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.1.0/24"
  map_public_ip_on_launch = true
  availability_zone = "us-east-1a"
  tags = { Name = "public-subnet" }
}

resource "aws_subnet" "private_subnet" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-east-1a"
  tags = { Name = "private-subnet" }
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main_vpc.id
  tags = { Name = "main-igw" }
}

resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.main_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }
  tags = { Name = "public-route-table" }
}

resource "aws_route_table_association" "public_assoc" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_rt.id
}

resource "aws_security_group" "web_sg" {
  name        = "web-sg"
  description = "Allow HTTP and SSH"
  vpc_id      = aws_vpc.main_vpc.id

  ingress {
    description = "HTTP from anywhere"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "SSH from anywhere"
    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" "db_sg" {
  name        = "db-sg"
  description = "Allow MySQL from web servers"
  vpc_id      = aws_vpc.main_vpc.id

  ingress {
    description = "MySQL from web servers"
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    security_groups = [aws_security_group.web_sg.id]
  }

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

resource "aws_instance" "web_server" {
  ami           = "ami-0c94855ba95c71c99"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public_subnet.id
  vpc_security_group_ids = [aws_security_group.web_sg.id]
  tags = { Name = "web-server" }
}

resource "aws_db_subnet_group" "db_subnet_group" {
  name       = "db-subnet-group"
  subnet_ids = [aws_subnet.private_subnet.id]
  tags = { Name = "db-subnet-group" }
}

resource "aws_db_instance" "db" {
  allocated_storage    = 20
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"
  name                 = "mydb"
  username             = "admin"
  password             = "StrongPass123!"
  parameter_group_name = "default.mysql8.0"
  skip_final_snapshot  = true
  vpc_security_group_ids = [aws_security_group.db_sg.id]
  db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
  tags = { Name = "db-instance" }
}

This Terraform file creates a simple multi-tier architecture on AWS.

  • VPC: A private network for all resources.
  • Subnets: One public for web servers, one private for the database.
  • Internet Gateway and Route Table: Allow public subnet to access the internet.
  • Security Groups: Control traffic; web servers allow HTTP/SSH, database allows MySQL only from web servers.
  • EC2 Instance: Web server in the public subnet.
  • RDS Instance: MySQL database in the private subnet.
Commands
This command initializes Terraform in the current directory. It downloads the AWS provider and prepares Terraform to manage resources.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v4.0.0... - Installed hashicorp/aws v4.0.0 (signed by HashiCorp) Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure.
This command creates all the AWS resources defined in the Terraform file. The -auto-approve flag skips manual confirmation to speed up deployment.
Terminal
terraform apply -auto-approve
Expected OutputExpected
aws_vpc.main_vpc: Creating... aws_vpc.main_vpc: Creation complete after 3s [id=vpc-0abcd1234efgh5678] aws_subnet.public_subnet: Creating... aws_subnet.private_subnet: Creating... aws_internet_gateway.igw: Creating... aws_route_table.public_rt: Creating... aws_security_group.web_sg: Creating... aws_security_group.db_sg: Creating... aws_db_subnet_group.db_subnet_group: Creating... aws_subnet.public_subnet: Creation complete after 2s [id=subnet-0abcd1234efgh5678] aws_subnet.private_subnet: Creation complete after 2s [id=subnet-0abcd1234efgh5679] aws_internet_gateway.igw: Creation complete after 2s [id=igw-0abcd1234efgh5678] aws_route_table.public_rt: Creation complete after 2s [id=rtb-0abcd1234efgh5678] aws_route_table_association.public_assoc: Creating... aws_route_table_association.public_assoc: Creation complete after 1s [id=rtbassoc-0abcd1234efgh5678] aws_security_group.web_sg: Creation complete after 2s [id=sg-0abcd1234efgh5678] aws_security_group.db_sg: Creation complete after 2s [id=sg-0abcd1234efgh5679] aws_db_subnet_group.db_subnet_group: Creation complete after 2s [id=dbsubnetgroup-0abcd1234efgh5678] aws_instance.web_server: Creating... aws_db_instance.db: Creating... aws_instance.web_server: Still creating... [10s elapsed] aws_db_instance.db: Still creating... [10s elapsed] aws_instance.web_server: Creation complete after 15s [id=i-0abcd1234efgh5678] aws_db_instance.db: Creation complete after 60s [id=mydb-instance] Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
-auto-approve - Skip manual confirmation to apply changes immediately
This command displays the current state of all resources Terraform manages, confirming what was created.
Terminal
terraform show
Expected OutputExpected
... # aws_instance.web_server: resource "aws_instance" "web_server" { ami = "ami-0c94855ba95c71c99" instance_type = "t3.micro" subnet_id = "subnet-0abcd1234efgh5678" vpc_security_group_ids = ["sg-0abcd1234efgh5678"] tags = { Name = "web-server" } } # aws_db_instance.db: resource "aws_db_instance" "db" { allocated_storage = 20 engine = "mysql" instance_class = "db.t3.micro" name = "mydb" username = "admin" vpc_security_group_ids = ["sg-0abcd1234efgh5679"] db_subnet_group_name = "db-subnet-group" tags = { Name = "db-instance" } } ...
This AWS CLI command checks the status of the web server instance to ensure it is running.
Terminal
aws ec2 describe-instances --filters "Name=tag:Name,Values=web-server" --query "Reservations[].Instances[].State.Name" --output text
Expected OutputExpected
running
--filters - Filter instances by tag name
--query - Select only the instance state from the output
--output - Format output as plain text
Key Concept

If you remember nothing else from this pattern, remember: separating your app into layers improves security, scalability, and maintenance.

Common Mistakes
Placing the database in the public subnet with open internet access.
This exposes sensitive data to the internet and increases security risks.
Always place databases in private subnets without direct internet access.
Not setting security group rules to restrict traffic between tiers.
This allows unwanted access and weakens security boundaries.
Configure security groups to allow only necessary traffic between layers.
Skipping the internet gateway or route table setup for public subnet.
Web servers won't be reachable from the internet without proper routing.
Create and attach an internet gateway and route table for public subnet traffic.
Summary
Use Terraform to create a VPC with public and private subnets for multi-tier architecture.
Deploy web servers in the public subnet with internet access and database servers in the private subnet.
Use security groups to control traffic between web and database layers for better security.