如何通过Terraform为虚拟网络中的Azure容器组配置公网IP访问?
问题解答与Terraform示例
核心结论
不能直接给部署在虚拟网络中的Azure容器组(ACI)绑定azurerm_public_ip——只有未加入VNet的ACI才支持直接分配公网IP。VNet内的ACI只能通过中转组件实现公网访问,最轻量化的方案是用Azure基础负载均衡器(Basic LB)的NAT规则做端口映射,而非直接关联公网IP。
思路误区纠正
- 错误认知:VNet内的ACI可以直接绑定公网IP
- 实际Azure设计中,VNet部署的ACI属于私有网络资源,仅分配私有IP,不支持直接挂载公网IP。
- 过度复杂化:优先考虑应用网关而非基础LB
- 单ACI的公网访问场景,基础LB的NAT规则足够满足需求,成本远低于应用网关,无需过度设计。
- 忽略LB依赖配置:以为只需要NAT规则就能转发流量
- LB必须将ACI加入后端池,同时配置健康探针(哪怕是简单的TCP探针),否则流量无法正常转发。
Terraform示例代码
以下代码实现:创建VNet/子网 → 部署带私有IP的ACI → 创建基础LB+公网IP → 配置NAT规则将公网IP的80端口映射到ACI的80端口
# 配置Azure Provider terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 3.0" } } } provider "azurerm" { features {} } # 1. 创建资源组 resource "azurerm_resource_group" "example" { name = "aci-public-access-rg" location = "East Asia" } # 2. 创建虚拟网络和子网(ACI必须部署到支持ACI的子网,不能有其他资源) resource "azurerm_virtual_network" "example" { name = "aci-vnet" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name } resource "azurerm_subnet" "aci_subnet" { name = "aci-subnet" resource_group_name = azurerm_resource_group.example.name virtual_network_name = azurerm_virtual_network.example.name address_prefixes = ["10.0.1.0/24"] # 子网必须启用ACI服务端点 service_endpoints = ["Microsoft.ContainerInstance"] } # 3. 创建部署在VNet内的ACI(仅私有IP) resource "azurerm_container_group" "example" { name = "aci-private" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name ip_address_type = "Private" subnet_id = azurerm_subnet.aci_subnet.id os_type = "Linux" container { name = "nginx" image = "nginx:latest" cpu = "1" memory = "1.0" ports { port = 80 protocol = "TCP" } } } # 4. 创建公网IP(用于LB) resource "azurerm_public_ip" "lb_public_ip" { name = "lb-public-ip" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name allocation_method = "Static" sku = "Basic" } # 5. 创建基础负载均衡器 resource "azurerm_lb" "example" { name = "aci-lb" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name frontend_ip_configuration { name = "public-ip-config" public_ip_address_id = azurerm_public_ip.lb_public_ip.id } } # 6. 创建LB后端池(关联ACI的私有IP) resource "azurerm_lb_backend_address_pool" "example" { name = "aci-backend-pool" loadbalancer_id = azurerm_lb.example.id } # 7. 将ACI的私有IP加入后端池 resource "azurerm_lb_backend_address_pool_address" "aci_address" { backend_address_pool_id = azurerm_lb_backend_address_pool.example.id ip_address = azurerm_container_group.example.ip_address } # 8. 创建健康探针(TCP 80端口) resource "azurerm_lb_probe" "example" { name = "tcp-probe" loadbalancer_id = azurerm_lb.example.id protocol = "Tcp" port = 80 interval_in_seconds = 10 number_of_probes = 3 } # 9. 创建NAT规则:公网IP 80端口 → ACI 80端口 resource "azurerm_lb_nat_rule" "example" { name = "aci-nat-rule" loadbalancer_id = azurerm_lb.example.id frontend_ip_configuration_name = "public-ip-config" protocol = "Tcp" frontend_port = 80 backend_port = 80 backend_address_pool_id = azurerm_lb_backend_address_pool.example.id probe_id = azurerm_lb_probe.example.id }
验证步骤
部署完成后,通过azurerm_public_ip.lb_public_ip.ip_address获取公网IP,在浏览器访问该IP即可看到Nginx默认页面。
内容的提问来源于stack exchange,提问作者Kafkaese
相关产品推荐
相关产品推荐

