為 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 憑證規格參考

  1. 一個 Mutating Webhook,可將 GMSA 的參考 (依 Pod 規格中的名稱) 展開為 Pod 規格內 JSON 格式的完整憑證規格。

  2. 一個 Validating Webhook,可確保所有 GMSA 參考都已獲得 Pod 服務帳戶的使用授權。

安裝上述 Webhook 和相關物件需要以下步驟

  1. 建立憑證金鑰組 (將用於允許 Webhook 容器與叢集通訊)

  2. 使用上述憑證安裝密鑰。

  3. 為核心 Webhook 邏輯建立部署。

  4. 建立參考部署的 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,然後轉換它的步驟

  1. 匯入 CredentialSpec 模組ipmo CredentialSpec.psm1

  2. 使用 New-CredentialSpec 以 JSON 格式建立憑證規格。若要建立名為 WebApp1 的 GMSA 憑證規格,請叫用 New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)

  3. 使用 Get-CredentialSpec 顯示 JSON 檔案的路徑。

  4. 將憑證規格檔案從 JSON 格式轉換為 YAML 格式,並套用必要的標頭欄位 apiVersionkindmetadatacredspec,使其成為可在 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 規格 (如上所述) 在叢集中套用時,會發生以下事件序列

  1. Mutating Webhook 解析並展開所有 GMSA 憑證規格資源的參考,以取得 GMSA 憑證規格的內容。

  2. Validating Webhook 確保與 Pod 相關聯的服務帳戶已獲得授權,可以對指定的 GMSA 憑證規格執行 use 動詞。

  3. 容器執行期使用指定的 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 件事

  1. Pod 可以連線到 DC
  2. DC 可以連線到 Pod
  3. 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 命令無錯誤退出。

最後修改時間:2024 年 7 月 10 日下午 2:05 PST:修正 gMSA 認證規格定義 (97bd20e5a9)