terraform 计数取决于来自目标环境的数据

terraform count dependent on data from target environment

我在尝试最初计划或应用使用 AWS 环境中的数据值的资源进行计数时遇到以下错误。

$ terraform plan 
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

Error: Invalid count argument

  on main.tf line 24, in resource "aws_efs_mount_target" "target":
  24:   count = length(data.aws_subnet_ids.subnets.ids)

The "count" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the count depends on.

$ terraform --version
Terraform v0.12.9
+ provider.aws v2.30.0

我尝试使用目标选项,但似乎不适用于数据类型。

$ terraform apply -target aws_subnet_ids.subnets

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

我发现唯一可行的解​​决方案是:

  1. 删除资源
  2. 申请项目
  3. 重新添加资源
  4. 再次申请

这是我为测试创建的 terraform 配置。

provider "aws" {
  version = "~> 2.0"
}

locals {
  project_id = "it_broke_like_3_collar_watch"
}

terraform {
  required_version = ">= 0.12"
}

resource aws_default_vpc default {
}

data aws_subnet_ids subnets {
  vpc_id = aws_default_vpc.default.id
}

resource aws_efs_file_system efs {
  creation_token = local.project_id
  encrypted = true
}

resource aws_efs_mount_target target {
  depends_on = [ aws_efs_file_system.efs ]
  count = length(data.aws_subnet_ids.subnets.ids)
  file_system_id = aws_efs_file_system.efs.id
  subnet_id = tolist(data.aws_subnet_ids.subnets.ids)[count.index]
}

aws_default_vpc 不是 TF 可以创建或销毁的资源。它是 AWS 自动为您创建的每个区域中您账户的默认 VPC,可防止被破坏。您只能(并且需要)将其用于管理和您的 TF 状态。这将允许您在 运行 计划或申请时开始管理和检查。否则,TF 不知道资源是什么或处于什么状态,并且它无法为您创建新资源,因为它是如上所述的一种特殊类型的受保护资源。

话虽如此,请从您在帐户中部署的正确区域获取默认 VPC ID。然后将其导入您的 TF 状态。然后它应该能够检查和计算子网的数量。

例如

terraform import aws_default_vpc.default vpc-xxxxxx

https://www.terraform.io/docs/providers/aws/r/default_vpc.html

为此使用 data 元素对我来说也有点奇怪。您可以更改您的 TF 脚本以直接通过 aws_default_vpc 资源获取计数吗?

研究了Dude0001的答案,终于找到答案了。

简答。使用带有默认参数的 aws_vpc 数据源,而不是 aws_default_vpc 资源。这是包含更改评论的工作示例。

locals {
  project_id = "it_broke_like_3_collar_watch"
}

terraform {
  required_version = ">= 0.12"
}

// Delete this --> resource aws_default_vpc default {}

// Add this
data aws_vpc default {
  default = true
}


data "aws_subnet_ids" "subnets" {
// Update this from aws_default_vpc.default.id 
  vpc_id = "${data.aws_vpc.default.id}"
}

resource aws_efs_file_system efs {
  creation_token = local.project_id
  encrypted = true
}

resource aws_efs_mount_target target {
  depends_on = [ aws_efs_file_system.efs ]
  count = length(data.aws_subnet_ids.subnets.ids)
  file_system_id = aws_efs_file_system.efs.id
  subnet_id = tolist(data.aws_subnet_ids.subnets.ids)[count.index]
}

我不明白为什么我在第一次申请时删除 aws_efs_mount_target 的工作有效。这是因为在第一次应用后 aws_default_vpc 被加载到状态文件中。

因此,不更改原始 tf 文件的替代解决方案是在第一次应用时使用目标选项:

$ terraform apply  --target aws_default_vpc.default

但是,我不喜欢这样,因为它在首次部署时需要特殊情况,这对于我使用过的 Terraform 部署来说非常独特。