我正在 Windows Server 2019 上的 SQL Server 2019 中配置可用性组。
我们有两个 Windows 服务器,UT01 和 UT02,配置了一个网络适配器,使用 Active Directory 域上的静态 IP 地址。
网络组为集群虚拟计算机对象分配了一个静态 IP 地址,UTCL,192.168.0.12。他们还为可用性组监听器分配了一个静态 IP 地址,UTAG,192.168.0.13。
服务器 | IP地址 | 子网 |
---|---|---|
UT01 | 192.168.0.10 | 192.168.0.0/24 |
UT02 | 192.168.0.11 | 192.168.0.0/24 |
UTCL | 192.168.0.12 | 192.168.0.0/24 |
UTAG | 192.168.0.13 | 192.168.0.0/24 |
服务器团队配置了 Windows Server 故障转移集群,我配置了 SQL Server 和可用性组。两个 SQL Server 都配置为命名实例;所以是返回的UT01\INS
名称UT02\INS
@@SERVERNAME;
从本地子网 (192.168.0.0/24) 上的任何计算机,我可以使用 sqlcmd 连接到可用性组,如下所示:
sqlcmd -S UTAG\INS
当我运行时PRINT @@SERVERNAME;
,返回UT01\INS
或UT02\INS
,具体取决于哪个节点当前正在运行可用性组的主节点。
我可以使用 sqlcmd 通过路由器从本地子网外的网络连接到各个 SQL Server,即sqlcmd -S UT01\INS
并sqlcmd -S UT02\INS
正常工作,为@@SERVERNAME
.
到目前为止一切都很好,完全符合预期。
但是,当我尝试通过非本地子网连接到 AG 名称时,AG 仅在 UT01 运行主节点时响应。当 UT02 运行主节点时,我们会遇到典型的连接错误:
建立与 SQL Server 的连接时发生了与网络相关或特定于实例的错误。服务器未找到或不可访问。检查实例名称是否正确以及 SQL Server 是否配置为允许远程连接。
UT02 上的 SQL Server 错误日志显示没有失败的登录(默认配置为审核失败的登录)。
ping UTAG
返回正确的 IP 地址 192.168.0.13,无论我在哪里运行它。 ping UTAG
从本地子网正常工作,当 AG 在 UT01 上运行时从远程子网工作,但当 UT02 是主要子网时则不能。
我在 UT01 和 UT02 上都安装了 WireShark 以查看是否可以确定发生了什么。我过滤了 WireShark 的输出:
((tcp.port == 2136) || (udp.port == 1434)) && ((ip.dst == 192.168.0.13 || ip.src == 192.168.0.13))
SQL Server AG 侦听器端口配置为侦听端口 2136,并且两个实例也配置为侦听端口 2136。SQL Server 配置管理器显示网络配置配置为侦听所有 IP 地址。
在 UT01 上观察 WireShark,当尝试从位于另一个子网上的客户端连接到 AG 时,无论哪个节点是 AG 主节点,都会显示端口 2136 上的传入 TCP 流量和端口 1434 上的 UDP 流量。当 AG primary 在 UT01 上运行时,连接到 AG 正常,当 AG primary 在 UT02 上时,连接到 AG 失败。
两台服务器都是虚拟机,运行在不同的物理主机上。交换机(虚拟或其他)清楚地知道哪个节点正在运行主节点,因为ping UTAG
无论哪个节点拥有 UTAG IP 地址,本地子网都可以工作。 ping UTAG
来自任何其他子网的请求仅在 AG 在 UT01 上运行时响应。
有任何想法吗?
因此,需要在服务于连接两个 SQL Server 与其他子网的本地子网的网络交换机中启用“基于 GARP 的检测”。
GARP 是 Gratuitous Address Resolution Protocol,用于广播托管可用性组的网络适配器的 MAC 地址。在我们的例子中,连接到交换机的路由器没有看到每当发生可用性组故障转移时自动生成的 ARP 数据包,从而阻止它发送发往 AG 的 TCP 数据包到正确的 MAC 地址 - 它只是总是发送这些数据包到第一个节点。
此 Microsoft 页面解释了该问题。