基于Express Route线路配置状态条件创建网关的Terraform问题
问题:根据Express Route线路状态条件创建网关失败
需求:通过Terraform实现仅当Express Route线路的服务商状态变为Provisioned时,才创建高成本的Express Route网关。首次运行流水线时,线路已创建但状态为Unprovisioned,需跳过网关创建;待服务商配置完成(状态变为Provisioned)后,再次运行流水线时自动创建网关。
遇到的错误
错误:无效的count参数
│
│ 在main.tf第75行,资源"azurerm_virtual_network_gateway" "example"中:
│ 75: count =data.azurerm_express_route_circuit.expressr_status.service_provider_provisioning_state == "Provisioned" ? 1 : 0
│
│ "count"值依赖于需在apply阶段才能确定的资源属性,因此Terraform无法预测将创建多少个实例。解决方法是使用-target参数先仅应用count依赖的资源。
原Terraform代码
resource "azurerm_resource_group" "example-express-rg" { name = "example-vnet-rg" location = "West Europe" } resource "azurerm_virtual_network" "vnettest" { name = "example-vnet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.example-express-rg.location resource_group_name = azurerm_resource_group.example-express-rg.name } resource "azurerm_subnet" "gateway_subnet" { name = "GatewaySubnet" resource_group_name = azurerm_resource_group.example-express-rg.name virtual_network_name = azurerm_virtual_network.vnettest.name address_prefixes = ["10.0.1.0/24"] } resource "azurerm_public_ip" "publicip" { name = "example-public-ip" location = azurerm_resource_group.example-express-rg.location resource_group_name = azurerm_resource_group.example-express-rg.name allocation_method = "Static" sku = "Standard" } resource "azurerm_resource_group" "expressrg" { name = "exprtTest" location = "West Europe" } resource "azurerm_express_route_circuit" "expressr" { name = "expressRoute1" resource_group_name = azurerm_resource_group.expressrg.name location = azurerm_resource_group.expressrg.location service_provider_name = "Equinix" peering_location = "Singapore" bandwidth_in_mbps = 1000 sku { tier = "Standard" family = "MeteredData" } tags = { Purpose = "Resource" ResorceOwner = "CCTeam" } } # Data Source to Check the Status of the ExpressRoute Circuit data "azurerm_express_route_circuit" "expressr_status" { name = azurerm_express_route_circuit.expressr.name resource_group_name = azurerm_resource_group.expressrg.name } # Virtual Network Gateway (Create Conditionally) resource "azurerm_virtual_network_gateway" "example" { depends_on = [azurerm_express_route_circuit.expressr] count = data.azurerm_express_route_circuit.expressr_status.service_provider_provisioning_state == "Provisioned" ? 1 : 0 name = "testgw" location = azurerm_resource_group.example-express-rg.location resource_group_name = azurerm_resource_group.example-express-rg.name type = "ExpressRoute" vpn_type = "PolicyBased" sku = "Standard" ip_configuration { name = "vnetGatewayConfig" public_ip_address_id = azurerm_public_ip.publicip.id private_ip_address_allocation = "Dynamic" subnet_id = azurerm_subnet.gateway_subnet.id } tags = { Purpose = "Resource" ResorceOwner = "CCTeam" } }
解决方案
方案一:直接引用线路资源属性(自动化检测状态)
删除多余的data块,直接使用线路资源本身的service_provider_provisioning_state属性判断,避免依赖apply阶段的数据源。
修改后的网关资源代码:
resource "azurerm_virtual_network_gateway" "example" { depends_on = [azurerm_express_route_circuit.expressr] count = azurerm_express_route_circuit.expressr.service_provider_provisioning_state == "Provisioned" ? 1 : 0 name = "testgw" location = azurerm_resource_group.example-express-rg.location resource_group_name = azurerm_resource_group.example-express-rg.name type = "ExpressRoute" vpn_type = "PolicyBased" sku = "Standard" ip_configuration { name = "vnetGatewayConfig" public_ip_address_id = azurerm_public_ip.publicip.id private_ip_address_allocation = "Dynamic" subnet_id = azurerm_subnet.gateway_subnet.id } tags = { Purpose = "Resource" ResorceOwner = "CCTeam" } }
操作步骤:
- 首次运行
terraform apply,创建Express Route线路及网关依赖的VNet、子网、公网IP,此时线路状态为Unprovisioned,网关因count=0不会创建。 - 等待服务商完成配置,线路状态变为
Provisioned后,运行terraform refresh获取Azure端最新的线路状态。 - 再次运行
terraform apply,Terraform检测到线路状态已就绪,自动创建网关。
方案二:使用输入变量手动控制(更可控)
通过定义布尔变量,手动控制网关的创建时机,避免依赖状态同步延迟。
- 添加变量定义:
variable "create_gateway" { type = bool default = false description = "当Express Route线路状态为Provisioned后,设置为true以创建网关" }
- 修改网关的
count参数:
resource "azurerm_virtual_network_gateway" "example" { depends_on = [azurerm_express_route_circuit.expressr] count = var.create_gateway ? 1 : 0 # 其余代码保持不变 }
操作步骤:
- 首次运行
terraform apply,默认create_gateway=false,跳过网关创建。 - 确认线路状态变为
Provisioned后,运行terraform apply -var create_gateway=true触发网关创建。
方案对比
- 方案一自动化程度高,无需手动干预,但需确保Terraform能获取到Azure端的最新状态,适合状态同步及时的场景。
- 方案二更可控,避免因状态同步延迟导致的误操作,适合流水线中需要人工确认后再创建资源的场景。
内容的提问来源于stack exchange,提问作者Deepika
相关产品推荐
相关产品推荐

