Skip to main content

SQL Server Always On AG(WSFC)配置指南(2) - 创建和配置gMSA账号

分类:  SQL Server 标签:  #SQL Server #SQL Server Always on AG 发布于: 2026-03-16 18:02:39

开始本章之前请检查下述清单:

  1. 安装了Windows Server
  2. 已经配置了网络,禁止了IPV6
  3. 创建了域控和DNS
  4. 将所有的节点都已经加入了域
  5. 安装了SQL Server
  6. 安装了故障转移集群

如果有遗漏,请补上,减少后期出错的可能性。

本章我们开始为运行SQL Server Always on AG准备运行账号,默认安装是使用本地的账号进行的,在配置多节点的集群上不推荐,容易遇到各种问题。

微软官方推荐两个方案来配置运行账号:

  • gMSA(Group Managed Service Account)
  • 专用的域账号

本章讨论gMSA

如下是基本步骤:

  1. 配置kdc root Key
  2. 创建安全组
  3. 添加所有SQL节点到安全组
  4. 创建gMSA账号
  5. gMSA分配read ServicePrincipalwrite servicePrincipal的权限
  6. 在各个SQL节点上安装gMSA账号
  7. 在各个SQL节点上为gMSA配置本地权限
  8. 在各个SQL节点上为gMSA配置文件权限
  9. 在各个SQL节点上为gMSA在数据库里创建login并赋予sysadmin角色
  10. 在各个SQL节点上为gMSA在数据库里创建AG Endpoint的权限。
  11. 使用SQL Server Configuration Manager 为SQL ServerSQL Server Agent配置运行账户为gMSA
  12. 观察gMSA是否自动注册了SPN

以域管理员的身份登陆到域控(一定是域控), 以管理员的身份启动终端。

配置kdc root key (在域控上)

在终端里运行:

Test-KdsRootKey -KeyId (Get-KdsRootKey).KeyId

如果没有任何返回,那么我们需要创建kdc root key, 如果您的系统是一个多节点的系统,尝试使用如下的命令:

Add-KdsRootKey -EffectiveImmediately

需要注意的是:

  • 多节点系统需要等待一会儿,创建完成之后可以使用test-kdsrootkey多次测试结果。
  • 如果是测试环境或者单dc环境,请使用如下的命令创建kdc root key
Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))

无论是哪种方法创建kdc root key都可以使用test-kdsrootkey -keyid (get-kdsrootkey).keyid来验证。

创建安全组和gMSA账户(在域控上)

运行下述命令创建安全组:

New-ADGroup -Name "grp-gmsa-sql-ag" -GroupScope Global -GroupCategory Security

安全组创建成功后,需要将所有的SQL Server节点机器加入到该安全组, 例如你的SQL Server节点的机器名字分别叫:dbserver1dbserver2,

注意
这里的前置要求是域控已经配置完毕,SQL Server节点也已经加入到域了

Add-ADGroupMember grp-gmsa-sql-ag dbserver1$
Add-ADGroupMember grp-gmsa-sql-ag dbserver2$

注意机器名称后面要多加一个$

创建账号:

New-ADServiceAccount -Name "gmsa-sql-ag" -SamAccountName "gmsa-sql-ag" -DNSHostName "gmsa-sql-ag.yourdomain.com"  -PrincipalsAllowedToRetrieveManagedPassword "grp-gmsa-sql-ag"

这里DNSHostName 主要用于kerberos/SPN
PrincipalsAllowedToRetrieveManagedPassword用于绑定服务器组

注意:
如果创建账号遇到错误:

New-ADServiceAccount : Key does not exist
At line:1 char:1
+ New-ADServiceAccount -Name "gmsa-sql-ag" -SamAccountName "gmsa-sql-ag ...

请重新创建kdc root key,使用下述语句缓解问题:
Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))

这类问题的troubleshooting的步骤:

为什么之前明明已经创建了kdc root key但是还是不起作用?可能的原因:

  1. 在非域控机器上运行的该命令

  2. kds root key刚创建,还没有生效,微软官方文档给出的理由:

    • AD 需要复制 & 初始化
    • 在部分环境(尤其多 DC):可能需要等待一段时间

    否则 gMSA 创建会报 Key does not exist
    验证是否真的“可用”: Get-KdsRootKey, 看到了KeyId才算真正存在

  3. 在单域或者试验的环境中或者刚刚搭建的环境中,更稳妥的创建kds root key的方式是:
    Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10)), 尤其是hyper-v环境中,微软最推荐的方式。

  4. 你的用户账户不是Schema/Domain Admin

百分百能创建成功的步骤:

  1. hostname 确认是登陆的域控
  2. Get-KdsRootKey 确认kdc root key的状态
  3. 如果返回空,重新创建kds root keyAdd-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))
  4. 再次创建gMSA账号

在每台SQL节点上安装账号

分别在每台SQL节点上(可以考虑使用Powershell远程终端), 运行如下的命令:

Install-WindowsFeature RSAT-AD-PowerShell
Install-ADServiceAccount -Identity gmsa-sql-ag
Test-ADServiceAccount -Identity gmsa-sql-ag

如果在运行install命令出错,例如返回如下错误:

Install-ADServiceAccount : Cannot install service account. Error Message: '{Access Denied}
A process has requested access to an object, but has not been granted those access rights.'.

请使用如下的步骤缓解:

  • 先确保命令是在“管理员 PowerShell”运行

  • 确认:SQL 节点计算机账号确实在允许组里(域控上运行):
    Get-ADGroupMember "grp-gmsa-sql-ag" | Select-Object Name, ObjectClass, 机器名是否在返回结果中, 如果不在,加进去:
    Add-ADGroupMember -Identity "grp-gmsa-sql-ag" -Members SQLNODE1$,SQLNODE2$,SQLNODE3$

  • 确认:gMSA 对象确实绑定了这个允许组(域控上运行):
    Get-ADServiceAccount gmsa-sql-ag -Properties PrincipalsAllowedToRetrieveManagedPassword |Select-Object -ExpandProperty PrincipalsAllowedToRetrieveManagedPassword,
    如果确实没有,重新设置:Set-ADServiceAccount -Identity gmsa-sql-ag -PrincipalsAllowedToRetrieveManagedPassword "grp-gmsa-sql-ag"

  • 最常见“已加组但仍 Access Denied”的修复:
    刷新这台 SQL 节点的机器票据:

      klist purge -li 0x3e7
      gpupdate /force /target:computer
    

再返回执行之前的账号安装命令

gMSN赋予Read servicePrincipalWrite servicePrincipal的权限(在域控上运行)

这个部分我称之为微软最腹黑的地方,GUI操作非常反人类,直接使用PowerShell来完成,请确保在域控上,并打开了Powershell的管理员模式:

  1. 在域控上获取 gMSA DN:

        $gmsa = Get-ADServiceAccount gmsa-sql-ag
        $gmsa.DistinguishedName
    

    样例输出:CN=gmsa-sql-ag,OU=ServiceAccounts,DC=hong,DC=cn

  2. 授予 SELF → Write servicePrincipalName

    dsacls "CN=gmsa-sql-ag,OU=ServiceAccounts,DC=hong,DC=cn" /G "SELF:RPWP;servicePrincipalName"
    

另外一个方案,如果是大规模的SQL Server Alaways on AG 或者是IIS集群:
在 OU 上一次性委派, 如果你把 所有 gMSA 都放在一个 OU(强烈推荐):
步骤:
对 OU 执行 Delegate Control
委派对象:SELF
对象类型:Group Managed Service Account
权限:Write servicePrincipalName

  • 新建的 gMSA 自动具备 SPN 自注册能力
  • 大规模 SQL / AG / IIS 场景必备

这样只要gMSA加入到这个组,就自动有spn自注册能力。

在每个SQL节点上给gMSA配置login as service

启动本地策略编辑器 secpol.msc, 按照下图添加gMSA, 注意它的账号格式: HONG\gmsa-sql-ag$, 这个账号后面必须要额外添加一个$


在每个SQL节点上给gMSA分配文件权限

icacls "C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA" /grant 'HONG\gmsa-sql-ag$:(OI)(CI)F'
icacls “C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Backup" /grant 'HONG\gmsa-sql-ag$:(OI)(CI)F'

需要注意的是,上述的目录路径是SQL Server的默认安装路径,C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA 将数据文件和日志文件放在了一起,如果你安装SQL Server的时候,将数据文件目录,日志目录,备份目录分开了放,上述路径根据需要更改。

命令解析:
'HONG\gmsa-sql-ag$:(OI)(CI)F'

  • HONG\gmsa-sql-ag$ —— 权限主体(Security Principal)
  • HONG\:域名
  • gmsa-sql-aggMSA账号。gMSA在域里是一个托管服务账号,命名上通常以 结尾(就像计算机账号 SQLNODE1$ 一样)。

也就是说:你在给 这个 gMSA 服务账号授权,让 SQL Server 服务运行时能访问目录。

:(OI)(CI)F —— 继承范围 + 权限级别

  • 冒号 ::分隔“主体”和“权限/继承标志”

  • (OI) Object Inherit(对象继承)
    表示:子文件会继承这条权限。

  • (CI) Container Inherit(容器继承)
    表示:子文件夹会继承这条权限。
    组合起来 (OI)(CI) 的效果是:该目录下现有 & 将来新建的文件/子目录,都会继承这条权限。

  • F Full Control(完全控制)
    F 表示 Full access(完全控制)。在 icacls 的“简单权限”里,F/M/RX/R/W 是常见的简写,其中 F 权限最高

SQL Server里添加gMSA作为Login, 并赋予权限(每个SQL节点上)

使用工具,例如SSMS登陆到SQL Server, 运行下述命令:

CREATE LOGIN [HONG\gmsa-sql-ag$] FROM WINDOWS;
ALTER SERVER ROLE sysadmin ADD MEMBER [HONG\gmsa-sql-ag$];

赋予AG Endpoint权限

GRANT CONNECT ON ENDPOINT::[Hadr_endpoint]
TO [HONG\gmsa-sql-ag$];

SQL ServerSQL Server Agent的运行账号更改为gMSA

如下图配置:



配置完成后需要重启SQL Server

明天继续介绍另外一个方案,使用专用的域账号来配置