You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨VNET/环境安全访问Azure Container App的最优Terraform配置问询

问题概述

我是Azure网络新手,在不同资源组、VNET中部署了两个Azure Container App(A和B),希望通过VNET/子网对等连接,用静态自定义名称实现二者安全互访。

当前问题1:自定义CNAME访问失败

完成VNET对等后,通过Terraform配置私有DNS区域,以B的最新修订版FQDN创建CNAME记录。使用FQDN可正常互访,但通过自定义CNAME(如myAppA.internal)访问时,虽nslookup解析正确,但curl请求失败,提示This Container App is stopped or does not exist.。相关Terraform代码如下:

resource "azurerm_subnet" "containerEnv" {
  name                 = "${var.name}-containerEnv"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes = ["10.0.2.0/23"]
  service_endpoints = ["Microsoft.Storage"]
}

resource "azurerm_virtual_network" "main" {
  name                = "${var.name}-vnet"
  location            = var.location
  resource_group_name = var.resource_group_name
  address_space = ["10.0.0.0/16"]
}

resource "azurerm_container_app_environment" "main" {
  name                       = var.name
  location                   = var.location
  resource_group_name        = var.resource_group_name
  log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
  infrastructure_subnet_id   = azurerm_subnet.containerEnv.id
}

resource "azurerm_private_dns_zone" "main" {
  name                = "${var.name}.internal"
  resource_group_name = var.resource_group_name
}

resource "azurerm_private_dns_zone_virtual_network_link" "main" {
  name                  = "${var.name}-link"
  private_dns_zone_name = azurerm_private_dns_zone.main.name
  resource_group_name   = var.resource_group_name
  virtual_network_id    = azurerm_virtual_network.main.id
}

resource "azurerm_private_dns_zone_virtual_network_link" "networkB" {
  for_each = var.remote_virtual_network_ids

  name                  = "${var.name}-B-link"
  private_dns_zone_name = azurerm_private_dns_zone.main.name
  resource_group_name   = var.resource_group_name
  virtual_network_id    = each.value
}

resource "azurerm_private_dns_cname_record" "appA" {
  name                = local.name
  record              = azurerm_container_app.main.latest_revision_fqdn
  resource_group_name = var.resource_group_name
  ttl                 = 300
  zone_name           = var.dns_zone_name
}

resource "azurerm_virtual_network_peering" "B" {
  for_each = var.remote_virtual_network_ids

  name                      = "peer-to-remote-B"
  remote_virtual_network_id = each.value
  resource_group_name       = var.resource_group_name
  virtual_network_name      = azurerm_virtual_network.main.name

  # TODO Seems to have implications public DNS entries, shelved for now.
  # peer_complete_virtual_networks_enabled = false
  # local_subnet_names = [azurerm_subnet.containerEnv.name]
  # remote_subnet_names                    = var.remote_subnet_names

  lifecycle {
    replace_triggered_by = [azurerm_virtual_network.main]
  }
}

当前问题2:访问控制依赖动态出站IP

目前通过将A的环境出站IP加入B的入站IP白名单实现访问,但该IP可能变更,且无法使用子网连接范围配置。相关Terraform代码如下:

resource "azurerm_container_app" "A" {
  name                         = local.name
  container_app_environment_id = var.container_app_environment_id
  resource_group_name          = var.resource_group_name
  revision_mode                = "Single"
  (...)

  ingress {
    external_enabled           = true
    allow_insecure_connections = false
    target_port                = 1234

    traffic_weight {
      percentage      = 100
      latest_revision = true
    }

    dynamic "ip_security_restriction" {
      for_each = var.allowed_ip_ranges
      content {
        ip_address_range = ip_security_restriction.value
        action           = "Allow"
        name             = "A"
      }
    }

  }

  template {
    min_replicas = 1
    max_replicas = 1

    container {
      name   = local.A
      image  = "registry"
      cpu    = "0.5"
      memory = "1Gi"

    }
  }
}

现寻求:

  • 无需非静态IP白名单的跨子网/VNET安全通信方案
  • 基于Terraform自动化的简洁易懂的双向互访最优配置方案

解决方案

一、自定义CNAME访问失败的修复

Azure Container App的Ingress会验证请求的Host头,只有匹配其自身FQDN的请求才会被正确路由。直接用CNAME指向修订版FQDN时,请求的Host头是自定义域名(如myAppA.internal),不匹配容器应用的默认FQDN,导致路由失败。

修复步骤(Terraform配置)

  1. 为容器应用配置自定义域名绑定,将自定义域名关联到容器应用:
resource "azurerm_container_app_custom_hostname_binding" "appA" {
  name                = local.name
  container_app_id    = azurerm_container_app.main.id
  hostname            = "${local.name}.${var.dns_zone_name}" # 对应myAppA.internal
  ssl_state           = "Disabled" # 内部访问可禁用SSL,需加密可配置私有证书
}
  1. 保留原有的私有DNS CNAME记录,确保解析正确。

配置完成后,请求的Host头会匹配绑定的自定义域名,Ingress即可正确路由到容器应用。

二、跨VNET安全通信(无需静态IP白名单)

利用VNET对等连接的子网信任关系,直接在容器应用的Ingress安全规则中允许对方VNET的子网CIDR,替代动态出站IP白名单。

核心配置要点

  1. 确保VNET对等连接双向配置完成(双方都创建对等链接,且启用allow_virtual_network_access)
  2. 在容器应用的Ingress中,添加对方VNET的子网CIDR到IP安全规则

Terraform双向互访配置示例

容器应用A的Ingress安全规则(允许B的VNET子网)

resource "azurerm_container_app" "A" {
  # 原有配置...
  ingress {
    external_enabled           = true
    allow_insecure_connections = false
    target_port                = 1234

    traffic_weight {
      percentage      = 100
      latest_revision = true
    }

    # 允许自身VNET子网
    ip_security_restriction {
      ip_address_range = azurerm_virtual_network.main.address_space[0] # 10.0.0.0/16
      action           = "Allow"
      name             = "Self-VNET"
    }

    # 允许B的VNET子网
    dynamic "ip_security_restriction" {
      for_each = var.remote_vnet_subnet_cidrs
      content {
        ip_address_range = ip_security_restriction.value
        action           = "Allow"
        name             = "Remote-VNET-B"
      }
    }
  }
  # 原有配置...
}

容器应用B的Ingress安全规则(允许A的VNET子网)

同理,在B的Terraform配置中添加A的VNET子网CIDR到IP安全规则即可。

完善VNET对等连接配置

确保对等连接启用必要的访问权限:

resource "azurerm_virtual_network_peering" "to_B" {
  for_each = var.remote_virtual_network_ids

  name                      = "peer-to-${each.key}"
  remote_virtual_network_id = each.value
  resource_group_name       = var.resource_group_name
  virtual_network_name      = azurerm_virtual_network.main.name

  allow_virtual_network_access = true
  allow_forwarded_traffic     = true
  allow_gateway_transit       = false
  use_remote_gateways         = false

  lifecycle {
    replace_triggered_by = [azurerm_virtual_network.main]
  }
}

注意:需在B的资源组中创建反向的VNET对等链接,配置相同的allow_virtual_network_access参数。

三、完整双向互访Terraform配置简化建议

  1. 用变量统一管理双方VNET的ID和子网CIDR,避免硬编码
  2. 为双方容器应用分别配置自定义域名绑定和私有DNS记录
  3. 双向VNET对等连接+子网级IP安全规则,确保通信安全

内容的提问来源于stack exchange,提问作者honest_annie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:52:32