為 Windows Pod 和容器配置 GMSA
Kubernetes v1.18 [stable]
本頁面展示如何為將在 Windows 節點上執行的 Pod 和容器配置 組託管服務賬戶 (GMSA)。組託管服務賬戶是一種特定型別的 Active Directory 賬戶,提供自動密碼管理、簡化的服務主體名稱 (SPN) 管理,以及將管理許可權委託給多個伺服器上的其他管理員的能力。
在 Kubernetes 中,GMSA 憑據規範以 Kubernetes 叢集範圍的自定義資源形式進行配置。Windows Pod 以及 Pod 內的單個容器可以配置為使用 GMSA,以便在與其他 Windows 服務互動時執行基於域的功能(例如 Kerberos 身份驗證)。
準備工作
你需要擁有一個 Kubernetes 叢集,並且 kubectl
命令列工具必須配置為與你的叢集通訊。叢集應包含 Windows 工作節點。本節介紹每個叢集僅需執行一次的初始步驟。
安裝 GMSACredentialSpec CRD
叢集上需要配置 GMSA 憑據規範資源的 CustomResourceDefinition (CRD),以定義自定義資源型別 GMSACredentialSpec
。下載 GMSA CRD YAML 並將其儲存為 gmsa-crd.yaml。接下來,使用 kubectl apply -f gmsa-crd.yaml
安裝 CRD。
安裝 Webhook 以驗證 GMSA 使用者
需要在 Kubernetes 叢集上配置兩個 Webhook,以在 Pod 或容器級別填充和驗證 GMSA 憑據規範引用:
一個變異 Webhook,用於將對 GMSA 的引用(透過 Pod 規範中的名稱)擴充套件為 Pod 規範中 JSON 格式的完整憑據規範。
一個驗證 Webhook,確保對 GMSA 的所有引用都被 Pod 服務賬戶授權使用。
安裝上述 Webhook 及相關物件需要以下步驟:
建立證書金鑰對(用於允許 Webhook 容器與叢集通訊)。
使用上述證書安裝一個 Secret。
為核心 Webhook 邏輯建立部署。
建立引用部署的驗證和變異 Webhook 配置。
可以使用指令碼來部署和配置上述 GMSA Webhook 及相關物件。指令碼可以帶 --dry-run=server
選項執行,以便你檢視將對叢集進行的更改。
指令碼使用的 YAML 模板 也可以用於手動部署 Webhook 和相關物件(引數需要適當替換)。
在 Active Directory 中配置 GMSA 和 Windows 節點
在 Kubernetes 中的 Pod 可以配置為使用 GMSA 之前,需要在 Active Directory 中配置所需的 GMSA,如 Windows GMSA 文件 中所述。Windows 工作節點(作為 Kubernetes 叢集的一部分)需要在 Active Directory 中進行配置,以訪問與所需 GMSA 關聯的秘密憑據,如 Windows GMSA 文件 中所述。
建立 GMSA 憑據規範資源
安裝 GMSACredentialSpec CRD 後(如前所述),可以配置包含 GMSA 憑據規範的自定義資源。GMSA 憑據規範不包含秘密或敏感資料。它是容器執行時可以用來描述容器所需的 GMSA 給 Windows 的資訊。GMSA 憑據規範可以使用一個實用 PowerShell 指令碼 生成 YAML 格式。
以下是手動生成 JSON 格式的 GMSA 憑據規範 YAML,然後進行轉換的步驟:
匯入 CredentialSpec 模組:
ipmo CredentialSpec.psm1
使用
New-CredentialSpec
建立 JSON 格式的憑據規範。要建立名為 WebApp1 的 GMSA 憑據規範,請呼叫New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)
使用
Get-CredentialSpec
顯示 JSON 檔案的路徑。將憑據規範檔案從 JSON 轉換為 YAML 格式,並應用必要的頭欄位
apiVersion
、kind
、metadata
和credspec
,使其成為可在 Kubernetes 中配置的 GMSACredentialSpec 自定義資源。
以下 YAML 配置描述了一個名為 gmsa-WebApp1
的 GMSA 憑據規範:
apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 # This is an arbitrary name but it will be used as a reference
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 # Username of the GMSA account
Scope: CONTOSO # NETBIOS Domain Name
- Name: WebApp1 # Username of the GMSA account
Scope: contoso.com # DNS Domain Name
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com # DNS Domain Name
DnsTreeName: contoso.com # DNS Domain Name Root
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a # GUID of the Domain
MachineAccountName: WebApp1 # Username of the GMSA account
NetBiosName: CONTOSO # NETBIOS Domain Name
Sid: S-1-5-21-2126449477-2524075714-3094792973 # SID of the Domain
上述憑證規範資源可以儲存為 gmsa-Webapp1-credspec.yaml
,並使用以下命令應用到叢集:kubectl apply -f gmsa-Webapp1-credspec.yml
配置叢集角色以在特定 GMSA 憑證規範上啟用 RBAC
需要為每個 GMSA 憑證規範資源定義一個叢集角色。這授權了主題(通常是服務賬戶)在特定 GMSA 資源上使用 use
動詞。以下示例顯示了一個授權使用上述 gmsa-WebApp1
憑證規範的叢集角色。將檔案儲存為 gmsa-webapp1-role.yaml,並使用 kubectl apply -f gmsa-webapp1-role.yaml
應用。
# Create the Role to read the credspec
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
為服務賬戶分配角色以使用特定的 GMSA credspecs
一個服務賬戶(Pod 將配置使用該賬戶)需要繫結到上面建立的叢集角色。這授權服務賬戶使用所需的 GMSA 憑證規範資源。以下顯示了預設服務賬戶繫結到叢集角色 webapp1-role
,以使用上面建立的 gmsa-WebApp1
憑證規範資源。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: allow-default-svc-account-read-on-gmsa-WebApp1
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: webapp1-role
apiGroup: rbac.authorization.k8s.io
在 Pod 規範中配置 GMSA 憑據規範引用
Pod 規範字段 securityContext.windowsOptions.gmsaCredentialSpecName
用於在 Pod 規範中指定對所需 GMSA 憑據規範自定義資源的引用。這會配置 Pod 規範中的所有容器使用指定的 GMSA。一個填充了引用 gmsa-WebApp1
註解的示例 Pod 規範:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-webapp1
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
nodeSelector:
kubernetes.io/os: windows
Pod 規範中的單個容器也可以使用每個容器的 securityContext.windowsOptions.gmsaCredentialSpecName
欄位指定所需的 GMSA 憑證規範。例如:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-Webapp1
nodeSelector:
kubernetes.io/os: windows
當帶有 GMSA 欄位的 Pod 規範(如上所述)在叢集中應用時,會發生以下事件序列:
變異 Webhook 解析並展開對 GMSA 憑據規範資源的所有引用到 GMSA 憑據規範的內容中。
驗證 Webhook 確保與 Pod 關聯的服務賬戶被授權在指定的 GMSA 憑證規範上使用
use
動詞。容器執行時使用指定的 GMSA 憑證規範配置每個 Windows 容器,以便容器可以承擔 Active Directory 中 GMSA 的身份,並使用該身份訪問域中的服務。
使用主機名或 FQDN 驗證網路共享
如果你在 Pod 中使用主機名或 FQDN 連線 SMB 共享時遇到問題,但可以透過 IPv4 地址訪問共享,請確保 Windows 節點上設定了以下注冊表項。
reg add "HKLM\SYSTEM\CurrentControlSet\Services\hns\State" /v EnableCompartmentNamespace /t REG_DWORD /d 1
之後,需要重新建立執行中的 Pod 以使其拾取行為更改。有關此登錄檔項如何使用的更多資訊,請參閱此處。
故障排除
如果您在環境中配置 GMSA 遇到困難,可以採取以下故障排除步驟。
首先,確保 credspec 已傳遞給 Pod。為此,您需要 exec
進入其中一個 Pod 並檢查 nltest.exe /parentdomain
命令的輸出。
在下面的示例中,Pod 未能正確獲取 credspec:
kubectl exec -it iis-auth-7776966999-n5nzr powershell.exe
nltest.exe /parentdomain
命令導致以下錯誤:
Getting parent domain failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
如果你的 Pod 正確獲得了憑據規範,那麼接下來檢查與域的通訊。首先,從你的 Pod 內部,快速執行 nslookup 來查詢你的域的根。
這將告訴我們三件事:
- Pod 可以訪問域控制器 (DC)
- DC 可以訪問 Pod
- DNS 正在正常工作。
如果 DNS 和通訊測試透過,接下來你需要檢查 Pod 是否已與域建立安全通道通訊。為此,再次 exec
進入你的 Pod 並執行 nltest.exe /query
命令。
nltest.exe /query
結果如下:
I_NetLogonControl failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
這告訴我們,由於某種原因,Pod 無法使用憑證規範中指定的帳戶登入到域。你可以嘗試透過執行以下命令來修復安全通道:
nltest /sc_reset:domain.example
如果命令成功,你將看到類似這樣的輸出:
Flags: 30 HAS_IP HAS_TIMESERV
Trusted DC Name \\dc10.domain.example
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully
如果上述方法糾正了錯誤,你可以透過將以下生命週期鉤子新增到 Pod 規範中來自動化該步驟。如果它沒有糾正錯誤,你需要再次檢查你的 credspec 並確認它是否正確和完整。
image: registry.domain.example/iis-auth:1809v1
lifecycle:
postStart:
exec:
command: ["powershell.exe","-command","do { Restart-Service -Name netlogon } while ( $($Result = (nltest.exe /query); if ($Result -like '*0x0 NERR_Success*') {return $true} else {return $false}) -eq $false)"]
imagePullPolicy: IfNotPresent
如果你將上面顯示的 lifecycle
部分新增到 Pod 規範中,Pod 將執行列出的命令以重啟 netlogon
服務,直到 nltest.exe /query
命令無錯誤退出。