Terraform: Deploying a 2-Tier Architecture

Terraform: Deploying a 2-Tier Architecture


Scenario

Deploying a 2-tier architecture that includes all our code in a single main.tf file (known as a monolith) with hardcoded data.

2-Tier Architecture

Step 1: Create main.tf-

The file that will be used here is the main.tf file (Note: the “.tf” extension allows terraform to track the file).

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "us-west-2"
}        

Step 2: Create VPC (Virtual Private Cloud) and subnets

We will be creating the VPC, 2 public subnets and 2 private subnets. The public and private subnets will be in different availability zones

#Create VPC
resource "aws_vpc" "my_vpc" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "my_vpc"
  }
}

#Create Public subnet #1
resource "aws_subnet" "Public_sub2a" {
  vpc_id                  = aws_vpc.my_vpc.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true
  availability_zone       = "us-west-2a"

  tags = {
    Name = "Public_sub2a"
  }
}

#Create Public subnet #2
resource "aws_subnet" "Public_sub2b" {
  vpc_id                  = aws_vpc.my_vpc.id
  cidr_block              = "10.0.2.0/24"
  map_public_ip_on_launch = true
  availability_zone       = "us-west-2b"

  tags = {
    Name = "Public_sub2b"
  }
}

#Create Private subnet #1
resource "aws_subnet" "db_private_sub2a" {
  vpc_id                  = aws_vpc.my_vpc.id
  cidr_block              = "10.0.3.0/24"
  map_public_ip_on_launch = false
  availability_zone       = "us-west-2a"

  tags = {
    Name = "Db_Private_sub2a"
  }
}

#Create Private subnet #2
resource "aws_subnet" "Private_sub2b" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.4.0/24"
  availability_zone = "us-west-2b"

  tags = {
    Name = "Private_sub2b"
  }
}        

Step 3: Create a Route table and Internet gateway

The next step would be to create the internet gateway and the routing table for the public subnets. The route specified shows traffic would go out to the internet via the internet gateway

#Create Internet gateway
resource "aws_internet_gateway" "my_igw" {
  vpc_id = aws_vpc.my_vpc.id

  tags = {
    Name = "main_IGW"
  }
}

#Create Route Table for Public Subnets
resource "aws_route_table" "my_rt_table" {
  vpc_id = aws_vpc.my_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.my_igw.id
  }

  tags = {
    Name = "My_Route_Table"
  }
}        

Step 4: Association of Public subnets to the routing table

Here we have to specify the subnet id for each public subnet and the route table id.

#Associate public subnets with routing table
resource "aws_route_table_association" "Public_sub1_Route_Association" {
  subnet_id      = aws_subnet.Public_sub2a.id
  route_table_id = aws_route_table.my_rt_table.id
}

resource "aws_route_table_association" "Public_sub2_Route_Association" {
  subnet_id      = aws_subnet.Public_sub2b.id
  route_table_id = aws_route_table.my_rt_table.id
}        

Step 5: Create security groups for VPC and RDS MySQL instance

It is important we get our security groups set up rightly to allow inbound traffic into the instances that would be launched in the public subnets. The security groups for both the VPC and RDS MySQL instance will be set up.

#Create Security group for VPC
resource "aws_security_group" "my_vpc_sg" {
  name        = "my_vpc_sg"
  description = "Allow inbound traffic to instance"
  vpc_id      = aws_vpc.my_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"]
  }
}

#Create a Security group for Database server
resource "aws_security_group" "db_sg" {
  name        = "db_sg"
  description = "Allows inbound traffic"
  vpc_id      = aws_vpc.my_vpc.id
  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.my_vpc_sg.id]
  }

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

Step 6: Create a target group and Loadbalancer

Next, we will create the Application load balancer and the target group. The load balancer is listening on port 80 and the target group must also have port 80 specified.

#Create an ALB target group
resource "aws_lb_target_group" "alb-TG" {
  name     = "alb-TG"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.my_vpc.id
}

#Create Load balancer
resource "aws_lb" "my-aws-alb" {
  name               = "my-aws-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.my_vpc_sg.id]
  subnets            = [aws_subnet.Public_sub2a.id, aws_subnet.Public_sub2b.id]
}

# Create Load balancer listner rule
resource "aws_lb_listener" "lb_lst" {
  load_balancer_arn = aws_lb.my-aws-alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.alb-TG.arn
  }
}

#Load balancer-Target group attachment
resource "aws_lb_target_group_attachment" "my-aws-alb" {
  target_group_arn = aws_lb_target_group.alb-TG.arn
  target_id        = aws_instance.Pub2a_ec2.id
  port             = 80
}

#Load balancer-Target group attachment
resource "aws_lb_target_group_attachment" "my-aws-alb2" {
  target_group_arn = aws_lb_target_group.alb-TG.arn
  target_id        = aws_instance.Pub2b_ec2.id
  port             = 80
}        

Step 7: Create ec2 instances and database instance

Now we will create the ec2 and database instances and also do some bootstrapping in our ec2 instances.

#Create EC2 instances in public subnets
resource "aws_instance" "Pub2a_ec2" {
  ami                         = "ami-00448a337adc93c05"
  instance_type               = "t2.micro"
  associate_public_ip_address = true
  subnet_id                   = aws_subnet.Public_sub2a.id
  security_groups             = [aws_security_group.my_vpc_sg.id]

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "<h1>Code finally Worked!!!</h1>" > var/www/html/index.html
    EOF
}

resource "aws_instance" "Pub2b_ec2" {
  ami                         = "ami-00448a337adc93c05"
  instance_type               = "t2.micro"
  associate_public_ip_address = true
  subnet_id                   = aws_subnet.Public_sub2b.id
  security_groups             = [aws_security_group.my_vpc_sg.id]

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "<h1>Welcome to 2-Tier Architecture Project!!!</h1>" > var/www/html/index.html
    EOF
}

# Create a Database instance
resource "aws_db_instance" "db_instance" {
  allocated_storage      = 10
  db_name                = "my_private_db"
  engine                 = "mysql"
  engine_version         = "5.7"
  instance_class         = "db.t2.micro"
  username               = "projectTerraform"
  password               = "Terraform1234"
  parameter_group_name   = "default.mysql5.7"
  db_subnet_group_name   = "db_sub_grp"
  vpc_security_group_ids = [aws_security_group.my_vpc_sg.id]
  skip_final_snapshot    = true
  availability_zone      = "us-west-2b"
}

#Create RDS instance subnet group
resource "aws_db_subnet_group" "db_sub_grp" {
  name       = "db_sub_grp"
  subnet_ids = [aws_subnet.db_private_sub2a.id, aws_subnet.Private_sub2b.id]
}        

Now, we need run below commands

$terraform init        

This command prepares the current working directory for terraform to run the configuration

Terraform has been successfully initialized


Next command

$terraform validate        

The code is literally a lifesaver as it validates your configuration, pointing out any errors or unspecified attributes in your resource blocks. I got that so many times after running the code severally. Now our configuration is super valid.

The configuration is valid


After that, we will run

$terraform plan        

This basically shows a plan for every resource that is to be executed/deployed. It allows you to review the plan before executing the configuration.

Terraform plan

finally,

$terraform apply        

This takes action on the terraform configuration to create the resources

After running it to completion, we have 20 resources added.

terraform apply completed

Let’s navigate to the AWS console to see what we spun up. I’ll show a few of them,

VPC


Subnets


EC2

RDS

now, browse your load balancer ARN/URL

Finally, we will have to take down everything we have created using the command below,

$terraform destroy        


Thank you for reading. I hope you found this article helpful.

Happy Learning :-)

Mounika Jilakari.


要查看或添加评论,请登录

mouni ka的更多文章

  • GitHub Actions Scouting Myntra App | DevSecOps

    GitHub Actions Scouting Myntra App | DevSecOps

    STEP 1A: Setting up AWS EC2 Instance and IAM Role Sign in to the AWS Management Console Access the AWS Management…

  • Setup ELK Stack Architecture

    Setup ELK Stack Architecture

    Continuous Monitoring: Continuous Monitoring is an important part of software development. It measures the health of…

  • Port Numbers

    Port Numbers

    DevOps engineers often work with a variety of tools and services that communicate over specific port numbers. ????????…

    1 条评论
  • Lost your Amazon EC2 Keypair?

    Lost your Amazon EC2 Keypair?

    In this, we have created two instances (DB-Server and Helper-EC2), of which one has lost its keypair. We lost our…

  • In this project I’m doing how to deploy a WordPress website on AWS(EC2 Ubuntu Instance) using Docker.

    In this project I’m doing how to deploy a WordPress website on AWS(EC2 Ubuntu Instance) using Docker.

    WordPress is a popular web hosting site that is very easy to use and setup. The platform allows users to create and…

  • Jenkins Pipeline (Docker + Kubernetes)

    Jenkins Pipeline (Docker + Kubernetes)

    Step - 1: Jenkins Server Setup 1.1) Create Ubuntu VM (20.

  • Hosting Static Website With AWS S3

    Hosting Static Website With AWS S3

    Hosting Static Website With AWS S3 Steps to develop Static website 1) login to AWS Portal 2) Search for S3 Service 3)…

    2 条评论
  • Jenkins CI/CD Pipeline Setup

    Jenkins CI/CD Pipeline Setup

    Jenkins CI/CD Pipeline with GitHub + Maven + Nexus + SonarQube + Tomcat Here we will complete our setup in 6 steps Step…

    1 条评论
  • DevOps Project Setup

    DevOps Project Setup

    Spring Boot + Angular + Docker + Kubernetes – Project Setup In this project I have deployed one Full Stack Application…

社区洞察

其他会员也浏览了