我有两个target_groups-一个用于端口80,另一个用于443。还具有两个实例(作为该NLB的成员),并且我需要将两个目标组都附加到每个实例。因此,这就是我配置的方式:
// Creates the target-group
resource "aws_lb_target_group" "nlb_target_groups" {
for_each = {
for lx in var.nlb_listeners : "${lx.protocol}:${lx.target_port}" => lx
}
name = "${var.vpc_names[var.idx]}-tgr-${each.value.target_port}"
deregistration_delay = var.deregistration_delay
port = each.value.target_port
protocol = each.value.protocol
vpc_id = var.vpc_ids[var.idx]
proxy_protocol_v2 = true
health_check {
port = each.value.health_port
protocol = each.value.protocol
interval = var.health_check_interval
healthy_threshold = var.healthy_threshold
unhealthy_threshold = var.unhealthy_threshold
}
}
// Attach the target groups to the instance(s)
resource "aws_lb_target_group_attachment" "tgr_attachment" {
for_each = {
for pair in setproduct(keys(aws_lb_target_group.nlb_target_groups), var.nlb_members.ids) : "${pair[0]}:${pair[1]}" => {
target_group = aws_lb_target_group.nlb_target_groups[pair[0]]
instance_id = pair[1]
}
}
target_group_arn = each.value.target_group.arn
target_id = each.value.instance_id
port = each.value.target_group.port
#target_id = [for tid in range(var.inst_count) : data.aws_instances.nlb_insts.ids[tid]]
}
其中var.nlb_listeners
的定义如下:
nlb_listeners = [
{
protocol = "TCP"
target_port = "80"
health_port = "1936"
},
{
protocol = "TCP"
target_port = "443"
health_port = "1936"
}
]
和var.elb_members.ids
像这样:
"ids" = [
"i-015604f88xxxxxx42",
"i-0e4defceexxxxxxe5",
]
但是我收到无效的for_each参数错误:
错误:无效的for_each参数
资源中../../modules/elb/balencer.tf第46行的“ aws_lb_target_group_attachment”“ tgr_attachment”:46:for_each = {47:配对 setproduct(键(aws_lb_target_group.nlb_target_groups), var.elb_members.ids):“ $ {pair [0]}:$ {pair [1]}” => {48:
target_group = aws_lb_target_group.nlb_target_groups [pair [0]] 49:
instance_id = pair [1] 50:} 51:}“ for_each”值取决于不能为 确定直到应用,所以Terraform无法预测有多少个实例 将被创建。要解决此问题,请使用-target参数 首先仅应用for_each依赖的资源。
我无法弄清楚为什么无效或 for_each 无法确定值。知道我在做什么错吗?认真地陷在中间,非常感谢您能为我提供正确的指导。
-S
===更新:02/23 =========
@ martin-atkins,
我想我理解您的意思,但是即使对于已经存在的实例,它似乎也给我带来同样的错误。无论如何,这是我的aws_instance
资源:
resource "aws_instance" "inst" {
count = var.inst_count
instance_type = var.inst_type
depends_on = [aws_subnet.snets]
ami = data.aws_ami.ubuntu.id
# the VPC subnet
subnet_id = element(aws_subnet.snets.*.id, count.index)
vpc_security_group_ids = [var.sg_default[var.idx], aws_security_group.secg.id]
user_data = <<-EOF
#!/bin/bash
hostnamectl set-hostname ${var.vpc_names[var.idx]}${var.inst_role}0${count.index + 1}
# Disable apt-daily.service & wait until `apt updated` has been killed
systemctl stop apt-daily.service && systemctl kill --kill-who=all apt-daily.service
while ! (systemctl list-units --all apt-daily.service | egrep -q '(dead|failed)')
do sleep 1; done
EOF
# the public SSH key
key_name = var.key_info
tags = merge(
var.common_tags,
{ "Name" = "${var.vpc_names[var.idx]}${var.inst_role}0${count.index + 1}" }
)
}
您认为可以采取其他任何措施来解决该问题吗?
-S
答案 0 :(得分:1)
EC2实例ID,因此AWS提供商无法在计划阶段对其进行预先计算。因此,它们不适合用作for_each
映射键的一部分。
相反,对于那些实例,您需要使用其他一些标识符,这些标识符由配置本身确定,而不是由应用程序在应用期间由提供程序返回的数据确定。您没有共享实例本身的配置,因此我无法提出具体建议,但是如果它们都是count
或for_each
创建的同一资源的所有实例,那么通常的选择是使用每个实例的索引(对于count
)或每个实例的唯一键(对于for_each
),以便将添加和删除该映射的元素以与要添加的实例本身相对应,并删除。
答案 1 :(得分:0)
最后我已经解决了。不知道这是否是最好的方法,但是现在为我工作是没有错误的。基本上,我已经像这样更改了数据查找:
// List of instance attributes by role
data "aws_instance" "by_role" {
for_each = {
for ic in range(var.inst_count): "${var.inst_role}0${ic+1}" => ic
}
instance_tags = {
Name = "${var.vpc_names[var.idx]}${each.key}"
}
instance_id = aws_instance.inst[substr(each.key,4,2)-1].id
}
并在for_each
中这样使用它:
for_each = {
for pair in setproduct(keys(aws_lb_target_group.nlb_target_groups), keys(aws_instance.by_role)):
"${pair[0]}:${pair[1]}" => {
target_group = aws_lb_target_group.nlb_target_groups[pair[0]]
member_name = aws_instance.by_role[pair[1]]
}
}
细节是here,在Terraform社区论坛中回答了我自己的问题,以防万一有人遇到与我相同的问题。
-圣