How do I attach an elastic IP upon creation of a network load balancer with Terraform?
Asked Answered
O

3

9

I'm attempting to associate my elastic IP address to a newly created network balancer using Terraform. I see no option in the aws_lb documentation for adding an elastic IP like one is able to do in the AWS console. The difficulty is that you have to associate the elastic IP upon creation of NLB.

EDIT: They now have made an explicit example on their documentation!

Obeng answered 10/4, 2018 at 19:34 Comment(1)
there is this piece here terraform.io/docs/providers/aws/r/lb.html#allocation_id I think when you launch your nlb into your subnet, that allocation_id lets tells it which eip within the subnet to use. Now as far as making sure things happen in the correct order, terraform.io/intro/getting-started/… can ensure that one resource is handled before another.Buttonhook
D
8

The aws_lb resource has a subnet_mapping block which allows you to specify an Elastic IP per subnet that the network load balancer exists in.

An absolutely minimal example looks something like this:

resource "aws_eip" "lb" {
  vpc = true
}

resource "aws_lb" "network" {
  name               = "test-lb-tf"
  load_balancer_type = "network"

  subnet_mapping {
    subnet_id     = "${var.subnet_id}"
    allocation_id = "${aws_eip.lb.id}"
  }
}

Obviously you'll probably want to run the load balancer in multiple subnets so you'd probably use something like this:

variable "vpc" {}

data "aws_vpc" "selected" {
  tags {
    Name = "${var.vpc}"
  }
}

data "aws_subnet_ids" "public" {
  vpc_id = "${data.aws_vpc.selected.id}"

  tags {
    Tier = "public"
  }
}

resource "aws_eip" "lb" {
  count = "${length(data.aws_subnet_ids.public)}"
  vpc   = true
}

resource "aws_lb" "network" {
  name               = "test-lb-tf"
  internal           = false
  load_balancer_type = "network"

  subnet_mapping {
    subnet_id     = "${data.aws_subnet_ids.public.ids[0]}"
    allocation_id = "${aws_eip.lb.id[0]}"
  }

  subnet_mapping {
    subnet_id     = "${data.aws_subnet_ids.public.ids[1]}"
    allocation_id = "${aws_eip.lb.id[1]}"
  }

  subnet_mapping {
    subnet_id     = "${data.aws_subnet_ids.public.ids[2]}"
    allocation_id = "${aws_eip.lb.id[2]}"
  }
}

The above assumes you have tagged your VPC with a Name tag and your subnets with a Tier tag that in this case uses public as the value for any external facing subnets. It then creates an elastic IP address for each of the public subnets a network load balancer in each of the public subnets, attaching an elastic IP for each of them.

Disini answered 12/4, 2018 at 8:58 Comment(1)
Yep. That's what i ended up doing. Thanks for replying!Obeng
D
8

The above answer is correct, however it can now be simplified using dynamic blocks available in Terraform 0.12. This has the advantage of working in vpcs with more or less subnets.

resource "aws_lb" "network" {
  name               = "test-lb-tf"
  internal           = false
  load_balancer_type = "network"

  dynamic "subnet_mapping" {
    for_each = data.aws.subnet_ids.public_ids
    content {
      subnet_id     = subnet_mapping.value
      allocation_id = aws_eip.lb.id[subnet_mapping.key].allocation_id
    }
  }
}
Distrustful answered 13/12, 2019 at 16:9 Comment(0)
M
3

Here's my implementation base on the answer above:

resource "aws_eip" "nlb" {
  for_each = toset(aws_subnet.public.*.id)
  vpc      = true

  tags = {
    "Name" = "my-app-nlb-eip"
  }
}

resource "aws_lb" "nlb" {
  name               = "my-app-nlb"
  internal           = false
  load_balancer_type = "network"

  enable_deletion_protection       = false
  enable_cross_zone_load_balancing = true

  dynamic "subnet_mapping" {
    for_each = toset(aws_subnet.public.*.id)
    content {
      subnet_id     = subnet_mapping.value
      allocation_id = aws_eip.nlb[subnet_mapping.key].allocation_id
    }
  }

  tags = {
    Environment = "development"
  }
}
Much answered 29/3, 2022 at 8:18 Comment(1)
How did you get around the error The "for_each" set includes values derived from resource attributes that cannot be determined until apply ?Ovate

© 2022 - 2024 — McMap. All rights reserved.