Terraform Azure现有代码新增2个NSG与3个子网配置求助
问题根因
现有代码无法正常新增子网和NSG,核心是3个硬伤:
- 仅定义了1个NSG、2个子网,且所有NSG规则绑定在同一个NSG上,子网、NSG的关联逻辑写死了单资源引用,不支持扩容
- 3台虚拟机的网卡配置为单例资源,多台VM共用1块网卡不符合Azure资源逻辑,且
network_interface_ids字段错误拼接count.index,会触发类型不匹配报错 - 同时在子网级别和网卡级别绑定同一个NSG,很容易出现关联冲突,导致Terraform状态漂移
修改方案
1. 子网规划
现有VNet地址段为10.0.0.0/16,在原有2个网段基础上新增第三个网段,3个子网分别做应用子网、数据库子网、管理子网使用,地址段分配:
- 应用子网:
10.0.1.0/24 - 数据库子网:
10.0.2.0/24 - 管理子网:
10.0.3.0/24
2. NSG拆分
新增第二个独立NSG,把原有混在同一个NSG的规则拆分绑定:
- 应用层NSG:绑定8080入站规则,关联应用子网
- 数据库层NSG:绑定5432入站规则,限制仅应用子网段可访问,关联数据库子网
- 移除网卡层面的NSG关联,统一在子网层面做NSG绑定,避免冲突
3. 资源关联修正
- 用
count生成3块独立网卡,分别绑定到应用子网,替代原有单块网卡的错误配置 - 修正虚拟机资源的网卡ID引用格式
- 补全PostgreSQL柔性服务器必需的子网参数,将数据库服务部署到数据库子网
- 统一公网IP、负载均衡的SKU为Standard,避免Basic SKU资源版本不兼容问题
修正后可直接运行的main.tf代码
resource "random_pet" "rg-name" { prefix = var.resource_group_name_prefix } resource "azurerm_resource_group" "rg" { name = random_pet.rg-name.id location = var.resource_group_location } # 创建虚拟网络 resource "azurerm_virtual_network" "Vnet" { name = "Vnet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name } # 3个子网定义 resource "azurerm_subnet" "app_subnet" { name = "app-subnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.Vnet.name address_prefixes = ["10.0.1.0/24"] } resource "azurerm_subnet" "db_subnet" { name = "db-subnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.Vnet.name address_prefixes = ["10.0.2.0/24"] } resource "azurerm_subnet" "mgmt_subnet" { name = "mgmt-subnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.Vnet.name address_prefixes = ["10.0.3.0/24"] } # 2个独立NSG定义 resource "azurerm_network_security_group" "app_nsg" { name = "app-nsg" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name } resource "azurerm_network_security_group" "db_nsg" { name = "db-nsg" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name } # 应用NSG规则:允许8080端口入站 resource "azurerm_network_security_rule" "app_port_8080" { name = "allow-8080-inbound" priority = 110 direction = "inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "8080" source_address_prefix = "*" destination_address_prefix = "*" resource_group_name = azurerm_resource_group.rg.name network_security_group_name = azurerm_network_security_group.app_nsg.name } # 数据库NSG规则:仅允许应用子网访问5432端口 resource "azurerm_network_security_rule" "db_port_5432" { name = "allow-5432-from-app" priority = 100 direction = "inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "5432" source_address_prefix = azurerm_subnet.app_subnet.address_prefixes[0] destination_address_prefix = "*" resource_group_name = azurerm_resource_group.rg.name network_security_group_name = azurerm_network_security_group.db_nsg.name } # 子网与NSG关联 resource "azurerm_subnet_network_security_group_association" "app_subnet_nsg_bind" { subnet_id = azurerm_subnet.app_subnet.id network_security_group_id = azurerm_network_security_group.app_nsg.id } resource "azurerm_subnet_network_security_group_association" "db_subnet_nsg_bind" { subnet_id = azurerm_subnet.db_subnet.id network_security_group_id = azurerm_network_security_group.db_nsg.id } # 负载均衡公网IP resource "azurerm_public_ip" "lb_pub_ip" { name = "lb-public-ip" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name allocation_method = "Static" sku = "Standard" } # 3台应用VM对应独立网卡 resource "azurerm_network_interface" "app_nic" { count = 3 name = "app-nic-${count.index}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name ip_configuration { name = "app-nic-conf-${count.index}" subnet_id = azurerm_subnet.app_subnet.id private_ip_address_allocation = "Dynamic" } } # 负载均衡 resource "azurerm_lb" "app_lb" { name = "app-loadbalancer" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name sku = "Standard" frontend_ip_configuration { name = "lb-frontend" public_ip_address_id = azurerm_public_ip.lb_pub_ip.id } } # 3台应用虚拟机 resource "azurerm_virtual_machine" "vm_app" { count = 3 name = "app_vm${count.index}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name network_interface_ids = [azurerm_network_interface.app_nic[count.index].id] vm_size = "Standard_B2s" delete_os_disk_on_termination = true delete_data_disks_on_termination = true storage_image_reference { publisher = "Canonical" offer = "0001-com-ubuntu-server-focal" sku = "20_04-lts-gen2" version = "latest" } storage_os_disk { name = "app-os-disk-${count.index}" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = "Standard_LRS" } } # 镜像存储资源组 resource "azurerm_resource_group" "Image_App" { name = "Weight_Tracker_application" location = "EastUS" } # PostgreSQL柔性服务器,部署到数据库子网 resource "azurerm_postgresql_flexible_server" "PS_SQL" { name = "sqlflexserver" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location version = "12" administrator_login = "postgres" administrator_password = "p@ssw0rd42" storage_mb = 32768 sku_name = "GP_Standard_D4s_v3" subnet_id = azurerm_subnet.db_subnet.id } resource "azurerm_postgresql_flexible_server_database" "PS_FLEX" { name = "db-server" server_id = azurerm_postgresql_flexible_server.PS_SQL.id collation = "en_US.utf8" charset = "utf8" }
部署校验要点
- 执行
terraform plan时确认资源变更清单包含3个子网、2个NSG,无资源替换报错 - 数据库NSG默认拒绝公网访问5432端口,如需本地调试可临时加放通规则,上线前务必删除
- 管理子网默认未绑定NSG,可后续按需配置跳板机相关访问规则
内容的提问来源于stack exchange,提问作者Evgeny Dudko
相关产品推荐
相关产品推荐

