Autoscaling Groups and Load Balancers in AWS with Terraform

In this blog, we will explore how to set up Autoscaling Groups and Load Balancers using Terraform. These resources ensure that your application is scalable and highly available. Let’s dive into the step-by-step implementation using the provided Terraform code.

Prerequisites

Before you begin, ensure you have the following:

  1. AWS CLI installed and configured with proper credentials.

  2. Terraform installed on your system.

  3. A basic understanding of Terraform and AWS.

Terraform Files Breakdown

1. Provider Configuration

This file specifies the AWS region where the resources will be created:

provider.tf:

provider "aws" {
  region = "us-east-1"
}

2. VPC Configuration/

The Virtual Private Cloud (VPC) acts as a container for all other resources:

vpc.tf:

resource "aws_vpc" "myvpc" {
  tags = {
    Name = "My-VPC"
  }
  cidr_block           = "10.0.0.0/16"
  instance_tenancy     = "default"
  enable_dns_hostnames = "true"
}

3. Subnets

Two subnets are created in different availability zones for high availability:

subnets.tf:

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

resource "aws_subnet" "mysubnet2" {
  tags = {
    Name = "subnet-2"
  }
  vpc_id                  = aws_vpc.myvpc.id
  availability_zone       = "us-east-1b"
  cidr_block              = "10.0.2.0/24"
  map_public_ip_on_launch = "true"
}

4. Security Group

This allows all inbound and outbound traffic for demonstration purposes:

security_group.tf:

resource "aws_security_group" "mysg" {
  tags = {
    Name = "my-SG"
  }
  name        = "Terraform-Sg"
  description = "it has all Traffic"
  vpc_id      = aws_vpc.myvpc.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"]
  }
}

5. Route Table and Internet Gateway

These resources ensure public connectivity for your subnets:

Route_table.tf:

resource "aws_route_table" "myrt" {
  vpc_id = aws_vpc.myvpc.id

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

  tags = {
    Name = "My-RT"
  }
}

resource "aws_route_table_association" "public_subnet_association_1a" {
  subnet_id      = aws_subnet.mysubnet1.id
  route_table_id = aws_route_table.myrt.id
}

resource "aws_route_table_association" "public_subnet_association_1b" {
  subnet_id      = aws_subnet.mysubnet2.id
  route_table_id = aws_route_table.myrt.id
}

Igw.tf:

resource "aws_internet_gateway" "myigw" {
  tags = {
    Name = "My_IGW"
  }
  vpc_id = aws_vpc.myvpc.id
}

6. Launch Template

Defines the configuration for instances in the Autoscaling Group:

main.tf (Launch Template):

resource "aws_launch_template" "mylt" {
  name                   = "terraform-lt"
  description            = "v1"
  image_id               = "ami-0ca9fb66e076a6e32"
  instance_type          = "t2.micro"
  key_name               = "Harikeypair"
  vpc_security_group_ids = [aws_security_group.mysg.id]
  user_data              = base64encode(<<-EOF
    #!/bin/bash
    sudo yum update -y
    sudo yum install httpd -y
    sudo systemctl start httpd
    sudo systemctl enable httpd
    sudo systemctl restart httpd
    sudo chmod 766 /var/www/html/index.html
    echo "<html><body><h1>Welcome to Terraform Scaling.</h1></body></html>" >/var/www/html/index.html
  EOF
  )
}

7. Load Balancer

A Classic Load Balancer to distribute incoming traffic:

main.tf (Load Balancer):

resource "aws_elb" "myelb" {
  name            = "terraform-asg-elb"
  security_groups = [aws_security_group.mysg.id]
  subnets         = [aws_subnet.mysubnet1.id, aws_subnet.mysubnet2.id]

  listener {
    instance_port     = 80
    instance_protocol = "HTTP"
    lb_port           = 80
    lb_protocol       = "HTTP"
  }
}

8. Autoscaling Group

Automatically scales the number of instances based on traffic:

main.tf (Autoscaling Group):

resource "aws_autoscaling_group" "myasg" {
  name                = "terraform-asg"
  min_size            = 2
  max_size            = 6
  desired_capacity    = 2
  health_check_type   = "EC2"
  load_balancers      = [aws_elb.myelb.name]
  vpc_zone_identifier = [aws_subnet.mysubnet1.id, aws_subnet.mysubnet2.id]

  launch_template {
    id      = aws_launch_template.mylt.id
    version = "$Latest"
  }
}

How It All Works Together

  1. VPC & Subnets: We create a VPC with two subnets to deploy instances in different availability zones.

  2. Security Groups & Route Tables: We allow all inbound and outbound traffic to/from the instances and associate the subnets with a route table.

  3. Launch Template: The launch template defines how the EC2 instances will be configured with a web server (Apache).

  4. Elastic Load Balancer: The ELB ensures that traffic is distributed evenly across all healthy EC2 instances.

  5. Auto Scaling Group: The ASG dynamically adjusts the number of EC2 instances between the minimum and maximum capacity based on demand.

Conclusion

Using Terraform to manage your infrastructure makes it easier to create scalable and fault-tolerant architectures in AWS. The combination of Auto Scaling Groups and Load Balancers ensures that your applications can handle fluctuating traffic while maintaining high availability.

Try deploying the above Terraform configuration and watch your infrastructure automatically scale as needed!