Terraform内联虚拟网络中子网ID获取与路由表关联求助
问题
我正在使用Terraform创建虚拟网络,子网是在虚拟网络资源块内创建(而非使用独立的资源块)。我尝试为这些子网关联一些路由表,但不确定如何获取在虚拟网络内创建的子网的资源ID,能否有人提供帮助?
main.tf
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "3.24.0" } } } provider "azurerm" { skip_provider_registration = true features {} } ########################### # RESOURCE GROUP CREATION # ########################### resource "azurerm_resource_group" "rg" { name = var.rg.name location = var.rg.location } ############################ # VIRTUAL NETWORK CREATION # ############################ resource "azurerm_virtual_network" "vnet" { name = var.vnet.name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location address_space = var.vnet.address_space dns_servers = var.vnet.dns_servers subnet { name = var.vnet.subnet1_name address_prefix = var.vnet.subnet1_address_prefix } subnet { name = var.vnet.subnet2_name address_prefix = var.vnet.subnet2_address_prefix } subnet { name = var.vnet.subnet3_name address_prefix = var.vnet.subnet3_address_prefix } subnet { name = var.vnet.subnet4_name address_prefix = var.vnet.subnet4_address_prefix } subnet { name = var.vnet.subnet5_name address_prefix = var.vnet.subnet5_address_prefix } } ######################## # ROUTE TABLE CREATION # ######################## resource "azurerm_route_table" "fslogix_rt" { name = var.rt.fslogix.name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location disable_bgp_route_propagation = false } resource "azurerm_route_table" "back_office_rt" { name = var.rt.back_office.name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location disable_bgp_route_propagation = false } resource "azurerm_route_table" "dev_dev_rt" { name = var.rt.dev_dev.name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location disable_bgp_route_propagation = false } resource "azurerm_route_table" "dev_prod_rt" { name = var.rt.dev_prod.name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location disable_bgp_route_propagation = false } resource "azurerm_route_table" "front_office_rt" { name = var.rt.front_office.name resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location disable_bgp_route_propagation = false } ################## # ROUTE CREATION # ################## resource "azurerm_route" "fslogix_routes" { for_each = var.fslogix_routes name = each.value.name resource_group_name = azurerm_resource_group.rg.name route_table_name = azurerm_route_table.fslogix_rt.name address_prefix = each.value.address_prefix next_hop_type = each.value.next_hop_type next_hop_in_ip_address = each.value.next_hop_in_ip_address } resource "azurerm_route" "back_office_routes" { for_each = var.back_office_routes name = each.value.name resource_group_name = azurerm_resource_group.rg.name route_table_name = azurerm_route_table.back_office_rt.name address_prefix = each.value.address_prefix next_hop_type = each.value.next_hop_type next_hop_in_ip_address = each.value.next_hop_in_ip_address } resource "azurerm_route" "dev_dev_routes" { for_each = var.developer_dev_routes name = each.value.name resource_group_name = azurerm_resource_group.rg.name route_table_name = azurerm_route_table.dev_dev_rt.name address_prefix = each.value.address_prefix next_hop_type = each.value.next_hop_type next_hop_in_ip_address = each.value.next_hop_in_ip_address } resource "azurerm_route" "dev_prod_routes" { for_each = var.developer_prod_routes name = each.value.name resource_group_name = azurerm_resource_group.rg.name route_table_name = azurerm_route_table.dev_prod_rt.name address_prefix = each.value.address_prefix next_hop_type = each.value.next_hop_type next_hop_in_ip_address = each.value.next_hop_in_ip_address } resource "azurerm_route" "front_office_routes" { for_each = var.front_office_routes name = each.value.name resource_group_name = azurerm_resource_group.rg.name route_table_name = azurerm_route_table.front_office_rt.name address_prefix = each.value.address_prefix next_hop_type = each.value.next_hop_type next_hop_in_ip_address = each.value.next_hop_in_ip_address } ########################### # ROUTE TABLE ASSOICATION # ########################### resource "azurerm_subnet_route_table_association" "fslogix_rta" { subnet_id = ??????????????????????????????????????? route_table_id = azurerm_route_table.fslogix_rt.id }
解决方案
当在azurerm_virtual_network资源块内定义子网时,Terraform会自动将这些子网暴露为subnets列表属性,每个元素包含id、name等核心字段,你可以通过以下方式获取子网ID并关联路由表:
1. 单个子网的路由表关联
使用for表达式筛选目标子网,再通过one()函数取出唯一匹配的子网ID(确保子网名称唯一):
resource "azurerm_subnet_route_table_association" "fslogix_rta" { subnet_id = one([for s in azurerm_virtual_network.vnet.subnets : s.id if s.name == var.vnet.subnet1_name]) route_table_id = azurerm_route_table.fslogix_rt.id }
2. 批量关联所有子网(推荐)
如果每个子网都对应一个路由表,可通过定义映射关系+for_each批量创建关联资源,减少重复代码:
# 定义子网名称与对应路由表ID的映射 locals { subnet_rt_mapping = { var.vnet.subnet1_name = azurerm_route_table.fslogix_rt.id var.vnet.subnet2_name = azurerm_route_table.back_office_rt.id var.vnet.subnet3_name = azurerm_route_table.dev_dev_rt.id var.vnet.subnet4_name = azurerm_route_table.dev_prod_rt.id var.vnet.subnet5_name = azurerm_route_table.front_office_rt.id } } # 批量生成路由表关联资源 resource "azurerm_subnet_route_table_association" "all" { for_each = local.subnet_rt_mapping subnet_id = one([for s in azurerm_virtual_network.vnet.subnets : s.id if s.name == each.key]) route_table_id = each.value }
注意事项
- 确保变量中定义的子网名称与虚拟网络内的子网名称完全匹配,否则会出现找不到子网的错误
- 若使用Terraform 0.13以下版本,可替换
one()为element([...], 0),但建议升级到新版本以获得更安全的语法支持
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

