為 Azure Kubernetes Service (AKS) 叢集上的 Windows 伺服器節點,啟用群組受管理的服務帳戶 (GMSA)

群組受管理的服務帳戶 (GMSA) 是多個伺服器的受控網域帳戶,可提供自動密碼管理、簡化的服務主體名稱 (SPN) 管理,以及將管理委派給其他管理員的能力。 藉由 Azure Kubernetes Service (AKS),您可以在 Windows 伺服器節點上啟用 GMSA,並可讓 Windows 伺服器節點上執行的容器,能與 GMSA 整合並透過其管理。

必要條件

  • Kubernetes 1.19 或更新版本。 若要檢查您的版本,請參閱檢查是否有可用的升級。 若要升級您的版本,請參閱升級 AKS 叢集
  • Azure CLI 2.35.0 版或更新版本。 執行 az --version 以尋找版本。 如果您需要安裝或升級,請參閱安裝 Azure CLI
  • 在您的 AKS 叢集上啟用受控識別
  • 建立或更新 Azure Key Vault 的權限。
  • 在 Active Directory 網域服務,或在內部部署 Active Directory 上,設定 GMSA 的權限。
  • 網域控制站必須已經啟用 Active Directory Web 服務,而且必須可透過 AKS 叢集,於連接埠 9389 上連線。

注意

Microsoft 也提供專門建置的 PowerShell 模組,以在 AKS 上設定 gMSA。 如需詳細資訊,請參閱 Azure Kubernetes Service上的 gMSA

在 Active Directory 網域控制站上設定 GMSA

若要透過 AKS 使用 GMSA,您需要標準網域使用者認證,才能存取網域控制站上設定的 GMSA 認證。 若要在網域控制站上設定 GMSA,請參閱開始使用群組受控服務帳戶。 針對標準網域使用者認證,只要其具有 GMSA 認證的存取權,您即可使用現有的使用者,或建立新的使用者。

重要

您必須使用 Active Directory 網域 Service 或內部部署 Active Directory。 此時,您無法使用 Microsoft Entra ID 設定 GMSA 與 AKS 叢集。

將標準網域使用者認證,儲存於 Azure Key Vault

您的 AKS 叢集會使用標準網域使用者認證,從網域控制站存取 GMSA 認證。 若要為 AKS 叢集提供這些認證的安全存取,您應該將這些儲存在 Azure Key Vault 中。

  1. 如果您還沒有 Azure Key Vault,請使用 az keyvault create 命令建立一個。

    az keyvault create --resource-group myResourceGroup --name myGMSAVault
    
  2. 使用 az keyvault secret set 命令將標準網域使用者認證,儲存為您金鑰保存庫中的祕密。 下列範例會將網域使用者認證與金鑰 GMSADomainUserCred,儲存在 myGMSAVault 金鑰保存庫中。

    az keyvault secret set --vault-name myGMSAVault --name "GMSADomainUserCred" --value "$Domain\\$DomainUsername:$DomainUserPassword"
    

    注意

    務必使用網域的完整網域名稱。

選用:透過自訂 DNS,使用自訂 VNet

您必須透過 DNS 設定域控制器,才能由 AKS 叢集連線。 您可以在 AKS 叢集外部設定網路和 DNS,以允許叢集存取網域控制站。 或者,您可以使用 Azure CNI 對於 AKS 叢集設定具有自訂 DNS 的自訂 VNet,以提供網域控制站的存取權。 如需詳細資訊,請參閱在 Azure Kubernetes Service (AKS) 中設定 Azure CNI 網路

選用:設定多個 DNS 伺服器

如果您想要在 AKS 叢集中為 Windows GMSA 設定多個 DNS 伺服器,請勿指定 --gmsa-dns-serverv--gmsa-root-domain-name。 不過,您可以選取 [自訂 DNS] 並新增 DNS 伺服器,在 VNet 中新增多個 DNS 伺服器。

選用:針對您的叢集,使用您自己的 kubelet 身分識別

若要提供金鑰保存庫的 AKS 叢集存取權,叢集 kubelet 身分識別需要存取您的金鑰保存庫。 依預設,您建立已啟用受控識別的叢集時,將會自動建立 kubelet 身分識別。

您可以在叢集建立之後,將金鑰保存庫的存取權授與身分識別,也可以使用下列步驟在叢集建立的前建立自己的身分識別:

  1. 使用 az identity create 命令建立 kubelet 身分識別。

    az identity create --name myIdentity --resource-group myResourceGroup
    
  2. 使用 az identity list 命令取得身分識別的識別碼,並將其設定為名為 MANAGED_ID 的變數。

    MANAGED_ID=$(az identity list --query "[].id" -o tsv)
    
  3. 使用 az keyvault set-policy 命令授與金鑰保存庫的身分識別存取權。

    az keyvault set-policy --name "myGMSAVault" --object-id $MANAGED_ID --secret-permissions get
    

在新的 AKS 叢集上啟用 GMSA

  1. 建立系統管理員認證,以便在叢集建立期間使用。 下列命令會提示您輸入使用者名稱,並將此設定為 WINDOWS_USERNAME,以供稍後的命令使用。

    echo "Please enter the username to use as administrator credentials for Windows Server nodes on your cluster: " && read WINDOWS_USERNAME 
    
  2. 使用 az aks create 命令搭配下列參數來建立 AKS 叢集:

    • --enable-managed-identity:啟用叢集的受控識別。
    • --enable-windows-gmsa:啟用叢集的 GMSA。
    • --gmsa-dns-server:DNS 伺服器的 IP 位址。
    • --gmsa-root-domain-name:DNS 伺服器的根功能變數名稱。
    DNS_SERVER=<IP address of DNS server>
    ROOT_DOMAIN_NAME="contoso.com"
    
    az aks create \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --vm-set-type VirtualMachineScaleSets \
        --network-plugin azure \
        --load-balancer-sku standard \
        --windows-admin-username $WINDOWS_USERNAME \
        --enable-managed-identity \
        --enable-windows-gmsa \
        --gmsa-dns-server $DNS_SERVER \
        --gmsa-root-domain-name $ROOT_DOMAIN_NAME
    

    注意

    • 如果您使用自訂 VNet,您必須使用 vnet-subnet-id 參數來指定 VNet 識別元,而且您可能需要根據組態新增 docker-bridge-addressdns-service-ipservice-cidr 參數。

    • 如果您為 kubelet 身分識別建立自己的身分識別,請使用 assign-kubelet-identity 參數指定您的身分識別。

    • 您指定 --gmsa-dns-server--gmsa-root-domain-name 參數時,DNS 轉寄規則會新增至 kube-system/coredns ConfigMap。 此規則會將 $ROOT_DOMAIN_NAME 的 DNS 要求從 Pod 轉送至 $DNS_SERVER

      $ROOT_DOMAIN_NAME:53 {
          errors
          cache 30
          log
          forward . $DNS_SERVER
      }
      
  3. 使用 az aks nodepool add 命令新增 Windows Server 節點集區。

    az aks nodepool add \
        --resource-group myResourceGroup \
        --cluster-name myAKSCluster \
        --os-type Windows \
        --name npwin \
        --node-count 1
    

在現有叢集上啟用 GMSA

  • 在現有叢集上啟用 GMSA,並使用 az aks update 命令啟用 Windows Server 節點和受控識別。

    az aks update \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --enable-windows-gmsa \
        --gmsa-dns-server $DNS_SERVER \
        --gmsa-root-domain-name $ROOT_DOMAIN_NAME
    

為 kubelet 身分識別授與金鑰保存庫的存取權

注意

如果您已為 kubelet 身分識別提供自己的身分識別,請略過此步驟。

  • 使用 az keyvault set-policy 命令,為 kubelet 身分識別授與金鑰保存庫的存取權。

    MANAGED_ID=$(az aks show -g myResourceGroup -n myAKSCluster --query "identityProfile.kubeletidentity.objectId" -o tsv)
    az keyvault set-policy --name "myGMSAVault" --object-id $MANAGED_ID --secret-permissions get
    

安裝 GMSA cred 規格

  1. 使用 az aks get-credentials 命令,設定 kubectl 連線到 Kubernetes 叢集。

    az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
    
  2. 建立名為 gmsa-spec.yaml 的新 YAML,並貼上下列 YAML。 請務必將預留位置取代為您自己的值。

    apiVersion: windows.k8s.io/v1
    kind: GMSACredentialSpec
    metadata:
      name: aks-gmsa-spec  # This name can be changed, but it will be used as a reference in the pod spec
    credspec:
      ActiveDirectoryConfig:
        GroupManagedServiceAccounts:
        - Name: $GMSA_ACCOUNT_USERNAME
          Scope: $NETBIOS_DOMAIN_NAME
        - Name: $GMSA_ACCOUNT_USERNAME
          Scope: $DNS_DOMAIN_NAME
        HostAccountConfig:
          PluginGUID: '{CCC2A336-D7F3-4818-A213-272B7924213E}'
          PortableCcgVersion: "1"
          PluginInput: "ObjectId=$MANAGED_ID;SecretUri=$SECRET_URI"  # SECRET_URI takes the form https://$akvName.vault.azure.net/secrets/$akvSecretName
      CmsPlugins:
     - ActiveDirectory
      DomainJoinConfig:
        DnsName: $DNS_DOMAIN_NAME
        DnsTreeName: $DNS_ROOT_DOMAIN_NAME
        Guid:  $AD_DOMAIN_OBJECT_GUID
        MachineAccountName: $GMSA_ACCOUNT_USERNAME
        NetBiosName: $NETBIOS_DOMAIN_NAME
        Sid: $GMSA_SID
    

注意

AKS 已在 v20230903 版本中將 GMSACredentialSpecapiVersionwindows.k8s.io/v1alpha1 升級為 windows.k8s.io/v1

  1. 建立名為 gmsa-role.yaml 的新 YAML,並貼上下列 YAML。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: aks-gmsa-role
    rules:
    - apiGroups: ["windows.k8s.io"]
      resources: ["gmsacredentialspecs"]
      verbs: ["use"]
      resourceNames: ["aks-gmsa-spec"]
    
  2. 建立名為 gmsa-role-binding.yaml 的新 YAML,並貼上下列 YAML。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: allow-default-svc-account-read-on-aks-gmsa-spec
      namespace: default
    subjects:
    - kind: ServiceAccount
      name: default
      namespace: default
    roleRef:
      kind: ClusterRole
      name: aks-gmsa-role
      apiGroup: rbac.authorization.k8s.io
    
  3. 使用 kubectl apply 命令以套用 gmsa-spec.yamlgmsa-role.yaml,以及 gmsa-role-binding.yaml 的變更。

    kubectl apply -f gmsa-spec.yaml
    kubectl apply -f gmsa-role.yaml
    kubectl apply -f gmsa-role-binding.yaml
    

確認 GMSA 安裝

  1. 建立名為 gmsa-demo.yaml 的新 YAML,並貼上下列 YAML。

    ---
    kind: ConfigMap
    apiVersion: v1
    metadata:
      labels:
       app: gmsa-demo
      name: gmsa-demo
      namespace: default
    data:
      run.ps1: |
       $ErrorActionPreference = "Stop"
    
       Write-Output "Configuring IIS with authentication."
    
       # Add required Windows features, since they are not installed by default.
       Install-WindowsFeature "Web-Windows-Auth", "Web-Asp-Net45"
    
       # Create simple ASP.NET page.
       New-Item -Force -ItemType Directory -Path 'C:\inetpub\wwwroot\app'
       Set-Content -Path 'C:\inetpub\wwwroot\app\default.aspx' -Value 'Authenticated as <B><%=User.Identity.Name%></B>, Type of Authentication: <B><%=User.Identity.AuthenticationType%></B>'
    
       # Configure IIS with authentication.
       Import-Module IISAdministration
       Start-IISCommitDelay
       (Get-IISConfigSection -SectionPath 'system.webServer/security/authentication/windowsAuthentication').Attributes['enabled'].value = $true
       (Get-IISConfigSection -SectionPath 'system.webServer/security/authentication/anonymousAuthentication').Attributes['enabled'].value = $false
       (Get-IISServerManager).Sites[0].Applications[0].VirtualDirectories[0].PhysicalPath = 'C:\inetpub\wwwroot\app'
       Stop-IISCommitDelay
    
       Write-Output "IIS with authentication is ready."
    
       C:\ServiceMonitor.exe w3svc
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: gmsa-demo
      name: gmsa-demo
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gmsa-demo
      template:
        metadata:
          labels:
            app: gmsa-demo
        spec:
          securityContext:
            windowsOptions:
              gmsaCredentialSpecName: aks-gmsa-spec
          containers:
          - name: iis
            image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
            imagePullPolicy: IfNotPresent
            command:
             - powershell
            args:
              - -File
              - /gmsa-demo/run.ps1
            volumeMounts:
              - name: gmsa-demo
                mountPath: /gmsa-demo
          volumes:
          - configMap:
              defaultMode: 420
              name: gmsa-demo
            name: gmsa-demo
          nodeSelector:
            kubernetes.io/os: windows
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: gmsa-demo
      name: gmsa-demo
      namespace: default
    spec:
      ports:
      - port: 80
        targetPort: 80
      selector:
        app: gmsa-demo
      type: LoadBalancer
    
  2. 使用 kubectl apply 命令從 gmsa-demo.yaml 套用變更。

    kubectl apply -f gmsa-demo.yaml
    
  3. 使用 kubectl get service 命令取得範例應用程式的 IP 位址。

    kubectl get service gmsa-demo --watch
    

    一開始,gmsa-demo 服務的 EXTERNAL-IP 會顯示為擱置中

    NAME               TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    gmsa-demo          LoadBalancer   10.0.37.27   <pending>     80:30572/TCP   6s
    
  4. EXTERNAL-IP 位址從擱置中變成實際的公用 IP 位址時,請使用 CTRL-C 停止 kubectl 監看式流程。

    下列範例輸出顯示指派給服務的有效公用 IP 位址:

    gmsa-demo  LoadBalancer   10.0.37.27   EXTERNAL-IP   80:30572/TCP   2m
    
  5. 開啟網頁瀏覽器並前往 gmsa-demo 服務的外部 IP 位址。

  6. 使用 $NETBIOS_DOMAIN_NAME\$AD_USERNAME 和密碼進行驗證,並確認您看到 Authenticated as $NETBIOS_DOMAIN_NAME\$AD_USERNAME, Type of Authentication: Negotiate

在現有叢集上停用 GMSA

  • 使用 az aks update 命令對於 Windows Server 節點在現有叢集上停用 GMSA。

    az aks update \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --disable-windows-gmsa 
    

注意

您可以使用 az aks update 命令,在現有的叢集 上重新啟用 GMSA。

疑難排解

載入頁面時不會提示驗證

如果頁面載入,但並未提示您進行驗證,請使用 kubectl logs POD_NAME 命令顯示 Pod 的記錄,並確認您看到「IIS 驗證已就緒」

注意

Windows 容器預設不會在 kubectl 上顯示記錄。 若要讓 Windows 容器顯示記錄,您必須在 Windows 映像上內嵌記錄監視器工具。 如需詳細資訊,請參閱「Windows Container Tools」

嘗試載入頁面時,發生連線逾時

如果您在嘗試載入頁面時收到連線逾時,請確認範例應用程式是使用 kubectl get pods --watch 命令執行。 有時候範例應用程式服務的外部 IP 位址,可在執行範例應用程式 Pod 之前取得。

Pod 無法啟動,而 Pod 事件中會顯示 winapi 錯誤

如果您的 Pod 在執行 kubectl get pods --watch 命令並等候數分鐘後未啟動,請使用 kubectl describe pod POD_NAME 命令。 如果您在 Pod 事件中看到 winapi 錯誤,則可能是 GMSA cred 規格設定中的錯誤。 確認 gmsa-spec.yaml 中的所有取代數值都正確、重新執行 kubectl apply -f gmsa-spec.yaml,然後重新部署應用程式範例。

下一步