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

Azure App Service配置私有端点与NAT网关实现静态出站IP

问题描述

我正在开发一个个人项目,包含2个以Linux Web App托管的ASP.NET Core Web API,近期计划新增一个React前端作为另一Linux Web App。基础设施设计涉及为后端Web App配置Application Insights、使用Azure Key Vault,并集成共享SQL数据库。我希望将资源部署在私有网络中(不暴露于公网),同时为其中一个需对接第三方API的API配置NAT网关以提供静态出站IP,该第三方API要求将特定静态出站IP加入白名单。

我了解到多种使用私有端点、网络安全组管理流量及用户定义路由引导流量的方案,但不确定这些方法能否与我的NAT网关实现(尤其是静态出站IP部分)连贯整合。

基于此,我有以下技术问题寻求指导:

  1. 如何将Application Insights、Key Vault及SQL数据库的私有端点与现有NAT网关实现的静态出站IP方案整合?具体实现方式是什么?
  2. 结合当前需求,现有Terraform代码中还缺少哪些可提升资源安全性或功能性的配置?

现有Terraform代码

resource "azurerm_resource_group" "rg" {
  name     = "${local.basename}-rg"
  location = "East US"
}

resource "azurerm_service_plan" "asp" {
  name                = "${local.basename}-asp"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  os_type             = "Linux"
  sku_name            = "S1"
}

resource "azurerm_linux_web_app" "app" {
  name                = "${local.basename}-app"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  service_plan_id     = azurerm_service_plan.asp.id

  site_config {
    vnet_route_all_enabled = true # WEBSITE_VNET_ROUTE_ALL
  }

  identity {
    type = "SystemAssigned"
  }
}

resource "azurerm_virtual_network" "vnet" {
  name                = "${local.basename}-vnet"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  address_space       = ["10.0.0.0/16"]
}

resource "azurerm_subnet" "snet" {
  name                 = "${local.basename}-linuxapp-snet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]

  delegation {
    name = "delegation"

    service_delegation {
      name    = "Microsoft.Web/serverFarms"
      actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
    }
  }
}

resource "azurerm_subnet_nat_gateway_association" "example" {
  subnet_id      = azurerm_subnet.snet.id
  nat_gateway_id = azurerm_nat_gateway.ng.id
}

resource "azurerm_public_ip" "pip" {
  name                = "${local.basename}-pip"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  allocation_method   = "Static"
  sku                 = "Standard"
  zones               = ["1"]
}

resource "azurerm_nat_gateway" "ng" {
  name                    = "${local.basename}-ng"
  resource_group_name     = azurerm_resource_group.rg.name
  location                = azurerm_resource_group.rg.location
  sku_name                = "Standard"
  idle_timeout_in_minutes = 10
  zones                   = ["1"]
}

resource "azurerm_nat_gateway_public_ip_association" "association" {
  nat_gateway_id       = azurerm_nat_gateway.ng.id
  public_ip_address_id = azurerm_public_ip.pip.id
}

resource "azurerm_app_service_virtual_network_swift_connection" "example" {
  app_service_id = azurerm_linux_web_app.app.id
  subnet_id      = azurerm_subnet.snet.id
}
解决方案

问题1:私有端点与NAT网关静态出站IP的整合实现

核心逻辑

私有端点让Web App通过VNet内网访问Azure PaaS服务(App Insights、Key Vault、SQL),NAT网关仅负责第三方API的出站流量,两者通过用户定义路由(UDR)区分流量走向,避免冲突。

具体实现步骤

  1. 创建专用子网用于私有端点
    为PaaS服务的私有端点创建独立子网,需禁用私有端点网络策略,避免与Web App子网的NAT规则冲突:

    resource "azurerm_subnet" "private_endpoints" {
      name                 = "${local.basename}-pe-snet"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.vnet.name
      address_prefixes     = ["10.0.2.0/24"]
      private_endpoint_network_policies = "Disabled"
    }
    
  2. 为各PaaS服务创建私有端点

    • SQL数据库私有端点:关联SQL服务器,配置内网访问通道
    resource "azurerm_private_endpoint" "sql" {
      name                = "${local.basename}-sql-pe"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      subnet_id           = azurerm_subnet.private_endpoints.id
    
      private_service_connection {
        name                           = "${local.basename}-sql-psc"
        private_connection_resource_id = azurerm_mssql_server.sql.id
        subresource_names              = ["sqlServer"]
        is_manual_connection           = false
      }
    }
    
    • Key Vault私有端点:关联Key Vault,支持Web App系统身份访问
    resource "azurerm_private_endpoint" "kv" {
      name                = "${local.basename}-kv-pe"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      subnet_id           = azurerm_subnet.private_endpoints.id
    
      private_service_connection {
        name                           = "${local.basename}-kv-psc"
        private_connection_resource_id = azurerm_key_vault.kv.id
        subresource_names              = ["vault"]
        is_manual_connection           = false
      }
    }
    
    • Application Insights私有端点:需同时关联API和 ingestion 子资源,确保遥测数据内网传输
    resource "azurerm_private_endpoint" "app_insights" {
      name                = "${local.basename}-ai-pe"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      subnet_id           = azurerm_subnet.private_endpoints.id
    
      private_service_connection {
        name                           = "${local.basename}-ai-psc"
        private_connection_resource_id = azurerm_application_insights.ai.id
        subresource_names              = ["api", "ingestion"]
        is_manual_connection           = false
      }
    }
    
  3. 配置用户定义路由(UDR)区分流量
    在Web App子网关联UDR,分别定义两类流量的走向:

    • 访问Azure PaaS服务的流量:引导至VNet内网,走私有端点
    • 访问第三方API的流量:引导至NAT网关,使用静态公网IP出站
    resource "azurerm_route_table" "web_app_udr" {
      name                = "${local.basename}-web-udr"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      disable_bgp_route_propagation = true
    }
    
    # 路由到私有端子网内的PaaS服务
    resource "azurerm_route" "paas_private" {
      name                = "${local.basename}-paas-route"
      resource_group_name = azurerm_resource_group.rg.name
      route_table_name    = azurerm_route_table.web_app_udr.name
      address_prefix      = "10.0.2.0/24"
      next_hop_type       = "VnetLocal"
    }
    
    # 路由到第三方API,走NAT网关
    resource "azurerm_route" "third_party_api" {
      name                = "${local.basename}-third-party-route"
      resource_group_name = azurerm_resource_group.rg.name
      route_table_name    = azurerm_route_table.web_app_udr.name
      address_prefix      = "x.x.x.x/32" # 替换为第三方API公网IP
      next_hop_type       = "NatGateway"
      next_hop_in_ip_address = azurerm_nat_gateway.ng.id
    }
    
    # 关联UDR到Web App子网
    resource "azurerm_subnet_route_table_association" "web_snet_udr" {
      subnet_id      = azurerm_subnet.snet.id
      route_table_id = azurerm_route_table.web_app_udr.id
    }
    
  4. 流量验证

    • Web App访问SQL/Key Vault/App Insights时,通过私有端点走内网,不经过NAT网关
    • 访问第三方API时,流量通过UDR引导到NAT网关,使用指定的静态公网IP出站

问题2:现有Terraform代码缺失的安全/功能性配置

安全类配置

  1. 网络安全组(NSG)限制子网流量
    为Web App子网和私有端子网添加NSG,仅允许必要的入站/出站流量:

    resource "azurerm_network_security_group" "web_snet_nsg" {
      name                = "${local.basename}-web-nsg"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
    
      security_rule {
        name                       = "AllowVnetInbound"
        priority                   = 100
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "80,443"
        source_address_prefix      = "10.0.0.0/16"
        destination_address_prefix = "*"
      }
    
      security_rule {
        name                       = "AllowThirdPartyOutbound"
        priority                   = 100
        direction                  = "Outbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "*"
        source_address_prefix      = "*"
        destination_address_prefix = "x.x.x.x/32" # 第三方API IP
      }
    }
    
    # 关联NSG到Web App子网
    resource "azurerm_subnet_network_security_group_association" "web_snet_nsg" {
      subnet_id                 = azurerm_subnet.snet.id
      network_security_group_id = azurerm_network_security_group.web_snet_nsg.id
    }
    
  2. 禁用Web App公网访问
    确保Web App仅通过VNet内网访问,不暴露公网:

    resource "azurerm_linux_web_app" "app" {
      # 保留现有配置
      public_network_access_enabled = false
    }
    
  3. Key Vault访问策略
    为Web App的系统身份分配Key Vault的最小权限,避免硬编码密钥:

    resource "azurerm_key_vault_access_policy" "web_app" {
      key_vault_id = azurerm_key_vault.kv.id
      tenant_id    = data.azurerm_client_config.current.tenant_id
      object_id    = azurerm_linux_web_app.app.identity[0].principal_id
    
      key_permissions = ["Get", "List"]
      secret_permissions = ["Get", "List"]
      certificate_permissions = ["Get", "List"]
    }
    
  4. 禁用SQL公网访问
    仅允许私有端点和VNet内流量访问SQL数据库:

    resource "azurerm_mssql_server" "sql" {
      # 保留现有配置
      public_network_access_enabled = false
      private_endpoint_connections {
        id = azurerm_private_endpoint.sql.id
      }
    }
    

功能性配置

  1. 多Web App资源定义
    现有代码仅定义了一个Web App,需添加第二个API和React前端的Web App资源,关联到服务计划并加入VNet。

  2. Application Insights集成
    为Web App配置App Insights扩展,启用遥测收集:

    resource "azurerm_application_insights" "ai" {
      name                = "${local.basename}-ai"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      application_type    = "web"
    }
    
    resource "azurerm_linux_web_app" "app" {
      # 保留现有配置
      app_settings = {
        APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.ai.connection_string
      }
    }
    
  3. 本地变量定义
    补充local.basename的定义:

    locals {
      basename = "your-project-prefix"
    }
    
  4. 区域冗余配置(可选)
    若需更高可用性,可将NAT网关和公网IP配置为多区域:

    resource "azurerm_public_ip" "pip" {
      # 保留现有配置
      zones = ["1", "2", "3"]
    }
    
    resource "azurerm_nat_gateway" "ng" {
      # 保留现有配置
      zones = ["1", "2", "3"]
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:54:57