terraform:data.aws_subnet,无法计算“ count”的值

问题描述

terraform版本0.11.13

错误错误刷新状态:发生1个错误

VPC代码产生了以上错误

resources.tf
data "aws_subnet_ids" "private_subnet_ids" {
  vpc_id            = "${module.vpc.vpc_id}"
}
data "aws_subnet" "private_subnet" {
  count = "${length(data.aws_subnet_ids.private_subnet_ids.ids)}"
  #count = "${length(var.private-subnet-mapping)}"
  id    = "${data.aws_subnet_ids.private_subnet_ids.ids[count.index]}"
}

更改上面的代码以使用count =“ $ {length(var.private-subnet-mapping)}”,我成功设置了VPC。但是,vpc_private_subnets_ids的输出为空。 vpc_private_subnets_ids = []

代码配置了VPC,但没有vpc_private_subnets_ids的空列表:

resources.tf

data "aws_subnet_ids" "private_subnet_ids" {
  vpc_id            = "${module.vpc.vpc_id}"
}
data "aws_subnet" "private_subnet" {
  #count = "${length(data.aws_subnet_ids.private_subnet_ids.ids)}"
  count = "${length(var.private-subnet-mapping)}"
  id    = "${data.aws_subnet_ids.private_subnet_ids.ids[count.index]}"
}

outputs.tf
output "vpc_private_subnets_ids" {
  value = ["${data.aws_subnet.private_subnet.*.id}"]
}

The output of vpc_private_subnets_ids:
vpc_private_subnets_ids = []

我需要vpc_private_subnets_ids的值。成功配置VPC使用该行之后,计数=“ $ {length(var.private-subnet-mapping)}”,我将代码改回计数为“ $ {length(data.aws_subnet_ids.private_subnet_ids.ids)}”。 terraform apply,我得到了列表vpc_private_subnets_ids的值,没有上述错误

vpc_private_subnets_ids = [
    subnet-03199b39c60111111,subnet-068a3a3e76de66666,subnet-04b86aa9dbf333333,subnet-02e1d8baa8c222222
    ......
]

我在配置VPC时无法使用count =“ $ {length(data.aws_subnet_ids.private_subnet_ids.ids)}”。但是,我可以在配置VPC之后使用它。有任何线索吗?

解决方法

这里的问题似乎是您的VPC尚未创建,因此读取data "aws_subnet_ids" "private_subnet_ids"数据源必须等到应用步骤,这反过来意味着子网的数目未知,并且因此data "aws_subnet" "private_subnet"实例的数量是不可预测的,并且Terraform返回此错误。

如果此配置也是负责创建这些子网的配置,那么更好的设计是直接引用子网对象。如果您的module.vpc也是创建子网的模块,那么我建议将子网ID导出为该模块的输出。例如:

output "subnet_ids" {
  value = "${aws_subnet.example.*.id}"
}

您的调用模块随后可以直接从module.vpc.subnet_ids获取这些ID,而无需进行多余的额外API调用来查找它们:

output "vpc_private_subnets_ids" {
  value = ["${module.vpc.subnet_ids}"]
}

除了关于count的错误外,您显示的配置还具有竞争条件,因为data "aws_subnet_ids" "private_subnet_ids"块仅取决于VPC本身,而不取决于单个VPC,因此Terraform可以在创建子网之前,请先读取该数据源。通过模块输出导出子网ID意味着对module.vpc.subnet_ids的任何间接引用都取决于所有子网,因此这些下游操作将等待,直到所有子网都已创建。

作为一般规则,特定的Terraform配置应该管理对象通过数据源读取该对象,而不是两者都一起使用。如果两者一起使用,有时可能会起作用,但是很容易无意间引入这样的竞争条件,即Terraform不能告诉data资源正在尝试消耗另一个resource块的结果参与同一计划。