繁体   English   中英

使用 for each 创建多个目标组和听众

[英]Create multiple target groups and listeners using for each

我正在尝试使用 For Each 在 Terraform 中创建多个应用程序目标组和侦听器。 我有一些复杂的设置来处理侦听器规则,以根据 HTTP 标头将流量路由到目标组。 下面是我写的资源:

resource "aws_lb_listener" "app_listener_forward" {
  for_each          = var.listeners
  load_balancer_arn = aws_lb.app_alb.arn
  port              = each.value.listeners
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
  certificate_arn   = var.ssl_cert

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app_tg[each.key].arn
  }
}

resource "aws_lb_listener_rule" "app_https_listener_rule" {
  for_each     = var.listeners
  listener_arn = aws_lb_listener.app_listener_forward[each.key].arn

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app_tg[each.key].arn
  }

  condition {
    path_pattern {
      values = each.value.paths
    }
  }
}

resource "aws_lb_target_group" "app_tg" {
  for_each    = var.listeners
  name        = each.key
  port        = each.value.app_port
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_vpc.app_vpc.id

  health_check {
    interval            = 130
    timeout             = 120
    healthy_threshold   = 10
    unhealthy_threshold = 10
  }

  stickiness {
    type            = "lb_cookie"
    cookie_duration = 86400
  }
}

下面是变量声明:

variable "listeners" {
  type = map(object({
    app_port  = number
    paths     = set(string)
    listeners = set(number)
  }))
  default = {
    "app_one" = {
       app_port = 3000
       paths = [
         "/appOne",
         "/appOne/*"
       ]
       listeners = [
         80, 443, 22, 7999, 8999
       ]
    }
    "app_two" = {
       app_port = 4000
       paths = [
         "/appTwo",
         "/appTwo/*"
       ]
       listeners = [
         80, 443, 22, 7999, 8999
       ]
    }
  }
}

尝试执行时,我在处理aws_lb_listener资源的port属性时遇到错误。 以下是错误:

Error: Incorrect attribute value type
│
│   on alb.tf line 38, in resource "aws_lb_listener" "app_listener_forward":
│   38:   port              = each.value.listeners
│     ├────────────────
│     │ each.value.listeners is set of string with 5 elements
│
│ Inappropriate value for attribute "port": number required.

由于数字列表,我尝试将变量的 listeners 属性设置为一个集合(数字)和一个集合(字符串),但我仍然收到此错误。

关于如何修复此错误的任何想法都会有所帮助。

谢谢!

错误消息指出resource "aws_lb_listener" "app_listener_forward" {..}中端口的值似乎不正确。

由于您已经在使用for_each循环整个资源,因此它不能在用于循环的变量中可用的值内循环。

一种解决方案是将可变listeners器分成两部分。

第 1 步:将变量分成 2 个变量

随意使用任何对您来说更有意义的名称。

variable "listner_ports" {
  type        = list(string)
  description = "(optional) listeners port numbers"
  default = [
    80, 443, 22, 7999, 8999
  ]
}
variable "listeners" {
  type = map(object({
    app_port = number
    paths    = set(string)
  }))
  default = {
    "app-one" = {
      app_port = 3000
      paths = [
        "/appOne",
        "/appOne/*"
      ]
    }
    "app-two" = {
      app_port = 4000
      paths = [
        "/appTwo",
        "/appTwo/*"
      ]
    }
  }
}

注意:我已将app_{one,two}更改为app-{one,two}因为aws_lb_target_group“名称”中只允许使用字母数字字符和连字符

第 2 步:使用aws_lb_listener中的 terraform 动态块对同一资源中的不同变量使用循环。

resource "aws_lb_listener" "app_listener_forward" {
  for_each          = toset(var.listner_ports)
  load_balancer_arn = data.aws_lb.test.arn ## Use aws_lb.app_alb.arn as per your usecase
  port              = each.value
  protocol          = "HTTP" # you might need to use a more complex variable to support ports and protocols but it gives an idea.
## Uncommend in your case.
  # ssl_policy        = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
  # certificate_arn   = var.ssl_cert

  dynamic "default_action" {
    for_each = var.listeners

    content {
      type             = "forward"
      target_group_arn = aws_lb_target_group.app_tg[default_action.key].arn
    }
  }
}

resource "aws_lb_target_group" "app_tg" {
  for_each    = var.listeners
  name        = each.key
  port        = each.value.app_port
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = local.vpc_id

  health_check {
    interval            = 130
    timeout             = 120
    healthy_threshold   = 10
    unhealthy_threshold = 10
  }

  stickiness {
    type            = "lb_cookie"
    cookie_duration = 86400
  }
}

只是为了向您展示它是如何工作的,下面是仅aws_lb_listeneraws_lb_target_group资源的附加计划。

Terraform will perform the following actions:

  # aws_lb_listener.app_listener_forward["22"] will be created
  + resource "aws_lb_listener" "app_listener_forward" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
      + port              = 22
      + protocol          = "HTTP"
      + ssl_policy        = (known after apply)
      + tags_all          = (known after apply)

      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
    }

  # aws_lb_listener.app_listener_forward["443"] will be created
  + resource "aws_lb_listener" "app_listener_forward" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
      + port              = 443
      + protocol          = "HTTP"
      + ssl_policy        = (known after apply)
      + tags_all          = (known after apply)

      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
    }

  # aws_lb_listener.app_listener_forward["7999"] will be created
  + resource "aws_lb_listener" "app_listener_forward" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
      + port              = 7999
      + protocol          = "HTTP"
      + ssl_policy        = (known after apply)
      + tags_all          = (known after apply)

      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
    }

  # aws_lb_listener.app_listener_forward["80"] will be created
  + resource "aws_lb_listener" "app_listener_forward" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
      + port              = 80
      + protocol          = "HTTP"
      + ssl_policy        = (known after apply)
      + tags_all          = (known after apply)

      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
    }

  # aws_lb_listener.app_listener_forward["8999"] will be created
  + resource "aws_lb_listener" "app_listener_forward" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + load_balancer_arn = "arn:aws:elasticloadbalancing:eu-central-1:xxxxxxxxxxxxxx:loadbalancer/app/stackoverflow/be9c11ed9c543788"
      + port              = 8999
      + protocol          = "HTTP"
      + ssl_policy        = (known after apply)
      + tags_all          = (known after apply)

      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
      + default_action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }
    }

  # aws_lb_target_group.app_tg["app-one"] will be created
  + resource "aws_lb_target_group" "app_tg" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + connection_termination             = false
      + deregistration_delay               = "300"
      + id                                 = (known after apply)
      + ip_address_type                    = (known after apply)
      + lambda_multi_value_headers_enabled = false
      + load_balancing_algorithm_type      = (known after apply)
      + name                               = "app-one"
      + port                               = 3000
      + preserve_client_ip                 = (known after apply)
      + protocol                           = "HTTP"
      + protocol_version                   = (known after apply)
      + proxy_protocol_v2                  = false
      + slow_start                         = 0
      + tags_all                           = (known after apply)
      + target_type                        = "ip"
      + vpc_id                             = "vpc-063017c6abb96eab6"

      + health_check {
          + enabled             = true
          + healthy_threshold   = 10
          + interval            = 130
          + matcher             = (known after apply)
          + path                = (known after apply)
          + port                = "traffic-port"
          + protocol            = "HTTP"
          + timeout             = 120
          + unhealthy_threshold = 10
        }

      + stickiness {
          + cookie_duration = 86400
          + enabled         = true
          + type            = "lb_cookie"
        }

      + target_failover {
          + on_deregistration = (known after apply)
          + on_unhealthy      = (known after apply)
        }
    }

  # aws_lb_target_group.app_tg["app-two"] will be created
  + resource "aws_lb_target_group" "app_tg" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + connection_termination             = false
      + deregistration_delay               = "300"
      + id                                 = (known after apply)
      + ip_address_type                    = (known after apply)
      + lambda_multi_value_headers_enabled = false
      + load_balancing_algorithm_type      = (known after apply)
      + name                               = "app-two"
      + port                               = 4000
      + preserve_client_ip                 = (known after apply)
      + protocol                           = "HTTP"
      + protocol_version                   = (known after apply)
      + proxy_protocol_v2                  = false
      + slow_start                         = 0
      + tags_all                           = (known after apply)
      + target_type                        = "ip"
      + vpc_id                             = "vpc-063017c6abb96eab6"

      + health_check {
          + enabled             = true
          + healthy_threshold   = 10
          + interval            = 130
          + matcher             = (known after apply)
          + path                = (known after apply)
          + port                = "traffic-port"
          + protocol            = "HTTP"
          + timeout             = 120
          + unhealthy_threshold = 10
        }

      + stickiness {
          + cookie_duration = 86400
          + enabled         = true
          + type            = "lb_cookie"
        }

      + target_failover {
          + on_deregistration = (known after apply)
          + on_unhealthy      = (known after apply)
        }
    }

Plan: 7 to add, 0 to change, 0 to destroy.

希望能帮助到你。 并且,是的,我已经屏蔽了帐户 ID:)。

已编辑

这部分是在阅读@David 的评论后添加的,他在评论中提到了另一个问题 ERROR Message: "InvalidLoadBalancerAction: You cannot specify multiple of the following action type: 'forward'" when trying to create the listener.

将其用作您的aws_lb_listener的基本代码,我强烈建议您根据最佳解决方案进行修改。[嵌套动态块 --> 有关文档,请参阅此处]


resource "aws_lb_listener" "app_listener_forward" {
  for_each          = toset(var.listner_ports)
  load_balancer_arn = aws_lb.test.arn
  port              = each.value
  protocol          = "HTTP" # you might need to use a more complex variable to support ports and protocols but it gives an idea.
## Uncommend in your case.
  # ssl_policy        = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
  # certificate_arn   = var.ssl_cert

  default_action {
    type = "forward"
    forward {
      dynamic "target_group" {
        for_each = var.listeners
        content {
          arn = aws_lb_target_group.app_tg[target_group.key].arn
        }
      }
      stickiness {
        enabled  = true
        duration = 86400
      }
    }
  }
}

结论: Apply 确实按预期使用上述代码(为具有不同端口的两个目标组创建了多个侦听器)但无法确认这是否是您所需要的,但是,可以根据要求调整解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM