Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load balancer fixes #1884

Closed
wants to merge 1 commit into from
Closed

Load balancer fixes #1884

wants to merge 1 commit into from

Conversation

dblooman
Copy link
Contributor

@dblooman dblooman commented Oct 13, 2017

The loadbalancer changes don't allow for a NLB to be created because the NLB uses TCP only, with most of the code only allowing HTTP or HTTPS.

I think there is probably some additional code coverage that can be added here, especially as NLB's are much more restrictive than ALB/ELB

Example

resource "aws_lb" "main" {
  name               = "test-nlb-tf"
  internal           = false
  load_balancer_type = "network"
  subnets            = ["subnet-123456"]

  enable_deletion_protection = true

  tags {
    Environment = "test"
  }
}

resource "aws_lb_target_group" "test" {
  name     = "tf-example"
  port     = 8085
  protocol = "TCP"
  vpc_id   = "vpc-c333ccc3"

  health_check {
    interval            = 30
    port                = "traffic-port"
    timeout             = 10
    protocol            = "TCP"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = "${aws_lb.main.id}"
  port              = "80"
  protocol          = "TCP"

  default_action {
    target_group_arn = "${aws_lb_target_group.test.id}"
    type             = "forward"
  }
}

resource "aws_lb_target_group_attachment" "test" {
  target_group_arn = "${aws_lb_target_group.test.arn}"
  target_id        = "i-0000000000000"
  port             = 80
}

@radeksimko radeksimko added the enhancement Requests to existing resources that expand the functionality or scope. label Oct 14, 2017
@code4mankind
Copy link

This should be marked as a bug, not an enhancement - aws_lb of type "network" is unusable, unable to create aws_lb_listener with "TCP" protocol.

@@ -420,7 +427,7 @@ func validateAwsLbTargetGroupPort(v interface{}, k string) (ws []string, errors

func validateAwsLbTargetGroupProtocol(v interface{}, k string) (ws []string, errors []error) {
protocol := strings.ToLower(v.(string))
if protocol == "http" || protocol == "https" {
if protocol == "http" || protocol == "https" || protocol == "tcp" {
return
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation error message below needs to be updated

@@ -402,7 +409,7 @@ func validateAwsLbTargetGroupHealthCheckTimeout(v interface{}, k string) (ws []s

func validateAwsLbTargetGroupHealthCheckProtocol(v interface{}, k string) (ws []string, errors []error) {
value := strings.ToLower(v.(string))
if value == "http" || value == "https" {
if value == "http" || value == "https" || value == "tcp" {
return
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation error message below needs to be updated

@elsbrock
Copy link

Cool! I think it's missing the possibility to attach the LB to a certain subnet / AZ.

@dblooman
Copy link
Contributor Author

@else My first comment is wrong, i removed the subnet ID from my example by mistake, if you try to create a LB without a subnet, it will fail. You are required to attach at least one subnet to a network load balancer. I have also seen that you cannot update a NLB with additional subnets after creation, handled in #1941

@c2h5oh
Copy link

c2h5oh commented Oct 25, 2017

Is there any more work left here? This is a blocker for us and I'll help if necessary

@jwinter
Copy link

jwinter commented Oct 26, 2017

This is minor, but I terraform applyed a target group with the same health check as the example:

resource "aws_lb_target_group" "test" {
  name     = "tf-example"
  port     = 8085
  protocol = "TCP"
  vpc_id   = "vpc-c333ccc3"

  health_check {
    interval            = 30
    port                = "traffic-port"
    timeout             = 10
    protocol            = "TCP"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}

After the apply succeeded, a subsequent terraform plan showed a change pending:

Terraform will perform the following actions:

  ~ module.ads.aws_lb_target_group.dataservice-target-group
      health_check.0.path:                   "" => "/"

I expected this plan not to show any changes since I had just applied.

I believe this is because the Default path for the health check is "/". The health-check-path is only for HTTP/HTTPS health checks, not TCP.

@c2h5oh
Copy link

c2h5oh commented Oct 30, 2017

There is one more - checker for healthcheck defaults to checking HTTP 200 response code, which is only supposed to happen for HTTP/HTTPS healthchecks http://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-health-checks.html

@dblooman
Copy link
Contributor Author

@c2h5oh in my branch or in master? I removed the default in my branch, so it shouldn't impact it anymore. @jwinter Removed default path, though im not actually sure if this PR is going to be merged or not, we'll have to see, @stack72 or @radeksimko could perhaps give us an update as current NLB is pretty unusable in terraform right now.

@c2h5oh
Copy link

c2h5oh commented Oct 30, 2017

Right, it's fixed in your branch. I wish we could just write a validator for entire HealthCheck, but https://github.com/hashicorp/terraform/blob/master/helper/schema/schema.go#L188 suggests we can't.

@stack72 or @radeksimko could perhaps give us an update as current NLB is pretty unusable in terraform right now.

Totally unusable.

@dblooman
Copy link
Contributor Author

I actually think the best approach would have been to keep the load balancer types separate. They have quite a lot of differences that have made this more complex than it needed to be. I'm sure there are additional things that have not been picked up so far, but once these fixes go in, we may see edge cases not picked up by tests.

@c2h5oh
Copy link

c2h5oh commented Oct 30, 2017

Ideally schema.Schema would have been an interface, not a struct and you could just compose the types of LB from a common struct and type specific one.

@nathanielks
Copy link
Contributor

@DaveBlooman maybe we should keep them separate? It's obvious implementation wasn't as simple as it appeared to be at the outset. It makes sense to me to keep them separate as they require different things. Even though AWS sees them as one resource, functionally they're different.

@c2h5oh
Copy link

c2h5oh commented Oct 31, 2017

@nathanielks the aws_lb is almost the same for both types - when load_balancer_type == "network" you can't change subnets after creation is the sole difference. aws_lb_target_group_attachment is the same between the two

The big differences are in:

  1. aws_lb_listener
  • network: TCP only, no TLS support, can have elastic IP assigned, has only a single rule - which target group should it forward the traffic to
  • application: HTTP/HTTPS only, TLS support, no elastic IP support, custom routing rules supported

basically no overlap

  1. aws_lb_target_group":
  • network: TCP only, TCP healthcheck (port optional, no path) no sticky sessions
  • application: HTTP/HTTPS only, HTTP/HTTPS healthcheck (port optional, path required with default) checking HTTP response code, sticky sessions support

again, no overlap

So IMHO it makes sense to split listener and target into _network_ and _application_ variants while keeping the rest.

@nathanielks
Copy link
Contributor

@c2h5oh access_logs are also different: alb's have them and nlb's don't.

@OferE
Copy link

OferE commented Nov 1, 2017

hi - since this is blocking us - is there a way to get a binary for this version?

@strongoose
Copy link
Contributor

@OferE you can just pull the branch and build your own binary pretty easily.

@dblooman
Copy link
Contributor Author

dblooman commented Nov 1, 2017

@OferE I have made a release on my fork, assuming its macOS/Linux you wanted. https://github.com/DaveBlooman/terraform-provider-aws/releases/tag/dev

@OferE
Copy link

OferE commented Nov 1, 2017

Thank u so much!! you are amazing

@Elethiomel
Copy link

@DaveBlooman : you're a lifesaver.

@Telling
Copy link
Contributor

Telling commented Nov 6, 2017

I just tried to setup a new NLB using the updated AWS provider provided by @DaveBlooman. I am not able to get a NLB up and running using it. It fails with:

Error: Error applying plan:

1 error(s) occurred:

* module.rabbitmq.aws_lb.lb: 1 error(s) occurred:

* aws_lb.lb: Failure Setting ALB Subnets: InvalidConfigurationRequest: SetSubnets is not supported for load balancers of type 'network'
        status code: 400, request id: eb422135-c302-11e7-b4bc-6b437721a612

This is my code:

# Load balancing

resource "aws_lb" "lb" {
  name               = "rabbitmq-old"
  internal           = true
  subnets            = ["subnet-9d4f83f5"]
  load_balancer_type = "network"
}

resource "aws_alb_target_group" "target" {
  name     = "rabbitmq-old"
  port     = "5672"
  protocol = "TCP"
  vpc_id   = "${var.vpc_id}"
}

resource "aws_alb_listener" "listener" {
  load_balancer_arn = "${aws_lb.lb.arn}"
  port              = "5672"
  protocol          = "TCP"

  default_action {
    target_group_arn = "${aws_alb_target_group.target.arn}"
    type             = "forward"
  }
}

And to clarify, I'm using the NLB with an ASG like so:

# Auto Scaling Group

resource "aws_autoscaling_group" "scaling_group" {
  name                = "rabbitmq-old"
  vpc_zone_identifier = ["${aws_subnet.subnet.id}"]
  target_group_arns   = ["${aws_alb_target_group.target.arn}"]

  health_check_type    = "EC2"
  launch_configuration = "${aws_launch_configuration.launch_config.name}"
  desired_capacity     = "${var.scaling_desired}"
  max_size             = "${var.scaling_max}"
  min_size             = "${var.scaling_min}"
}

Which I believe should be fine. Am I doing something wrong or is this just a bug?

@c2h5oh
Copy link

c2h5oh commented Nov 6, 2017

@DaveBlooman one more:
Error creating LB Target Group: InvalidConfigurationRequest: Custom health check timeouts are not supported for health checks for target groups with the TCP protocol - I guess we need to get rid of the timeout default in health check nope, it has to be exactly 10 seconds.

edit2: interval has to be exactly 30s, timeout exactly 10s

@dblooman
Copy link
Contributor Author

@c2h5oh So you can change the interval, you can set it to 10 or 30s, but the timeout is set to 10s. I have made some changes to this PR so that it should cover the health check block correctly.

Here is some sample TF for those having issues with ASG's and NLB's, just fill in the locals and deploy an app running on 8080.

locals {
  subnet_id     = "subnet-"
  vpc_id        = "vpc-"
  ami_id        = "ami-"
  key_pair      = ""
  instance_type = "t2.micro"
}

resource "aws_lb" "demo" {
  name                       = "demo-lb"
  internal                   = false
  load_balancer_type         = "network"
  enable_deletion_protection = false

  subnet_mapping {
    subnet_id     = "${local.subnet_id}"
    allocation_id = "${aws_eip.demo.id}"
  }

  tags {
    Environment = "demo"
  }
}

resource "aws_lb_target_group" "demo" {
  name     = "nlb-example"
  port     = 8080
  protocol = "TCP"
  vpc_id   = "${local.vpc_id}"

  health_check {
    interval          = 30
    port              = 8080
    protocol          = "TCP"
    healthy_threshold = 3
  }
}

resource "aws_lb_listener" "demo" {
  load_balancer_arn = "${aws_lb.demo.id}"
  port              = "80"
  protocol          = "TCP"

  default_action {
    target_group_arn = "${aws_lb_target_group.demo.id}"
    type             = "forward"
  }
}

resource "aws_eip" "demo" {}

resource "aws_autoscaling_group" "demo" {
  name                 = "testing-asg"
  vpc_zone_identifier  = ["${local.subnet_id}"]
  target_group_arns    = ["${aws_lb_target_group.demo.arn}"]
  health_check_type    = "EC2"
  launch_configuration = "${aws_launch_configuration.demo.name}"
  desired_capacity     = 1
  max_size             = 1
  min_size             = 1
}

resource "aws_launch_configuration" "demo" {
  name_prefix     = "demo-"
  image_id        = "${local.ami_id}"
  instance_type   = "${local.instance_type}"
  key_name        = "${local.key_pair}"
  security_groups = ["${aws_security_group.demo.id}"]

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_security_group" "demo" {
  vpc_id      = "${local.vpc_id}"
  name        = "demo-nlb"
  description = "demo-nlb"

  tags {
    Name = "demo-nlb"
  }
}

resource "aws_security_group_rule" "demo_ssh_in" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = "${aws_security_group.demo.id}"
}

resource "aws_security_group_rule" "nlb_port_in" {
  type      = "ingress"
  from_port = 8080
  to_port   = 8080
  protocol  = "tcp"

  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = "${aws_security_group.demo.id}"
}

resource "aws_security_group_rule" "traffic_out" {
  type      = "egress"
  from_port = 0
  to_port   = 0
  protocol  = "-1"

  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = "${aws_security_group.demo.id}"
}

Copy link
Contributor

@catsby catsby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some notes below. I believe I'll build of this branch and do the remaining work, since everyone here has already contributed a lot and we're a bit behind on addressing this

@@ -794,6 +794,39 @@ resource "aws_vpc" "test" {
}`, targetGroupName)
}

func testAccAWSLBTargetGroupConfig_typeTCP(targetGroupName string) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This configuration isn't actually used in a test, was the corresponding test omitted?


deregistration_delay = 200

stickiness {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stickiness is only applicable to Application Load balancers:

We should take this opportunity to document that as well

@catsby
Copy link
Contributor

catsby commented Nov 10, 2017

I've opened #2251 to supersede of this one. It's a continuation with just a commit on top that adds a test and updates the docs. That PR will allow Network Load balancers to use Target Groups. Please let me know what you think! I'm going to close this one for now

@catsby catsby closed this Nov 10, 2017
@AnishAnil
Copy link

Hello Terraform,

This is a very critical blocker for our automation and we are ending up getting the same error.
The Application load balancer and classic load balancer works flawlessly but network LB fails wil the error.


Error applying plan:

1 error(s) occurred:

  • aws_lb.test: 1 error(s) occurred:

  • aws_lb.test: Failure Setting ALB Subnets: InvalidConfigurationRequest: SetSubnets is not supported for load bala
    ncers of type 'network'
    status code: 400, request id: 11cbb172-cb7a-11e7-9498-cbadb6f85381
    Error applying plan:

1 error(s) occurred:

  • aws_lb.test: 1 error(s) occurred:

  • aws_lb.test: Failure Setting ALB Subnets: InvalidConfigurationRequest: SetSubnets is not supported for load bala
    ncers of type 'network'
    status code: 400, request id: 11cbb172-cb7a-11e7-9498-cbadb6f85381


My Code*
resource "aws_lb" "test" {
name = "test-lb-tf"
idle_timeout = 60
load_balancer_type = "network"
internal = false
subnets = ["${aws_subnet.main-public-2.id}", "${aws_subnet.main-public-1.id}"]

enable_deletion_protection = false

tags {
Environment = "production"
}
}


NOTE: The Load balancer is actually created and is attached to multiple Availability zone as mentioned in the subnet. But the error simply fails the automation.

Is there an ETA when this will be resolved or any suggestions to circumvent this behavior.....

Thank you

@radeksimko
Copy link
Member

@AnishAnil this was shipped yesterday in 1.3.0

@AnishAnil
Copy link

I just updated Terraform and tested and ended up with the same error.

The only differnec being it asks to confirm before i apply the plan and after the plan it applied the "Error" is in red while the rest of the message is in plain white text.


Error: Error applying plan: <"Error" in this statement is in RED and is the only differnece>

1 error(s) occurred:

  • aws_lb.test: 1 error(s) occurred:

  • aws_lb.test: Failure Setting ALB Subnets: InvalidConfigurationRequest: SetSubnets is not supported for load bala
    ncers of type 'network'
    status code: 400, request id: b801a52e-cb7f-11e7-9498-cbadb6f85381

Terraform does not automatically rollback in the face of errors.Instead, your Terraform state file has been partially updated with any resources that successfully completed. Please address the error above and apply again to incremental


terraform version
Terraform v0.11.0

  • provider.aws v1.2.0

Is this the intended behavior.........or is there any separete mentod to upgrade to 1.3??

@Ninir
Copy link
Contributor

Ninir commented Nov 17, 2017

HI @AnishAnil

Since Terraform 0.10, providers (aws, google, azure, rabbitmq, etc..) are not in their own repository, like the one you are currently seeing. This brings a lot of pros: you don't need the core release to get new fixes & features as each one of them has its own lifecycle and thus is built & released independently.

Yesterday, we released version 1.3.0 of the AWS Provider, which contains the new features & fixes.

It seems you updated Terraform only, which is a great thing! however, you will only get those new features once you run: terraform init -upgrade (this will work most of the time, except if you specified the provider version in the Terraform configuration).

Can you do that and tell us how it goes?

Thanks!

@AnishAnil
Copy link

@Ninir, Thank you n it works now.

@jasonkuehl
Copy link

jasonkuehl commented Dec 14, 2017

I'm having the same issue where TCP is not a valid option for protocol.

Error: aws_lb_target_group.testexternal: "protocol" must be either "HTTP" or "HTTPS"

resource "aws_lb" "testexternal" {
  name                        = "testserver"

  load_balancer_type          = "network"
  internal                    = false
  subnets                     = ["${module.subnet.ELB-subnet-ids}"]
  enable_deletion_protection  = true
}

resource "aws_lb_target_group" "testexternal" {
  name     = "testexternal"
  protocol = "TCP"
  port     = 22
  vpc_id      = "${aws_vpc.bla.id}"

  health_check {
      healthy_threshold   = 10
      unhealthy_threshold = 2
      interval            = 10
      timeout             = 3
  }
}

resource "aws_lb" "testexternal" {
  name                        = "testserver"

  load_balancer_type          = "network"
  internal                    = false
  subnets                     = ["${module.subnet.ELB-subnet-ids}"]
  enable_deletion_protection  = true
}

resource "aws_lb_listener" "testexternal" {
  load_balancer_arn = "${aws_lb.testexternal.arn}"
  protocol          = "TCP"
  port              = "22"

  default_action {
    target_group_arn = "${aws_lb_target_group.testexternal.arn}"
    type             = "forward"
  }
}

resource "aws_lb_target_group_attachment" "testexternal" {
  target_group_arn = "${aws_lb_target_group.testexternal.arn}"
  target_id        = "${aws_instance.testserver-001.id}"
  port             = 22
}

@ghost
Copy link

ghost commented Apr 10, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Apr 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests to existing resources that expand the functionality or scope.
Projects
None yet
Development

Successfully merging this pull request may close these issues.