![](/img/trans.png)
[英]Terraform create multiple resources using for_each and jsondecode
[英]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
器分成两部分。
随意使用任何对您来说更有意义的名称。
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“名称”中只允许使用字母数字字符和连字符
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_listener
和aws_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.