Terraform AzureRM中public_ips参数报错及执行计划失败求助
解决Terraform AzureRM公网IP查询崩溃问题
问题根源
- 首次执行计划后,outbound IP已被Kubernetes集群关联,原数据源仅查询
Unattached状态的IP,导致已关联的outbound IP不在结果列表中。 - 直接用
[0]索引空列表会触发崩溃,而你的AzureRM 3.25.0版本尚不支持attachment_status = "All"参数(该参数为后续版本新增)。
解决方案
方案一:简化数据源配置(推荐)
AzureRM旧版本中,azurerm_public_ips数据源不指定attachment_status时,默认返回资源组内所有公网IP(无论关联状态)。结合one()函数避免索引报错:
修改后的完整代码:
# 查询资源组内所有公网IP(默认返回全部状态) data "azurerm_public_ips" "all_ip_addresses" { resource_group_name = azurerm_resource_group.rg.name } locals { # 使用one()函数获取唯一匹配的IP:找到则返回该对象,空列表返回null,多匹配会报错(符合IP名称唯一的场景) inbound_ipv4 = one([for ip in data.azurerm_public_ips.all_ip_addresses.public_ips : ip if ip.name == "ip-${var.cluster_name}-inbound"]) outbound_ipv4 = one([for ip in data.azurerm_public_ips.all_ip_addresses.public_ips : ip if ip.name == "ip-${var.cluster_name}-outbound"]) resource_group_name = var.resource_group rg = azurerm_resource_group.rg }
方案二:分状态查询后合并(兼容特殊场景)
如果需要明确区分关联/未关联IP,可创建两个数据源分别查询,再合并结果:
# 查询未关联的公网IP data "azurerm_public_ips" "unattached" { resource_group_name = azurerm_resource_group.rg.name attachment_status = "Unattached" } # 查询已关联的公网IP data "azurerm_public_ips" "attached" { resource_group_name = azurerm_resource_group.rg.name attachment_status = "Attached" } locals { # 合并两种状态的IP列表 all_public_ips = concat(data.azurerm_public_ips.unattached.public_ips, data.azurerm_public_ips.attached.public_ips) inbound_ipv4 = one([for ip in local.all_public_ips : ip if ip.name == "ip-${var.cluster_name}-inbound"]) outbound_ipv4 = one([for ip in local.all_public_ips : ip if ip.name == "ip-${var.cluster_name}-outbound"]) resource_group_name = var.resource_group rg = azurerm_resource_group.rg }
关键说明
one()函数:Terraform 0.13+支持,专门处理“预期有且仅有一个元素”的场景,避免直接索引[0]导致的崩溃。如果匹配结果为空,会返回null而非报错;如果有多个匹配结果,会抛出错误(符合IP名称唯一的业务逻辑)。- 若需强制要求必须找到匹配的IP,可添加断言逻辑:
locals { inbound_ipv4 = one([for ip in data.azurerm_public_ips.all_ip_addresses.public_ips : ip if ip.name == "ip-${var.cluster_name}-inbound"]) outbound_ipv4 = one([for ip in data.azurerm_public_ips.all_ip_addresses.public_ips : ip if ip.name == "ip-${var.cluster_name}-outbound"]) # 断言必须找到两个IP _assert_ips_exist = assert(local.inbound_ipv4 != null && local.outbound_ipv4 != null, "未找到指定名称的公网IP") }
内容的提问来源于stack exchange,提问作者CloudAnywhere
相关产品推荐
相关产品推荐

