故障描述:AD 模式登录失败 - 不受信任的域(大数据群集)
重要
Microsoft SQL Server 2019 大数据群集附加产品将停用。 对 SQL Server 2019 大数据群集的支持将于 2025 年 2 月 28 日结束。 具有软件保障的 SQL Server 2019 的所有现有用户都将在平台上获得完全支持,在此之前,该软件将继续通过 SQL Server 累积更新进行维护。 有关详细信息,请参阅公告博客文章和 Microsoft SQL Server 平台上的大数据选项。
在 Active Directory 模式下的 SQL Server 大数据群集上,连接尝试可能会失败,并返回以下错误:
Login failed. The login is from an untrusted domain and cannot be used with Integrated authentication.
如果已将 DNS 条目配置为 CNAME(它指向将流量分发到 Kubernetes 节点的反向代理的别名),则会发生这种情况。
根本原因
如果将终结点的 DNS 条目配置为 CNAME(它指向将流量分发到 Kubernetes 节点的反向代理的别名):
- Kerberos 身份验证过程会查找与 CNAME 条目匹配的服务主体名称 (SPN);而不是 BDC 在 Active Directory 中注册的实际 SPN
- 身份验证会失败
确认根本原因
身份验证失败后,请检查 Kerberos 票证的缓存。
要检查票证的缓存,请使用 klist
命令。
查找与你尝试连接的终结点匹配的 SPN 的票证。
找不到预期票证。
在下面的示例中,主终结点(bdc-sql
DNS 记录)是设置为 ServerReverseProxy
反向代理的 CNAME
Resolve-DnsName bdc-sql
以下部分显示前一个命令的结果。
Name Type TTL Section NameHost
---- ---- --- ------- --------
bdc-sql.mydomain.com CNAME 3600 Answer ReverseProxyServer.mydomain.com
Name : ReverseProxyServer.mydomain.com
QueryType : A
TTL : 3600
Section : Answer
IP4Address : 193.168.5.10
若要查看从 Active Directory 请求的 SPN,请使用 tshark
。 以下命令将网络跟踪捕获限制为 Kerberos 协议通信,并仅显示 krb-error (30)
消息。 这些消息应包含失败的 SPN 请求消息。
tshark -Y "kerberos && kerberos.msg_type == 30" -T fields -e kerberos.error_code -e kerberos.SNameString
在其他命令行界面中,尝试连接到主 Pod:
klist purge
sqlcmd -S bdc-sql.mydomain.com,31433 -E
来看看下面的示例输出。
klist purge
Current LogonId is 0:0xf6b58
Deleting all tickets:
Ticket(s) purged!
sqlcmd -S bdc-sql.mydomain.com,31433 -E
sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login failed. The login is from an untrusted domain and cannot be used with Integrated authentication.
查看 tshark
输出。
Capturing on 'Ethernet 3'
25 krbtgt,RLAZURE.COM
7 MSSQLSvc,ReverseProxyServer.mydomain.com:31433
2 packets captured
请注意,客户端请求的 SPN MSSQLSvc,ReverseProxyServer.mydomain.com:31433
不存在。 连接尝试最终失败,显示错误 7。 错误 7 表示 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN Server not found in Kerberos database
。
在正确的配置中,客户端将请求 BDC 注册的 SPN。 本例中正确的 SPN 应该是 MSSQLSvc,bdc-sql.mydomain.com:31433
。
注意
错误 25 表示 KDC_ERR_PREAUTH_REQUIRED
- 需要额外的预身份验证。 可以安全地忽略此错误。 在初始 Kerberos AD 请求中返回 KDC_ERR_PREAUTH_REQUIRED
。 默认情况下,Windows Kerberos 客户端在第一个请求中不包括预身份验证信息。
要查看 BDC 为主终结点注册的 SPN 列表,请运行 setspn -L mssql-master
。
请参阅以下示例输出:
Registered ServicePrincipalNames for CN=mssql-master,OU=bdc,DC=mydomain,DC=com:
MSSQLSvc/bdc-sqlread.mydomain.com:31436
MSSQLSvc/-sqlread:31436
MSSQLSvc/bdc-sqlread.mydomain.com
MSSQLSvc/bdc-sqlread
MSSQLSvc/bdc-sql.mydomain.com:31433
MSSQLSvc/bdc-sql:31433
MSSQLSvc/bdc-sql.mydomain.com
MSSQLSvc/bdc-sql
MSSQLSvc/master-p-svc.mydomain.com:1533
MSSQLSvc/master-p-svc:1533
MSSQLSvc/master-p-svc.mydomain.com:1433
MSSQLSvc/master-p-svc:1433
MSSQLSvc/master-p-svc.mydomain.com
MSSQLSvc/master-p-svc
MSSQLSvc/master-svc.mydomain.com:1533
MSSQLSvc/master-svc:1533
MSSQLSvc/master-svc.mydomain.com:1433
MSSQLSvc/master-svc:1433
MSSQLSvc/master-svc.mydomain.com
MSSQLSvc/master-svc
在上面的结果中,不应注册反向代理地址。
解决
本节介绍可解决此问题的两种方法。 做出适当的更改后,在客户端中运行 ipconfig -flushdns
和 klist purge
。 然后再次尝试连接。
选项 1
在 DNS 中删除每个 BDC 终结点的 CNAME 记录,并将其替换为指向每个 Kubernetes 节点或每个 Kubernetes 主节点(如果有多个主节点)的多个 A
记录。
提示
下面所述的脚本使用 PowerShell。 有关详细信息,请参阅在 Linux 上安装 PowerShell。
可以使用以下 PowerShell 脚本更新 DNS 终结点记录。 从连接到同一域的任何计算机运行以下脚本:
#Specify the DNS server, example contoso.local
$Domain_DNS_name=mydomain.com'
#DNS records for bdc endpoints
$Controller_DNS_name = 'bdc-control'
$Managment_proxy_DNS_name= 'bdc-proxy'
$Master_Primary_DNS_name = 'bdc-sql'
$Master_Secondary_DNS_name = 'bdc-sqlread'
$Gateway_DNS_name = 'bdc-gateway'
$AppProxy_DNS_name = 'bdc-appproxy'
#Performing Endpoint DNS records Checks..
#Build array of endpoints
$BdcEndpointsDns = New-Object System.Collections.ArrayList
[void]$BdcEndpointsDns.Add($Controller_DNS_name)
[void]$BdcEndpointsDns.Add($Managment_proxy_DNS_name)
[void]$BdcEndpointsDns.Add($Master_Primary_DNS_name)
[void]$BdcEndpointsDns.Add($Master_Secondary_DNS_name)
[void]$BdcEndpointsDns.Add($Gateway_DNS_name)
[void]$BdcEndpointsDns.Add($AppProxy_DNS_name)
#Build arrary for results
$BdcEndpointsDns_Result = New-Object System.Collections.ArrayList
foreach ($DnsName in $BdcEndpointsDns) {
try {
$endpoint_DNS_record = Resolve-DnsName $DnsName -Type A -Server $Domain_DNS_IP_address -ErrorAction Stop
foreach ($ip in $endpoint_DNS_record.IPAddress) {
[void]$BdcEndpointsDns_Result.Add("OK - $DnsName is an A record with an IP $ip")
}
}
catch {
[void]$BdcEndpointsDns_Result.Add("MisConfiguration - $DnsName is not an A record or does not exists")
}
}
#show the results
$BdcEndpointsDns_Result
方法 2
另外,将 CNAME 修改为指向反向代理的 IP 地址(而不是反向代理的名称)后,也可以解决此问题。
确认解决方法
使用上面的一种方法解决修复后,通过使用 Active Directory 连接到大数据群集来确认修复。