排查 Azure DocumentDB 迁移连接问题

这些故障排除步骤适用于使用 Azure DocumentDB 迁移扩展或Azure门户中Azure 数据库迁移服务体验创建的基于Azure 数据库迁移服务的迁移。

Azure 数据库迁移服务(DMS)运行迁移,并管理源环境和 Azure Cosmos DB 之间的网络连接。 迁移作业失败时,请使用以下步骤跟踪网络连接中断的位置。 对于私有迁移,DMS 将为每个迁移作业创建专用临时虚拟网络,并在作业完成或失败时清除。 之后无法检查 DMS 虚拟网络,因此可以重现其网络位置来隔离故障。

验证先决条件

工具 Purpose
Azure CLI (az) 查询Azure网络资源
PowerShell 或 Bash 运行验证脚本
nc (netcat) 或 Test-NetConnection 测试 TCP 连接
网络参与者或读者 RBAC 角色 在相关虚拟网络上读取访问权限

公共连接验证

在公共模式下,DMS 使用迁移向导显示的静态 IP 通过公共 Internet 连接到源和目标。

验证源防火墙

查看源 MongoDB 防火墙配置,并确认它是否允许迁移向导中显示的每个 DMS 静态 IP 地址。

以下命令用于测试是否可从您的计算机访问该源终结点。 它们不会验证源防火墙是否允许 DMS 静态 IP 地址,因为连接源自计算机的出口地址。

# PowerShell
Test-NetConnection -ComputerName <SOURCE_PUBLIC_IP_OR_HOSTNAME> -Port 27017
# Bash / Linux
nc -zv <SOURCE_PUBLIC_IP_OR_HOSTNAME> 27017

预期:TcpTestSucceeded : True 或 Connection succeeded。

验证目标防火墙

列出 Azure DocumentDB 防火墙规则,并确认它们是否允许迁移向导中显示的每个 DMS 静态 IP 地址:

az documentdb mongocluster firewall-rule list \
  --cluster-name "<CLUSTER_NAME>" \
  --resource-group "<RESOURCE_GROUP>" \
  --output table

以下命令测试是否可以从您的计算机连通目标终结点。 它不会验证来自 DMS 静态 IP 地址的连通性。

Test-NetConnection -ComputerName <DOCUMENTDB_HOSTNAME> -Port 10260

验证 DNS 解析

Resolve-DnsName <SOURCE_HOSTNAME>
Resolve-DnsName <DOCUMENTDB_HOSTNAME>

验证这两个主机名是否解析为 公共 IP。 私有 IP 响应表明存在私有 DNS 覆盖。

公共连接清单

# 检查 命令 预期
1 源防火墙允许 DMS IP 查看源防火墙配置 每个 DMS IP 都位于允许列表中
2 目标防火墙允许 DMS IP 地址 az documentdb mongocluster firewall-rule list 每个 DMS IP 都位于允许列表中
3 DNS 解析到公网 IP 地址 Resolve-DnsName <hostname> 返回的公网 IP
4 可从您的计算机访问该源 Test-NetConnection <source> -Port 27017 成功
5 可从您的计算机连接到目标 Test-NetConnection <target> -Port 10260 成功

专用连接验证

专用连接验证有四个阶段:验证基础结构、生成模拟环境、测试模拟的连接以及清理。

阶段 1:验证基础结构

Azure中的源

验证源终结点和目标专用终结点:

# Check source private endpoints
az network private-endpoint list \
  --subscription "<SUBSCRIPTION>" -g "<SOURCE_RG>" \
  --query "[].{Name:name,Subnet:subnet.id,Status:privateLinkServiceConnections[0].privateLinkServiceConnectionState.status}" \
  -o table

# Check target private endpoints
az network private-endpoint list \
  --subscription "<SUBSCRIPTION>" -g "<TARGET_RG>" \
  --query "[].{Name:name,Subnet:subnet.id,Status:privateLinkServiceConnections[0].privateLinkServiceConnectionState.status}" \
  -o table

预期: 两者的状态均 = Approved。

检查虚拟网络与 DMS CIDR 之间的 CIDR 重叠情况:

echo "=== Source VNet ==="
az network vnet show --subscription "<SUB>" -g "<SOURCE_RG>" -n "<SOURCE_VNET>" \
  --query "addressSpace.addressPrefixes" -o tsv

echo "=== Target VNet ==="
az network vnet show --subscription "<SUB>" -g "<TARGET_RG>" -n "<TARGET_VNET>" \
  --query "addressSpace.addressPrefixes" -o tsv

预期: 在向导中选择的 DMS CIDR 不得与任一虚拟网络重叠。

标识与每个源和目标子网关联的 NSG:

az network vnet subnet show \
  --subscription "<SUB>" -g "<SOURCE_RG>" \
  --vnet-name "<SOURCE_VNET>" -n "<SOURCE_SUBNET>" \
  --query "networkSecurityGroup.id" -o tsv

az network vnet subnet show \
  --subscription "<SUB>" -g "<TARGET_RG>" \
  --vnet-name "<TARGET_VNET>" -n "<TARGET_SUBNET>" \
  --query "networkSecurityGroup.id" -o tsv

列出两个资源组中的 NSG,并检查上述命令返回的 NSG 的规则:

az network nsg list \
  --subscription "<SUB>" -g "<SOURCE_RG>" \
  --query "[].{Name:name,Rules:securityRules[?direction=='Inbound'].{Rule:name,Priority:priority,Access:access,Source:sourceAddressPrefix,Port:destinationPortRange}}" \
  -o json

az network nsg list \
  --subscription "<SUB>" -g "<TARGET_RG>" \
  --query "[].{Name:name,Rules:securityRules[?direction=='Inbound'].{Rule:name,Priority:priority,Access:access,Source:sourceAddressPrefix,Port:destinationPortRange}}" \
  -o json

验证: 没有 Deny 规则阻止 MongoDB 端口(默认 27017)或 DocumentDB 端口(默认为 10260)上的 DMS 虚拟网络 CIDR。

验证专用 DNS 区域配置:

# Check private DNS zones
az network private-dns zone list \
  --subscription "<SUB>" \
  --query "[?contains(name,'mongo') || contains(name,'cosmos') || contains(name,'documentdb')].{Zone:name,RecordSets:numberOfRecordSets}" \
  -o table

# Verify DNS zone is linked to relevant VNets
az network private-dns link vnet list \
  --subscription "<SUB>" -g "<DNS_ZONE_RG>" -z "<ZONE_NAME>" \
  --query "[].{Link:name,VNet:virtualNetwork.id,AutoReg:registrationEnabled}" \
  -o table

Azure 到 Azure 清单:

# 检查 预期
1 源专用终结点状态 Approved
2 目标专用终结点状态 Approved
3 虚拟网络与 DMS CIDR 之间没有 CIDR 重叠 不同的地址范围
4 NSG 允许在所需端口上使用 DMS CIDR 无阻止 Deny 规则
5 链接到你的虚拟网络的专用 DNS 区域 区域已关联,记录可解析

本地或其他云的源

验证 VPN/ExpressRoute 隧道:

# For VPN Gateway
az network vpn-connection list \
  --subscription "<SUB>" -g "<GATEWAY_RG>" \
  --query "[].{Name:name,Status:connectionStatus,IngressBytes:ingressBytesTransferred,EgressBytes:egressBytesTransferred}" \
  -o table

预期:connectionStatus = Connected,字节数随时间增加。

# For ExpressRoute
az network express-route show \
  --subscription "<SUB>" -g "<GATEWAY_RG>" -n "<ER_CIRCUIT_NAME>" \
  --query "{Name:name,State:serviceProviderProvisioningState,PeeringState:peerings[0].state}" \
  -o table

必须将 DMS 虚拟网络 CIDR 通告到远程网络,并验证 BGP 路由通告:

az network vnet-gateway list-advertised-routes \
  --subscription "<SUB>" -g "<GATEWAY_RG>" -n "<VPN_GATEWAY_NAME>" \
  --peer <REMOTE_BGP_PEER_IP> -o table

验证 DMS 虚拟网络 CIDR 是否显示在输出中。 如果未设置,请在网关虚拟网络对等互连中设置 allowGatewayTransit=true。

根据拓扑验证路由:

  • 单个虚拟网络(无中心辐射): 在虚拟网络对等互连上验证 allowGatewayTransit=true 。
  • 中心直接: 与单个虚拟网络相同,但检查中心虚拟网络对等互连。
  • TCP 代理:如果 DMS 只能与某个辐射网络建立对等互连,且无法直接与中心网络建立对等互连,请在与 DMS 对等互连的虚拟网络中部署 MongoDB 迁移代理 虚拟机。 代理通过现有的 VPN/ExpressRoute 路径将来自 DMS 的流量转发到源 MongoDB 服务器。 将 DMS 迁移作业配置为使用代理 VM 的私有 IP 和监听端口作为源端点。
# Check VNet peering configuration
az network vnet peering list \
  --subscription "<SUB>" -g "<YOUR_VNET_RG>" --vnet-name "<YOUR_VNET>" \
  --query "[].{Name:name,State:peeringState,AllowGatewayTransit:allowGatewayTransit}" \
  -o table

Important

虚拟网络对等互连不具有传递性。 如果 DMS 与辐射型虚拟网络建立对等互连,则它无法自动连接到中心的 VPN 网关。 若要使 DMS 流量到达本地或其他云中的源,您需要具备以下两者之一:直接与中心虚拟网络对等互连(这样 DMS 就可以通过 useRemoteGateways 原生使用 VPN 网关),或者在与 DMS 对等互连的虚拟网络中部署一个 TCP 代理,通过您现有的网络路径将流量转发到源。

本地或其他云网络必须具有 DMS 虚拟网络 CIDR 的返回路由,验证远程返回路由。 对于 AWS:

aws ec2 describe-route-tables --region <REGION> \
  --route-table-ids <ROUTE_TABLE_ID> \
  --query "RouteTables[0].Routes[?GatewayId!=null && starts_with(GatewayId,'vgw')].{Destination:DestinationCidrBlock,Gateway:GatewayId,State:State}" \
  --output table

对于本地路由器,请验证 DMS CIDR 是否显示在 BGP 路由表中。

远端还必须允许来自 DMS 虚拟网络 CIDR 的 入站 流量通过所需端口(默认情况下,MongoDB 为 27017)。

DMS 为每个迁移作业创建一个具有动态 CIDR 的新虚拟网络。 配置远程防火墙规则时,请使用迁移向导中显示的特定 DMS CIDR。

本地/其他云清单:

# 检查 预期
1 VPN/ExpressRoute 隧道状态 Connected、字节流动
2 Azure通过 BGP 播发 DMS CIDR 通告路由中的 DMS CIDR
3 虚拟网络对等互连允许网关传输 allowGatewayTransit=true
4 远程端具有 DMS CIDR 的返回路由 路由表中存在的路由
5 远程防火墙/SG 允许 DMS CIDR 所需端口上的入站规则
6 目标专用终结点状态 Approved

阶段 2:生成模拟环境

DMS 为每个迁移作业创建一个临时虚拟网络,并在作业完成或失败时将其删除。 若要从 DMS 网络所在位置测试连通性,请创建一个具有相同 CIDR 的用于模拟的虚拟网络,将其与您的各个网络建立对等互连,并部署一台测试 VM。

从现有网关或辐射型虚拟网络中的 VM 进行测试,只能确认 VPN 可正常工作。 它并不证明源自 DMS CIDR 的流量可以正确路由。 模拟虚拟网络复制 DMS 的确切网络位置,因此来自它的连接测试反映实际迁移流量。

创建测试虚拟网络

在 DMS 迁移向导中,使用您已提供(或计划提供)的相同 CIDR:

SUBSCRIPTION="<YOUR_SUBSCRIPTION>"
TEST_RG="dms-network-test-rg"
LOCATION="<SAME_REGION_AS_DMS>"
DMS_CIDR="<DMS_CIDR_FROM_WIZARD>"
TEST_VNET="dms-test-vnet"
TEST_SUBNET="default"
TEST_SUBNET_CIDR="<SUBNET_WITHIN_DMS_CIDR>"

az group create --subscription "$SUBSCRIPTION" -n "$TEST_RG" -l "$LOCATION"

az network vnet create --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "$TEST_VNET" \
  --address-prefix "$DMS_CIDR" \
  --subnet-name "$TEST_SUBNET" --subnet-prefix "$TEST_SUBNET_CIDR" \
  -l "$LOCATION"

与测试虚拟网络建立对等互连

创建与 DMS 所执行操作相对应的对等互连。 选择符合您的拓扑的对等互连。

对于单个虚拟网络或中心直连(VPN/ExpressRoute 场景):

HUB_RG="<HUB_OR_SINGLE_VNET_RESOURCE_GROUP>"
HUB_VNET="<HUB_OR_SINGLE_VNET_NAME>"

TEST_VNET_ID=$(az network vnet show --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "$TEST_VNET" --query id -o tsv)

HUB_VNET_ID=$(az network vnet show --subscription "$SUBSCRIPTION" \
  -g "$HUB_RG" -n "$HUB_VNET" --query id -o tsv)

# Gateway VNet → Test VNet
az network vnet peering create --subscription "$SUBSCRIPTION" \
  -g "$HUB_RG" --vnet-name "$HUB_VNET" \
  -n "hub-to-dms-test" --remote-vnet "$TEST_VNET_ID" \
  --allow-vnet-access true --allow-forwarded-traffic true --allow-gateway-transit true

# Test VNet → Gateway VNet
az network vnet peering create --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" --vnet-name "$TEST_VNET" \
  -n "dms-test-to-hub" --remote-vnet "$HUB_VNET_ID" \
  --allow-vnet-access true --allow-forwarded-traffic true --use-remote-gateways true

对于Azure中的源(无需 VPN):

SOURCE_RG="<SOURCE_RESOURCE_GROUP>"
SOURCE_VNET="<SOURCE_VNET_NAME>"

SOURCE_VNET_ID=$(az network vnet show --subscription "$SUBSCRIPTION" \
  -g "$SOURCE_RG" -n "$SOURCE_VNET" --query id -o tsv)

TEST_VNET_ID=$(az network vnet show --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "$TEST_VNET" --query id -o tsv)

az network vnet peering create --subscription "$SUBSCRIPTION" \
  -g "$SOURCE_RG" --vnet-name "$SOURCE_VNET" \
  -n "source-to-dms-test" --remote-vnet "$TEST_VNET_ID" \
  --allow-vnet-access true --allow-forwarded-traffic true

az network vnet peering create --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" --vnet-name "$TEST_VNET" \
  -n "dms-test-to-source" --remote-vnet "$SOURCE_VNET_ID" \
  --allow-vnet-access true --allow-forwarded-traffic true

与源虚拟网络不同时,与目标虚拟网络对等互连:

如果源和目标使用相同的虚拟网络,请跳过此块。 源对等互连已将公共虚拟网络连接到测试虚拟网络,Azure不允许同一虚拟网络对之间的第二个对等互连。

TARGET_RG="<TARGET_RESOURCE_GROUP>"
TARGET_VNET="<TARGET_VNET_NAME>"

TARGET_VNET_ID=$(az network vnet show --subscription "$SUBSCRIPTION" \
  -g "$TARGET_RG" -n "$TARGET_VNET" --query id -o tsv)

az network vnet peering create --subscription "$SUBSCRIPTION" \
  -g "$TARGET_RG" --vnet-name "$TARGET_VNET" \
  -n "target-to-dms-test" --remote-vnet "$TEST_VNET_ID" \
  --allow-vnet-access true --allow-forwarded-traffic true

az network vnet peering create --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" --vnet-name "$TEST_VNET" \
  -n "dms-test-to-target" --remote-vnet "$TARGET_VNET_ID" \
  --allow-vnet-access true --allow-forwarded-traffic true

验证对等互连

az network vnet peering list --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" --vnet-name "$TEST_VNET" \
  --query "[].{Name:name,State:peeringState,UseRemoteGateways:useRemoteGateways}" \
  -o table

预期: 所有对等互连都显示 peeringState = Connected。

部署测试 VM

az vm create --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "dms-test-vm" \
  --image Ubuntu2204 --size Standard_B2s \
  --vnet-name "$TEST_VNET" --subnet "$TEST_SUBNET" \
  --admin-username azureuser --generate-ssh-keys \
  --public-ip-address "" --no-wait

VM 没有公共 IP。 通过 Azure Bastion、串行控制台或 az vm run-command invoke 访问它。

阶段 3:测试模拟 VM 的连接

在测试 VM 中使用 az vm run-command invoke 运行以下命令。

测试 DNS 解析

az vm run-command invoke --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "dms-test-vm" \
  --command-id RunShellScript \
  --scripts "nslookup <SOURCE_HOSTNAME> && echo '---' && nslookup <TARGET_DOCUMENTDB_HOSTNAME>"

预期结果: 两者都解析为 私有 IP。 如果任一 IP 解析为公共 IP,请将专用 DNS 区域链接到测试虚拟网络。

测试 TCP 连接

# Source MongoDB
az vm run-command invoke --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "dms-test-vm" \
  --command-id RunShellScript \
  --scripts "nc -zv -w 10 <SOURCE_PRIVATE_IP_OR_HOSTNAME> 27017 2>&1"

# Target DocumentDB
az vm run-command invoke --subscription "$SUBSCRIPTION" \
  -g "$TEST_RG" -n "dms-test-vm" \
  --command-id RunShellScript \
  --scripts "nc -zv -w 10 <TARGET_DOCUMENTDB_HOSTNAME> 10260 2>&1"

预期:Connection … succeeded,两者均为。

使用 mongosh 进行测试

通过Azure Bastion或其他安全管理连接以交互方式连接到测试 VM。 不要在 az vm run-command 脚本中传递凭据,因为 Azure 可以在调用日志中记录脚本及其参数。

在测试 VM 上安装 mongosh:

sudo apt-get update -qq && sudo apt-get install -y -qq gnupg curl
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
  sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg
echo 'deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse' | \
  sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
sudo apt-get update -qq && sudo apt-get install -y -qq mongosh

为每个连接字符串提示输入凭据,以便凭据不会存储在 shell 历史记录中。 使用启用 TLS 并验证服务器证书的连接字符串。 不要添加 tlsAllowInvalidCertificates=true。

read -rsp "Source MongoDB connection string: " SOURCE_URI
echo
mongosh "$SOURCE_URI" --eval 'db.runCommand({ping:1})'
unset SOURCE_URI

read -rsp "Target Azure DocumentDB connection string: " TARGET_URI
echo
mongosh "$TARGET_URI" --eval 'db.runCommand({ping:1})'
unset TARGET_URI

预期:{ ok: 1 },两者均为。 如果 nc 成功但 mongosh 失败,则网络正常运行,问题可能与身份验证凭据或 TLS 配置相关。

解读结果

Result Meaning Action
对等互连状态 = Disconnected CIDR 重叠或虚拟网络配置问题 检查是否存在重叠的地址空间
nc 到源超时 流量被阻止或未路由 检查防火墙规则、返回路由、NSG
nc 成功, mongosh TLS 错误 TLS/证书不匹配 检查 tls=true 和证书设置
nc 成功, mongosh 身份验证错误 凭据错误 验证用户名/密码和身份验证数据库
DNS 解析为公共 IP 专用 DNS 区域未链接 将 DNS 区域链接到测试虚拟网络
源 CIDR 的有效路由显示None 无到源的路由 检查 VPN 网关/对等互连配置

如果所有测试都通过,但迁移作业仍然失败,则问题可能在于 DMS 管理的组件,而不是基础结构。 请联系 Azure 技术支持,并提供这些测试结果,以便加快故障排除过程。

阶段 4:清理

Important

在重试迁移作业 之前 清理模拟虚拟网络和 VM。 如果它们仍然存在,则 DMS 由于 IP 地址冲突而无法创建自己的虚拟网络和 VM。

# Remove the test resource group (includes the test VNet and VM)
az group delete --subscription "$SUBSCRIPTION" -n "$TEST_RG" --yes

# Remove peerings on your existing VNets
az network vnet peering delete --subscription "$SUBSCRIPTION" \
  -g "<HUB_RG>" --vnet-name "<HUB_VNET>" -n "hub-to-dms-test" 2>/dev/null

az network vnet peering delete --subscription "$SUBSCRIPTION" \
  -g "<SOURCE_RG>" --vnet-name "<SOURCE_VNET>" -n "source-to-dms-test" 2>/dev/null

az network vnet peering delete --subscription "$SUBSCRIPTION" \
  -g "<TARGET_RG>" --vnet-name "<TARGET_VNET>" -n "target-to-dms-test" 2>/dev/null

常见连接问题

Issue 症状 解决方案
DMS CIDR 未通过 BGP 通告 VPN 已启动,但迁移报告连接错误 在网关虚拟网络对等互连上启用 allowGatewayTransit=true
远程防火墙阻止 DMS CIDR 其他 Azure 虚拟网络可以访问源,但 DMS 连接超时 将向导中的 DMS CIDR 添加到远端防火墙规则中
代理 NSG 阻止 DMS CIDR 代理可以访问源端,但 DMS 向代理发出的请求会超时 在与代理 VM 网络接口或子网关联的 NSG 中,添加允许从迁移向导中提供的 DMS CIDR 到代理侦听端口的 TCP 流量的入站规则
缺少返回路由 流量离开Azure但永远不会返回;连接超时 在远程路由表上启用路由传播,或为 DMS CIDR 添加静态路由
专用终结点未获批准 DNS 解析但连接被拒绝 在门户或 CLI 中批准专用终结点连接
DNS 无法正确解析 主机名解析为公共 IP 而不是专用 IP 将专用 DNS 区域链接到用于迁移的虚拟网络
CIDR 重叠 虚拟网络对等互连失败或一直处于 Disconnected 选择不与现有虚拟网络冲突的 DMS CIDR
资源锁阻止对等互连清理 使用相同 CIDR 的新迁移任务会失败,因为之前作业中的源到 DMS 或目标到 DMS 的对等连接仍然存在 从源虚拟网络或目标虚拟网络中删除锁,或者从任一资源组中删除锁,删除残留的对等互连,然后重试迁移
用于多个专用作业的单个虚拟网络 第二个任务失败或干扰第一个任务 为每个并发迁移作业使用不同的虚拟网络