為 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 憑據規範引用:

  1. 一個變異 Webhook,用於將對 GMSA 的引用(透過 Pod 規範中的名稱)擴充套件為 Pod 規範中 JSON 格式的完整憑據規範。

  2. 一個驗證 Webhook,確保對 GMSA 的所有引用都被 Pod 服務賬戶授權使用。

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

  1. 建立證書金鑰對(用於允許 Webhook 容器與叢集通訊)。

  2. 使用上述證書安裝一個 Secret。

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

  4. 建立引用部署的驗證和變異 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,然後進行轉換的步驟:

  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 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 規範(如上所述)在叢集中應用時,會發生以下事件序列:

  1. 變異 Webhook 解析並展開對 GMSA 憑據規範資源的所有引用到 GMSA 憑據規範的內容中。

  2. 驗證 Webhook 確保與 Pod 關聯的服務賬戶被授權在指定的 GMSA 憑證規範上使用 use 動詞。

  3. 容器執行時使用指定的 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 來查詢你的域的根。

這將告訴我們三件事:

  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 無法使用憑證規範中指定的帳戶登入到域。你可以嘗試透過執行以下命令來修復安全通道:

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 命令無錯誤退出。

上次修改時間:2024 年 7 月 10 日太平洋標準時間下午 2:05:修復 gMSA 憑證規範定義 (97bd20e5a9)