為 Windows Pods 和容器設定 GMSA
Kubernetes v1.18 [stable]
此頁面說明如何為將在 Windows 節點上執行的 Pod 和容器設定群組受管理服務帳戶 (GMSA)。群組受管理服務帳戶是一種特定的 Active Directory 帳戶類型,可提供自動密碼管理、簡化的服務主體名稱 (SPN) 管理,以及將管理委派給多個伺服器上的其他管理員的能力。
在 Kubernetes 中,GMSA 憑證規格在 Kubernetes 叢集範圍內設定為自訂資源。Windows Pod 以及 Pod 內的個別容器可以設定為在與其他 Windows 服務互動時,使用 GMSA 進行網域型功能 (例如 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 憑證規格參考
一個 Mutating Webhook,可將 GMSA 的參考 (依 Pod 規格中的名稱) 展開為 Pod 規格內 JSON 格式的完整憑證規格。
一個 Validating Webhook,可確保所有 GMSA 參考都已獲得 Pod 服務帳戶的使用授權。
安裝上述 Webhook 和相關物件需要以下步驟
建立憑證金鑰組 (將用於允許 Webhook 容器與叢集通訊)
使用上述憑證安裝密鑰。
為核心 Webhook 邏輯建立部署。
建立參考部署的 Validating 和 Mutating Webhook 組態。
可以使用腳本來部署和設定上述 GMSA Webhook 和相關物件。可以使用 --dry-run=server
選項執行腳本,以允許您審查將對叢集所做的變更。
腳本使用的YAML 範本也可以用於手動部署 Webhook 和相關物件 (針對參數進行適當的替換)
在 Active Directory 中設定 GMSA 和 Windows 節點
在 Kubernetes 中的 Pod 可以設定為使用 GMSA 之前,需要在 Active Directory 中佈建所需的 GMSA,如Windows GMSA 文件中所述。需要在 Active Directory 中設定 Windows 工作節點 (屬於 Kubernetes 叢集的一部分),以存取與所需 GMSA 相關聯的密鑰憑證,如Windows GMSA 文件中所述。
建立 GMSA 憑證規格資源
安裝 GMSACredentialSpec CRD (如先前所述) 後,可以設定包含 GMSA 憑證規格的自訂資源。GMSA 憑證規格不包含密鑰或敏感資料。它是容器執行期可用於向 Windows 描述容器所需 GMSA 的資訊。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 憑證規格
需要將服務帳戶 (將使用 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 規格 (如上所述) 在叢集中套用時,會發生以下事件序列
Mutating Webhook 解析並展開所有 GMSA 憑證規格資源的參考,以取得 GMSA 憑證規格的內容。
Validating Webhook 確保與 Pod 相關聯的服務帳戶已獲得授權,可以對指定的 GMSA 憑證規格執行
use
動詞。容器執行期使用指定的 GMSA 憑證規格設定每個 Windows 容器,以便容器可以承擔 Active Directory 中 GMSA 的身分,並使用該身分存取網域中的服務。
使用主機名稱或 FQDN 驗證網路共用
如果您在使用主機名稱或 FQDN 從 Pod 連接到 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 已正確取得認證規格 (credspec),則接下來請檢查與網域的通訊。首先,從您的 Pod 內部,快速執行 nslookup 以尋找您網域的根目錄。
這將告訴我們 3 件事
- 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 無法使用認證規格 (credspec) 中指定的帳戶登入網域。您可以嘗試執行以下命令來修復安全通道
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
如果上述步驟修正了錯誤,您可以將以下生命週期 hook 新增至您的 Pod spec 來自動化此步驟。如果它沒有修正錯誤,您將需要再次檢查您的認證規格 (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 spec,Pod 將執行列出的命令以重新啟動 netlogon
服務,直到 nltest.exe /query
命令無錯誤退出。