Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I configure AWS network load balancers to route HTTPS traffic with Terraform?

I am trying to use API Gateway’s VPC links to route traffic to an internal API on HTTPS. But, VPC links forces me to change my API’s load balancer from "application" to "network".

I understand that the network load balancer is on layer 4 and as such will not know about HTTPS.

I am used to using the layer 7 application load balancer. As such, I am not sure how I should configure or indeed use the network load balancer in terraform.

Below is my attempt at configuring the network load balancer in Terraform. The health check fails and I'm not sure what I am doing wrong.

resource "aws_ecs_service" “app” {
  name = "${var.env}-${var.subenv}-${var.appname}"
  cluster = "${aws_ecs_cluster.cluster.id}"
  task_definition = "${aws_ecs_task_definition.app.arn}"
  desired_count = "${var.desired_app_count}"
  deployment_minimum_healthy_percent = 50
  deployment_maximum_percent = 200
  iam_role = "arn:aws:iam::${var.account}:role/ecsServiceRole"

  load_balancer {
    target_group_arn = "${aws_lb_target_group.app-lb-tg.arn}"
    container_name = "${var.env}-${var.subenv}-${var.appname}"
    container_port = 9000
  }
  depends_on = [
    "aws_lb.app-lb"
  ]
}

resource "aws_lb" “app-lb" {
  name               = "${var.env}-${var.subenv}-${var.appname}"
  internal           = false
  load_balancer_type = "network"
  subnets = "${var.subnet_ids}"
  idle_timeout = 600

  tags {
    Owner = ""
    Env = "${var.env}"
  }
}

resource "aws_lb_listener" “app-lb-listener" {
  load_balancer_arn = "${aws_lb.app-lb.arn}"
  port = 443
  protocol = "TCP"

  default_action {
    type = "forward"
    target_group_arn = "${aws_lb_target_group.app-lb-tg.arn}"
  }
}

resource "aws_lb_target_group" “app-lb-tg" {
  name = "${var.env}-${var.subenv}-${var.appname}"
  port = 443
  stickiness = []

  health_check {
    path = "/actuator/health"
  }

  protocol = "TCP"
  vpc_id = "${var.vpc_id}"
}

For reference, this is how I previously configured my application load balancer before attempting to switch to a network load balancer:

resource "aws_ecs_service" "app" {
  name = "${var.env}-${var.subenv}-${var.appname}"
  cluster = "${aws_ecs_cluster.cluster.id}"
  task_definition = "${aws_ecs_task_definition.app.arn}"
  desired_count = "${var.desired_app_count}"
  deployment_minimum_healthy_percent = 50
  deployment_maximum_percent = 200
  iam_role = "arn:aws:iam::${var.account}:role/ecsServiceRole"

  load_balancer {
    target_group_arn = "${aws_lb_target_group.app-alb-tg.arn}"
    container_name = "${var.env}-${var.subenv}-${var.appname}"
    container_port = 9000
  }
  depends_on = [
    "aws_alb.app-alb"]
}

resource "aws_alb" "app-alb" {
  name = "${var.env}-${var.subenv}-${var.appname}"
  subnets = "${var.subnet_ids}"
  security_groups = [
    "${var.vpc_default_sg}",
    "${aws_security_group.app_internal.id}"]
  internal = false
  idle_timeout = 600
  tags {
    Owner = ""
    Env = "${var.env}"
  }
}

resource "aws_lb_listener" "app-alb-listener" {
  load_balancer_arn = "${aws_alb.app-alb.arn}"
  port = "443"
  protocol = "HTTPS"
  ssl_policy = "ELBSecurityPolicy-2015-05"
  certificate_arn = "${var.certificate_arn}"

  default_action {
    type = "forward"
    target_group_arn = "${aws_lb_target_group.app-alb-tg.arn}"
  }
}

resource "aws_lb_target_group" "app-alb-tg" {
  name = "${var.env}-${var.subenv}-${var.appname}"
  port = 80
  health_check {
    path = "/actuator/health"
  }
  protocol = "HTTP"
  vpc_id = "${var.vpc_id}"   
}
like image 354
Freid001 Avatar asked Dec 18 '19 11:12

Freid001


1 Answers

A network load balancer automatically performs passive health checks on non UDP traffic that flows through it so if that's enough then you can just remove the active health check configuration.

If you want to enable active health checks then you can either use TCP health checks (the default) which will just check that the port is open or you can specify the HTTP/HTTPS protocol and specify a path. Ideally the AWS API would error when you try to specify a path for the health check but don't set the protocol to HTTP or HTTPS but apparently that's not the case right now.

With Terraform this would look something like this:

resource "aws_lb_target_group" "app-alb-tg" {
  name     = "${var.env}-${var.subenv}-${var.appname}"
  port     = 443
  protocol = "TCP"
  vpc_id   = "${var.vpc_id}"

  health_check {
    path     = "/actuator/health"
    protocol = "HTTPS"
  }
}

Remember that active health checks which will check that the port is open on the target from the network load balancer's perspective (not just the source traffic). This means that your target will need to allow traffic from the subnets that your NLBs reside in as well as security groups or CIDR ranges etc that your source traffic originates in.

like image 77
ydaetskcoR Avatar answered Nov 15 '22 09:11

ydaetskcoR