Configure an AWS Load Balancer to target an Autoscaling Group using terraform

Terraform AWS load balancer target auto scaling group

3 min read | by Jordi Prats

It's quite convenient to be able to configure a AWS Load Balancer to target an Auto Scaling Group so we don't have to handle how instances are getting in and out of this load balancer. This can be done easily using terraform as follows

First we will have to create a SecurityGroup and the Load Balancer itself. We are going to use the AWS NLB (network load balancer) but configuring an ALB is quite similar. We'll have to set the load_balancer_type to application

resource "aws_security_group" "lb_access_sg" {
  vpc_id      = var.vpc_id
  name        = "LB SG"
  description = "web access k3s"

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

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

resource "aws_lb" "k3s_lb" {
  name = "k3s-lb"

  load_balancer_type = "network"

  security_groups = [ aws_security_group.lb_access_sg.id ]

  subnets = var.subnet_ids

  enable_cross_zone_load_balancing = true
}

Then, we need to configure the listener using the aws_lb_listener resource and the target group (the destination) without setting any actual targets:

resource "aws_lb_target_group" "k3s_master_http_tg" {
  name     = "http"
  port     = 80
  protocol = "TCP"
  vpc_id   = var.vpc_id

  health_check {
    port     = 80
    protocol = "TCP"
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_lb_listener" "k3s_lb_http" {
  load_balancer_arn = aws_lb.k3s_lb.id
  port              = "80"
  protocol          = "TCP"

  default_action {
    target_group_arn = aws_lb_target_group.k3s_master_http_tg.id
    type             = "forward"
  }
}

To attach the ASG to the target group we can use the target_group_arns property on the aws_autoscaling_group resource as follows:

resource "aws_autoscaling_group" "k3s_master_asg" {
  name                      = "k3s_master_asg"
  wait_for_capacity_timeout = "5m"
  vpc_zone_identifier       = var.subnet_ids

  target_group_arns = [
    aws_lb_target_group.k3s_master_http_tg.arn
  ]

  lifecycle {
    create_before_destroy = true
    ignore_changes        = [load_balancers]
  }

  mixed_instances_policy {
    instances_distribution {
      on_demand_base_capacity                  = var.k3s_master_on_demand_base_capacity
      on_demand_percentage_above_base_capacity = var.k3s_master_on_demand_percentage_above_base_capacity
      spot_allocation_strategy                 = "lowest-price"
    }

    launch_template {
      launch_template_specification {
        launch_template_id = aws_launch_template.k3s_lt.id
        version            = "$Latest"
      }

      dynamic "override" {
        for_each = var.k3s_master_weighted_instance_types
        content {
          instance_type     = override.key
          weighted_capacity = override.value
        }
      }

    }
  }

  desired_capacity          = var.k3s_master_desired_capacity
  min_size                  = var.k3s_master_min_capacity
  max_size                  = var.k3s_master_max_capacity
  health_check_grace_period = 300
  health_check_type         = "EC2"
  force_delete              = true
}

With this code we are going to create a new AWS NLB creating a listener for port 80 that's going to be redirected to the healthy instances the ASG has.


Posted on 04/05/2022

Categories