hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.73k stars 9.09k forks source link

health_check.matcher not supported for TCP protocol #8305

Open ghost opened 5 years ago

ghost commented 5 years ago

This issue was originally opened by @SrikanthSoma as hashicorp/terraform#21004. It was migrated here as a result of the provider split. The original body of the issue is below.


Issue:

health_check.matcher is not supported for target_groups with TCP protocol

I'm creating NLB with terraform

#Creating target group for search api
resource "aws_alb_target_group" "search_api_target_group" {
  name        = "${var.app_name}-${var.environment}"
  port        = "80"
  vpc_id      = "${data.aws_vpc.vpc_id.id}"
  target_type = "ip"
  protocol    = "TCP"
  stickiness  = []

  health_check {
    port                = "traffic-port"
    protocol            = "TCP"
    healthy_threshold   = 5
    unhealthy_threshold = 5
    timeout             = "${var.health_check_timeout}"
    interval            = "${var.health_check_interval}"
  }

  tags = "${var.search_api_tags}"
}

Terraform don't have a option to set false for health_check matcher for NLB

terraform plan

I'm on terraform version Terraform v0.11.13

Please have a option to set matcher to disable for TCP protocol

kitchen commented 5 years ago

getting same problem here:

resource "aws_lb_target_group" "rabbit_amqp" {
  name        = "rabbit-amqp"
  target_type = "instance"
  port        = "5672"
  protocol    = "TCP"
  vpc_id      = "${data.terraform_remote_state.s3.vpc_id}"

  health_check {
    protocol = "TCP"
  }
}

plan output:

* aws_lb_target_group.rabbit_amqp: arn:aws:elasticloadbalancing:us-east-1:REDACTED:targetgroup/rabbit-amqp/REDACTED: health_check.matcher is not supported for target_groups with TCP protocol
kitchen commented 5 years ago

ohhhh I think it may be because the protocol type was previously set to HTTP (apparently it defaults to that even on TCP target groups) and that is now getting in the way. I think I'm going to have to nuke the target group and recreate it with TCP from the getgo. NBD. I'll report back.

kitchen commented 5 years ago

can confirm, nuking and recreating with explicit TCP from the start was successful.

Because the target group was in use I couldn't just comment it out so there were some ... acrobatics and a couple of "just run it again" that I could have done cleaner, but that is unrelated.

I think there's still a bug here, for sure, and I might get bored and look at it later, but at least it seems like it can be worked around, at least in my situation.

@SrikanthSoma, does this sound familiar? you might try what I did in the mean time. If I'm not clear enough, I'd be happy to elaborate on what I did, let me know :)

ghost commented 5 years ago

@kitchen Thanks for responding yes after the deleting existing TG from AWS Console and recreating TG using terraform worked fine by default it is taking HTTP

kcd83 commented 5 years ago

Using a targeted destroy is more likely to find all the dependant resources rather than trying to delete it via the AWS UI or CLI. Not sure if I needed to have exactly the right depends_on (works on my machine...)

 terraform state list | grep aws_lb_target_group
 terraform destroy -target module.pilot1.aws_lb_target_group.target_es
bhalothia commented 4 years ago

I have had the same issue and I could work around it by first creating TG and then the health-checks.

Raveendran commented 4 years ago

@bhalothia, could you kindly help with the TF code snippet on how you create TG and healthcheck separately and linked them finally please

Raveendran commented 4 years ago

Is there a proper solution for this matchers issue? please help

djdjalas commented 4 years ago

I had the same issue and fixed it by deleting the listener then target groups and then plan apply. This is a bug and happens when you have an HTTP health check for a target group and then when you change to TCP you get that error

marekaf commented 4 years ago

can confirm that this is still a problem today :(

limratechnologies commented 4 years ago

As of today, I'm facing this same issue.

jamescjchan commented 4 years ago

Same here. I haven't brought anything up yet so nothing I can delete from according to the solution above. :/

boxrick commented 3 years ago

I am seeing this exact same issue, even with a number of workarounds to force resource re-creation. ( Such as a dynamic name ). It seems to evaluate before it does the resource re-creation and just gives this error.

A manual targeted destroy fixes it, but this isn't ideal.

maiconbaumx commented 3 years ago

Same behaviour. =/

fizzy123 commented 3 years ago

This is still happening. A fix for this would be awesome!

6sossomons commented 3 years ago

Unfortunately still seeing this today with code for verifying just over TCP with a bland space, never been used. :-(

55octet commented 3 years ago

I am seeing this as well. In order for this to work, I had to taint both the listener and the target group. Tainting just the target group throws an error Error: error deleting Target Group: ResourceInUse: Target group 'xxxxx' is currently in use by a listener or a rule

jeanvetorello commented 3 years ago

same problem, I had to destroy and create with TCP.

donaltuohy commented 3 years ago

Still seeing this issue unfortunately health_check.matcher is not supported for target_groups with TCP protocol

moshe0076 commented 3 years ago

The NLB HTTP health check requires a number of fields to be with specific values: health_check { enabled = true healthy_threshold = 3 interval = 30 matcher = "200-399" path = "/healthz" port = "31254" protocol = "HTTP" timeout = 6 unhealthy_threshold = 3 } You must set: unhealthy_threshold = 3 timeout = 6 interval = 30 matcher = "200-399"

Jabsal commented 2 years ago

Still looking for the solution since April 2019 ? Anyone that has found the solution, kindly share with us please.

However, I tried the following

However, I still had to manually register the EC2 instance which does not satisfy what I want to achieve.

I really do not know why I am getting this error considering Terraform documentation mentions that the matcher is not to be used with NLB

[matcher](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group#matcher) (May be required) Response codes to use when checking for a healthy responses from a target. You can specify multiple values (for example, "200,202" for HTTP(s) or "0,12" for GRPC) or a range of values (for example, "200-299" or "0-99"). Required for HTTP/HTTPS/GRPC ALB. Only applies to Application Load Balancers (i.e., HTTP/HTTPS/GRPC) not Network Load Balancers (i.e., TCP). see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group

fewknow commented 1 year ago

I ran into this problem as well. I am not sure it is a terraform provider issue more than it is a AWS NLB problem. Here is how I solved it. Following https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_CreateTargetGroup.html and https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group. I was able to use the settings for NLB and conditionals based on protocol TCP and build my target group with no errors.

** I did notice the AWS documentation it says "For target groups with a protocol of TCP or TLS, this value must be 6 seconds for HTTP health checks and 10 seconds for TCP and HTTPS health checks." for the HealthCheckTimeoutSeconds. But in setting this threw an error so I had to set it to NULL in the end.

EXAMPLE CODE:

resource "aws_lb_target_group" "lb_target_group" {
  #name                 = "${var.run_env}-${var.service_name}-${var.optional_subdomain}"
  port                 = var.lb_target_group_port
  protocol             = var.target_group_protocol
  target_type          = "ip"
  vpc_id               = var.vpc_id
  deregistration_delay = var.target_group_drain_duration

  health_check {
    healthy_threshold   = ( var.target_group_protocol == "TCP" ? 3 : var.health_check_healthy_threshold )
    unhealthy_threshold = ( var.target_group_protocol == "TCP" ? 3 : var.health_check_unhealthy_threshold )
    timeout             = ( var.target_group_protocol == "TCP" ? null : var.health_check_timeout )
    protocol            = var.health_check_protocol
    path                = ( var.target_group_protocol == "TCP" ? null : var.health_check_path )
    interval            = ( var.target_group_protocol == "TCP" ? 30 : var.health_check_interval )
    matcher             = ( var.target_group_protocol == "TCP" ? null : var.health_check_matcher )
  }
jj6584 commented 1 year ago

Just an update on this issue, I was able to create a target group now without encountering any issue

My Terraform code below:

resource "aws_lb_target_group" "default_thrift" {
  name                 = "${var.nlb_name}-tg"
  port                 = var.ecs_app_port2
  protocol             = "TCP"
  vpc_id               = var.vpc_id
  deregistration_delay = var.deregistration_delay

  health_check {
    protocol            = "TCP"
    healthy_threshold   = 3
    unhealthy_threshold = 3
    interval            = 10
  }

  tags = {
    Environment = var.environment
  }
}

resource "aws_alb" "nlb" {
  name               = var.nlb_name
  subnets            = var.private_subnet_ids
  internal           = "true"
  load_balancer_type = "network"
  idle_timeout       = "300"

  tags = {
    Environment = var.environment
  }
}

# NLB Listeners
resource "aws_lb_listener" "nlb_thrift" {
  load_balancer_arn = aws_alb.nlb.id
  port              = "7070"
  protocol          = "TCP"

  default_action {
    target_group_arn = aws_lb_target_group.default_thrift.id
    type             = "forward"
  }
}
janory commented 1 year ago

After checking the AWS provider's code here. Setting the matcher and the path explicitly to an empty string did the trick for me:

  health_check {
    protocol = "TCP"
    matcher = ""
    path = ""
  }
vnetmx commented 7 months ago

After checking the AWS provider's code here. Setting the matcher and the path explicitly to an empty string did the trick for me:

  health_check {
    protocol = "TCP"
    matcher = ""
    path = ""
  }

Thanks @janory. That did the trick!

TheRealWaldo commented 7 months ago

Using provider 5.3.3

health_check {
    protocol = "TCP"
    matcher = ""
    path = ""
  }

Now fails with Error: expected health_check.0.path to have prefix /, got as well as Error: expected length of health_check.0.path to be in the range (1 - 1024), got

Omitting the path results in Attribute "health_check[0].path" cannot be specified when "health_check[0].protocol" is "TCP". health_check[0].path

Setting the path to "/" results in Attribute "health_check[0].path" cannot be specified when "health_check[0].protocol" is "TCP". health_check[0].path

So it seems we are back to not having a workaround for this problem.

kkkhanenko commented 5 months ago

Using provider 5.27 (version with started supporting java 21) and seeing this issue. Please fix it otherwise upgrade to newer java version is not possible.