Menu
  • Home
  • About Me
  • Blog
  • Github
  • LinkedIn

Terraform Certification – Load balancer

July 13, 2022July 13, 2022

I’ve updated configuration to include variables, locals, and output. Now it’s time to update the architecture of deployment to include resiliency by adding new resources.

Our current architecture is using a single subnet in a single AZ with a single EC2 instance. That’s a lot of single point of failure. To improve reliability of the deployment, I’ll start by:

  1. Add a second availability zone
  2. Add a second EC2 instance
  3. Add load balancing for instances
  4. Maintain readability of code

Add availability zone

Add data source for AZ on main.tf


data "aws_availability_zones" "available" {
  state = "available"
}

Add a new argument for the AZ on aws_subnet resource and subnet.

resource "aws_subnet" "subnet1" {
  cidr_block              = var.vpc_subnets_cidr_block[0]
  vpc_id                  = aws_vpc.vpc.id
  map_public_ip_on_launch = var.map_public_ip_on_launch

  # Add new argument
  availability_zone = data.aws_availability_zones.available.names[0]

  tags = local.common_tags
}


resource "aws_subnet" "subnet2" {
  cidr_block              = var.vpc_subnets_cidr_block[1]
  vpc_id                  = aws_vpc.vpc.id
  map_public_ip_on_launch = var.map_public_ip_on_launch

  availability_zone = data.aws_availability_zones.available.names[1]

  tags = local.common_tags
}

variable "vpc_subnets_cidr_block" {
  # Change string to list()
  type        = list(string)
  description = "CIDR Block for Subnets in VPC"
  # Use list to add subnet
  default     = ["10.0.0.0/24", "10.0.1.0/24"]
}

Add route table associations

# Copy existing route table resource, then change the name label to "rta-subnet2" and subnet_id reference to subnet2

# Both of theses subnets are going to use the same route table.

resource "aws_route_table_association" "rta-subnet2" {
  subnet_id      = aws_subnet.subnet2.id
  route_table_id = aws_route_table.rtb.id
}

Add Second EC2 instance

Add aws_instance resource and modify subnet id and label name.

# INSTANCES #
resource "aws_instance" "nginx1" {
  ami                    = data.aws_ssm_parameter.ami.value
  instance_type          = var.instance_type
  subnet_id              = aws_subnet.subnet1.id
  vpc_security_group_ids = [aws_security_group.nginx-sg.id]

  user_data = <<EOF
#! /bin/bash
sudo amazon-linux-extras install -y nginx1
sudo service nginx start
sudo rm /usr/share/nginx/html/index.html
echo '<html><head><title>Taco Team Server 1</title></head><body style=\"background-color:#1F778D\"><p style=\"text-align: center;\"><span style=\"color:#FFFFFF;\"><span style=\"font-size:28px;\">You did it! Have a &#127790;</span></span></p></body></html>' | sudo tee /usr/share/nginx/html/index.html
EOF

  tags = local.common_tags

}

# INSTANCES #
resource "aws_instance" "nginx2" {
  ami                    = data.aws_ssm_parameter.ami.value
  instance_type          = var.instance_type
  subnet_id              = aws_subnet.subnet2.id
  vpc_security_group_ids = [aws_security_group.nginx-sg.id]

  user_data = <<EOF
#! /bin/bash
sudo amazon-linux-extras install -y nginx1
sudo service nginx start
sudo rm /usr/share/nginx/html/index.html
echo '<html><head><title>Taco Team Server 2</title></head><body style=\"background-color:#1F778D\"><p style=\"text-align: center;\"><span style=\"color:#FFFFFF;\"><span style=\"font-size:28px;\">You did it! Have a &#127790;</span></span></p></body></html>' | sudo tee /usr/share/nginx/html/index.html
EOF

  tags = local.common_tags

}

Add load balancing for instances

I’ll update the name label of security group to alb_sg and allow traffic from addresses that are in the vpc_cidr_block.

resource "aws_security_group" "alb_sg" {
  name   = "nginx_alb_sg"
  vpc_id = aws_vpc.vpc.id

  # HTTP access from anywhere
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = [var.vpc_cidr_block]
  }

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

  tags = local.common_tags
}

The next thing to do is add our load balancer resources. We need to construct each of those resources.

Search for the aws load balancing in the Terraform docs page, and copy a example of load balancer resource

resource "aws_lb" "test" {
  name               = "test-lb-tf"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.lb_sg.id]
  subnets            = [for subnet in aws_subnet.public : subnet.id]

  enable_deletion_protection = true

  access_logs {
    bucket  = aws_s3_bucket.lb_logs.bucket
    prefix  = "test-lb"
    enabled = true
  }

  tags = {
    Environment = "production"
  }
}

update the name label and the name of our load balancer

resource "aws_lb" "nginx" {
  name               = "globo_web_alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb_sg.id]                 // update correct security group name label
  subnets            = [aws_subnet.subnet1.id, aws_subnet.subnet2.id] // both of the subnets are associated with load balancer

  enable_deletion_protection = false // I want to delete this load balancer when I'm done with it.

  tags = local.common_tags // use local value
}

Add load balancer target group

resource "aws_lb_target_group" "nginx" {
  name     = "nginx-alb-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.vpc.id

  tags = local.common_tags
}

Add the aws_lb_listener which needs to reference the ARN of the load balancer. Set the proper port and protocol, and the default_action

resource "aws_lb_listener" "nginx" {
  load_balancer_arn = aws_lb.nginx.arn
  port              = 80
  protocol          = "HTTP"

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

  tags = local.common_tags
}

Add two target group attachments

resource "aws_lb_target_group_attachment" "nginx1" {
  target_group_arn = aws_lb_target_group.nginx.arn
  target_id        = aws_instance.nginx1.id
  port             = 80
}

resource "aws_lb_target_group_attachment" "nginx2" {
  target_group_arn = aws_lb_target_group.nginx.arn
  target_id        = aws_instance.nginx2.id
  port             = 80
}

Final

resource "aws_lb" "nginx" {
  name               = "globo_web_alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb_sg.id]                 // update correct security group name label
  subnets            = [aws_subnet.subnet1.id, aws_subnet.subnet2.id] // both of the subnets are associated with load balancer

  enable_deletion_protection = false // I want to delete this load balancer when I'm done with it.

  tags = local.common_tags // use local value
}

## aws_lb_target_group

resource "aws_lb_target_group" "nginx" {
  name     = "nginx-alb-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.vpc.id

  tags = local.common_tags
}

## aws_lb_listener

resource "aws_lb_listener" "nginx" {
  load_balancer_arn = aws_lb.nginx.arn
  port              = 80
  protocol          = "HTTP"

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

  tags = local.common_tags
}

## aws_lb_target_group_attachment

resource "aws_lb_target_group_attachment" "nginx1" {
  target_group_arn = aws_lb_target_group.nginx.arn
  target_id        = aws_instance.nginx1.id
  port             = 80
}

resource "aws_lb_target_group_attachment" "nginx2" {
  target_group_arn = aws_lb_target_group.nginx.arn
  target_id        = aws_instance.nginx2.id
  port             = 80
}

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts
  • ChinguTalkBot v0.1.0: Setting up AWS Cognito with CDK for User Authentication
  • Phoenix & Elixir: Fix PostgreSQL connection refused
  • Demo: Git Log with Shell script to create a release notes
  • Metasploit
  • CyberSecurity Lab – Online Password Attack

Archives
  • March 2024
  • May 2023
  • April 2023
  • February 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
Categories
  • Amazon Interview (3)
  • Ansible (3)
  • AWS (9)
  • Azure (9)
  • Certification (2)
  • ChinguTalkBot Project (1)
  • cybersecurity (3)
  • Data analytics (6)
  • Demo Videos (6)
  • Docker (5)
  • Git (1)
  • GitLab (1)
  • Golang (3)
  • JavaScript (2)
  • Jenkins (4)
  • PowerShell (1)
  • Python (10)
  • Terraform (11)
  • Uncategorized (9)

©2025 | Powered by WordPress and Superb Themes!