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

Azure容器实例通过私有端点连接Azure SQL数据库超时排查

ACI通过私有端点连接Azure SQL超时问题排查

问题描述

使用Terraform部署的Azure容器实例(ACI)尝试通过私有端点连接Azure SQL数据库时出现超时,所有资源配置如下:

数据库配置

resource "azurerm_sql_server" "azure_sql_server" {
  name                         = "azure-sql-server"
  resource_group_name          = data.azurerm_resource_group.arc_resource_group.name
  location                      = data.azurerm_resource_group.arc_resource_group.location
  administrator_login          = var.administrator_login
  administrator_login_password = var.administrator_login_password
  version                       = "12.0"
}

resource "azurerm_sql_database" "azure_sql_database" {
  name                = "database"
  server_name         = azurerm_sql_server.arc_azure_sql_server.name
  resource_group_name = data.azurerm_resource_group.arc_resource_group.name
  location            = data.azurerm_resource_group.arc_resource_group.location
}

容器实例配置

resource "azurerm_container_group" "nginx_container" {
  name                = "nginx-container-group"
  resource_group_name = data.azurerm_resource_group.arc_resource_group.name
  location            = data.azurerm_resource_group.arc_resource_group.location
  ip_address_type     = "Private"
  os_type             = "Linux"
  subnet_ids          = [azurerm_subnet.subnet_b.id]

  container {
    name   = "nginx-container"
    image  = "${var.acr_repository}.azurecr.io/docker_image:latest"
    cpu    = "0.5"
    memory = "1.5"

    environment_variables = {
        "DB_HOST" = format("%s.database.windows.net", azurerm_sql_server.arc_azure_sql_server.name)
    }
    
    ports {
      port     = 80
      protocol = "TCP"
    }
  }
}

虚拟网络配置

data "azurerm_virtual_network" "existing_vnet" {
  name                = "vnet-uks-dev"
  resource_group_name = data.azurerm_resource_group.arc_resource_group.name
}

resource "azurerm_subnet" "subnet_a" {
  name                 = "sql-sn"
  resource_group_name  = data.azurerm_resource_group.arc_resource_group.name
  virtual_network_name = data.azurerm_virtual_network.existing_vnet.name
  address_prefixes     = ["10.2.1.0/24"]
}

resource "azurerm_subnet" "subnet_b" {
  name                 = "aci-sn"
  resource_group_name  = data.azurerm_resource_group.arc_resource_group.name
  virtual_network_name = data.azurerm_virtual_network.existing_vnet.name
  address_prefixes     = ["10.2.2.0/24"]
  service_endpoints    = ["Microsoft.Sql"]
  delegation {
    name = "aci"
    service_delegation {
      name    = "Microsoft.ContainerInstance/containerGroups"
      actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
    }
  }
}

resource "azurerm_subnet" "subnet_c" {
  name                 = "private-link-sn"
  resource_group_name  = data.azurerm_resource_group.arc_resource_group.name
  virtual_network_name = data.azurerm_virtual_network.existing_vnet.name
  address_prefixes     = ["10.2.3.0/24"]
}

DNS与私有端点配置

resource "azurerm_private_dns_zone" "sql_private_dns_zone" {
  name                = "privatelink.database.windows.net"
  resource_group_name = data.azurerm_resource_group.arc_resource_group.name
}

resource "azurerm_private_dns_zone_virtual_network_link" "vnet_link" {
  name                  = "vnet-link-to-private-dns"
  resource_group_name   = data.azurerm_resource_group.arc_resource_group.name
  private_dns_zone_name = azurerm_private_dns_zone.sql_private_dns_zone.name
  virtual_network_id    = data.azurerm_virtual_network.existing_vnet.id
}

resource "azurerm_sql_virtual_network_rule" "allow_aci_subnet" {
  name                = "AllowACISubnet"
  resource_group_name = data.azurerm_resource_group.arc_resource_group.name
  server_name         = azurerm_sql_server.arc_azure_sql_server.name
  subnet_id           = azurerm_subnet.subnet_b.id
}

resource "azurerm_private_endpoint" "database_private_endpoint" {
  name                = "pe-database"
  location            = data.azurerm_resource_group.arc_resource_group.location
  resource_group_name = data.azurerm_resource_group.arc_resource_group.name
  subnet_id           = azurerm_subnet.subnet_c.id

  private_service_connection {
    name                           = "psc-sql"
    private_connection_resource_id = azurerm_sql_server.arc_azure_sql_server.id
    subresource_names             = ["sqlServer"]
  }

  private_dns_zone_group {
    name                 = "default"
    private_dns_zone_ids = [azurerm_private_dns_zone.sql_private_dns_zone.id]
  }
}

注:已配置3个专用子网,私有端点和容器实例分别使用独立子网;确认数据库连接字符串正确,SQL服务器域名为azure-sql-server.database.windows.net。

可能的原因

  • SQL服务器公共网络访问未禁用:若SQL服务器仍允许公网访问,DNS解析可能优先指向公网IP,但ACI在私有子网无法访问公网,导致超时;同时私有端点的DNS解析规则可能未生效。
  • ACI子网服务端点与私有端点冲突:ACI所在的subnet_b配置了Microsoft.Sql服务端点,会强制SQL流量走服务端点而非私有端点,两者路由逻辑冲突。
  • 私有端点子网网络策略限制:私有端点所在的subnet_c默认可能启用了NSG或路由表策略,阻止了ACI到私有端点的流量。
  • DNS解析未验证:虽配置了私有DNS区域和VNet链接,但ACI内部可能未正确将SQL域名解析到私有端点的私有IP。
  • 冗余的虚拟网络规则:使用私有端点时,azurerm_sql_virtual_network_rule属于冗余配置,可能干扰流量路由。

解决步骤

1. 禁用SQL服务器公共网络访问

修改azurerm_sql_server资源,强制所有流量走私有端点:

resource "azurerm_sql_server" "azure_sql_server" {
  name                         = "azure-sql-server"
  resource_group_name          = data.azurerm_resource_group.arc_resource_group.name
  location                      = data.azurerm_resource_group.arc_resource_group.location
  administrator_login          = var.administrator_login
  administrator_login_password = var.administrator_login_password
  version                       = "12.0"
  public_network_access_enabled = false # 新增:禁用公网访问
}

2. 移除ACI子网的SQL服务端点

删除subnet_b中的service_endpoints配置,消除与私有端点的冲突:

resource "azurerm_subnet" "subnet_b" {
  name                 = "aci-sn"
  resource_group_name  = data.azurerm_resource_group.arc_resource_group.name
  virtual_network_name = data.azurerm_virtual_network.existing_vnet.name
  address_prefixes     = ["10.2.2.0/24"]
  # 移除service_endpoints = ["Microsoft.Sql"]
  delegation {
    name = "aci"
    service_delegation {
      name    = "Microsoft.ContainerInstance/containerGroups"
      actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
    }
  }
}

3. 禁用私有端点子网的网络策略

修改subnet_c,确保私有端点流量不受NSG和路由表限制:

resource "azurerm_subnet" "subnet_c" {
  name                 = "private-link-sn"
  resource_group_name  = data.azurerm_resource_group.arc_resource_group.name
  virtual_network_name = data.azurerm_virtual_network.existing_vnet.name
  address_prefixes     = ["10.2.3.0/24"]
  private_endpoint_network_policies_enabled = false # 新增:禁用私有端点子网网络策略
}

4. 验证DNS解析

进入ACI容器执行以下命令,确认解析结果为私有端点的私有IP(10.2.3.x段):

nslookup azure-sql-server.database.windows.net

若解析失败,检查私有DNS区域与VNet的链接是否生效,确保自动关联的DNS记录已生成。

5. 移除冗余的SQL虚拟网络规则

使用私有端点时无需配置虚拟网络规则,直接删除该资源:

# 删除以下资源
# resource "azurerm_sql_virtual_network_rule" "allow_aci_subnet" {
#   name                = "AllowACISubnet"
#   resource_group_name = data.azurerm_resource_group.arc_resource_group.name
#   server_name         = azurerm_sql_server.arc_azure_sql_server.name
#   subnet_id           = azurerm_subnet.subnet_b.id
# }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:44:52