Terraform:尝试使用列表创建一系列子网 cidr,但出现错误“需要字符串”

Posted

技术标签:

【中文标题】Terraform:尝试使用列表创建一系列子网 cidr,但出现错误“需要字符串”【英文标题】:Terraform: Trying to create a range of subnet cidrs using a list, but getting error "string required" 【发布时间】:2020-09-24 17:41:27 【问题描述】:

按照以下创建范围列表

subnet_names = ["subnet-lister", "subnet-kryten", "subnet-rimmer", "subnet-cat", "subnet-holly",]
subnet_cidrs = ["192.2.128.0/18", "192.2.0.0/17", "192.2.208.0/20", "192.2.192.0/20", "192.2.224.0/20",]

在 subnets.tf 中有这个

resource "google_compute_subnetwork" "subnet" 
  name          = "$var.subnet_names-subnet"
  ip_cidr_range = var.subnet_cidrs
  network       = var.network_name
  region        = var.subnet_region

以及 variables.tf 中的以下内容(用于模块)

variable "subnet_names" 
  description = "The name to use for Subnet "
  type        =  list(string)


variable "subnet_cidrs" 
  description = "The cidr range for for Subnets"
  type        = list(string)

但是从 Terraform 收到以下消息。

Error: Incorrect attribute value type

  on ..\..\..\Test-Modules\red\dwarf\subnets.tf line 3, in resource "google_compute_subnetwork" "subnet":
   3:   ip_cidr_range = var.subnet_cidrs

Inappropriate value for attribute "ip_cidr_range": string required.

我对此很陌生,你能帮我弄清楚我出了什么问题吗?我似乎有人使用 cidr 范围的列表(请注意,这是针对 AWS 的)。 GCP 不支持吗?

【问题讨论】:

【参考方案1】:

看起来您实际上是在创建多个子网。为此,您应该使用 map 变量和循环。

variable "subnets" 
    type = map(string)


resource "google_compute_subnetwork" "subnet" 
  for_each      = var.subnets
  name          = each.key
  ip_cidr_range = each.value
  ...

然后您可以提供如下子网:

subnets = 
    subnet-lister = "192.2.128.0/18",
    subnet-kryten = "192.2.0.0/17",
    ...

【讨论】:

我没有收到错误“此处不应出现名为“子网”的参数。”假设这应该在我的 main.tf 中('subnets =' 部分 ``` subnets= 部分是您传入的变量的值。请参阅这些文档:terraform.io/docs/configuration/… 现在一切正常。但是我遇到了一个新问题,试图输出这些子网的 IP 地址。我想我也许可以使用 [0] 将它们从列表中的位置拉出来,但这似乎不起作用。有什么想法吗? 如果将后续问题作为单独的问题发布会更容易回答,但快速回答是 for k, s in google_compute_network.subnet : k => s.id ,其中s.id 检索每个子网的ID。您可以通过这种方式使用google_compute_network 的任何属性来生成从子网名称到所选值的映射。【参考方案2】:

根据Terraform Docs,ip_cidr_range 只需要一个 CIDR-Block,而不是一个列表。因此,您需要为每个子网创建一个资源,如下所示:

resource "google_compute_subnetwork" "subnet" 
  count = length(var.subnet_names)

  name          = "$var.subnet_names[count.index]-subnet"
  ip_cidr_range = var.subnet_cidrs[count.index]
  network       = var.network_name
  region        = var.subnet_region

  ...

我还建议对您的数据进行一些重组,以便您可以使用 for_each 而不是 count(查看 Ben 的答案)。如果您稍后更改配置并插入新子网,这会表现得更好,正如in this post 中所描述的那样。

【讨论】:

慢慢到达那里。现在在使用您建议的网站时,给定值不适合 cidr 上的子模块“给定值不适合在 ..\..\..\Modules\subnets\variables.tf 中定义的子模块变量“subnet_cidrs” :16,1-24: 需要字符串映射。 知道了!结合 Ben 的子网列表和您建议的重组。一起工作!

以上是关于Terraform:尝试使用列表创建一系列子网 cidr,但出现错误“需要字符串”的主要内容,如果未能解决你的问题,请参考以下文章

如何在不满足给定条件的情况下创建一系列变量并将它们存储在列表中?

使用 Terraform 的 aws 子网的子网范围无效

AWS VPC 模块公有和私有子网 - Terraform

Pandas:通过从列表的字典映射创建一列

Terraform 模块 - 输出变量作为另一个模块的输入

使用扩展语法创建一系列自然数