You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform使用count从列表取值创建Azure子网报错求助

问题:Terraform创建Azure子网时address_prefixes类型错误

我需要根据启用的环境数量(ENA/DMZ/BDL),从预定义的CIDR列表中取值,动态创建对应数量的Azure子网,但所有尝试的方案都报类型不匹配错误。


初始尝试(列表方式)

locals.tf

locals {
  build_ena_true       = var.build_ena ? 1 : 0
  build_dmz_true       = var.build_dmz ? 1 : 0
  build_bdl_true       = var.build_bdl ? 1 : 0
  azurerm_cidrs = [
    cidrsubnet("10.1.2.0/24", 1, 0),
    cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 0),
    cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 1)
  ]
}

network.tf

resource "azurerm_subnet" "subnet" {
  count                = local.build_ena_true + local.build_dmz_true + local.build_bdl_true
  name                 = "${var.azurerm_resource_prefix}-${local.env_short_name}-snet-${format("%03d", count.index + 1)}"
  resource_group_name  = var.azurerm_net_resource_group
  virtual_network_name = var.azurerm_network_name
  address_prefixes     = local.azurerm_cidrs[count.index]
}

错误信息

Error: Incorrect attribute value type

on network.tf line 21, in resource "azurerm_subnet" "subnet":
21: address_prefixes = local.azurerm_cidrs[count.index]
├────────────────
│ count.index is 0
│ local.azurerm_cidrs is tuple with 3 elements

Inappropriate value for attribute "address_prefixes": list of string required.


第二种尝试(Map+lookup方式)

locals.tf

locals {
  build_ena_true       = var.build_ena ? 1 : 0
  build_dmz_true       = var.build_dmz ? 1 : 0
  build_bdl_true       = var.build_bdl ? 1 : 0
  azurerm_cidrs = {
    0 = cidrsubnet("10.1.2.0/24", 1, 0)
    1 = cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 0)
    2 = cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 1)
  }
}

network.tf

resource "azurerm_subnet" "subnet" {
  count                = local.build_ena_true + local.build_dmz_true + local.build_bdl_true
  name                 = "${var.azurerm_resource_prefix}-${local.env_short_name}-snet-${format("%03d", count.index + 1)}"
  resource_group_name  = var.azurerm_net_resource_group
  virtual_network_name = var.azurerm_network_name
  address_prefixes     = lookup(local.azurerm_cidrs, tostring(count.index), "")
}

错误信息

Error: Incorrect attribute value type

on network.tf line 21, in resource "azurerm_subnet" "subnet":
21: address_prefixes = lookup(local.azurerm_cidrs, tostring(count.index), "")
├────────────────
│ count.index is 1
│ local.azurerm_cidrs is object with 3 attributes

Inappropriate value for attribute "address_prefixes": list of string required.


使用的Provider配置

terraform {
  required_version = ">= 1.9.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.4.0"
    }
  }
}

问题原因及解决方法

核心问题是AzureRM子网的address_prefixes属性要求传入字符串列表(list(string)),但你直接传入了单个字符串(cidrsubnet函数返回的是string类型),导致类型不匹配。

修正方案1:直接包装为列表

修改network.tf中的address_prefixes字段,把单个CIDR值包装成列表:

resource "azurerm_subnet" "subnet" {
  count                = local.build_ena_true + local.build_dmz_true + local.build_bdl_true
  name                 = "${var.azurerm_resource_prefix}-${local.env_short_name}-snet-${format("%03d", count.index + 1)}"
  resource_group_name  = var.azurerm_net_resource_group
  virtual_network_name = var.azurerm_network_name
  address_prefixes     = [local.azurerm_cidrs[count.index]]
}

修正方案2:提前定义嵌套列表

如果想在locals中提前处理好格式,可将azurerm_cidrs定义为列表的列表:

locals {
  build_ena_true       = var.build_ena ? 1 : 0
  build_dmz_true       = var.build_dmz ? 1 : 0
  build_bdl_true       = var.build_bdl ? 1 : 0
  azurerm_cidrs = [
    [cidrsubnet("10.1.2.0/24", 1, 0)],
    [cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 0)],
    [cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 1)]
  ]
}

之后network.tf可直接使用原写法:

address_prefixes     = local.azurerm_cidrs[count.index]

额外优化:用for_each替代count(更直观)

当前通过count求和的方式不够清晰,可改用for_each直接关联启用的环境与对应CIDR,同时自动生成关联名称:

locals {
  enabled_environments = merge(
    var.build_ena ? { ena = cidrsubnet("10.1.2.0/24", 1, 0) } : {},
    var.build_dmz ? { dmz = cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 0) } : {},
    var.build_bdl ? { bdl = cidrsubnet(cidrsubnet("10.1.2.0/24", 1, 1), 1, 1) } : {}
  )
}

resource "azurerm_subnet" "subnet" {
  for_each             = local.enabled_environments
  name                 = "${var.azurerm_resource_prefix}-${local.env_short_name}-snet-${each.key}"
  resource_group_name  = var.azurerm_net_resource_group
  virtual_network_name = var.azurerm_network_name
  address_prefixes     = [each.value]
}

这种方式无需手动维护count值,子网名称直接关联环境类型,更易维护。


内容的提问来源于stack exchange,提问作者Dragonsys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 19:04:58