Habilitación de cuentas de servicio administradas de grupo (GMSA) para los nodos de Windows Server en el clúster de Azure Kubernetes Service (AKS)

Una cuenta de servicio administrado de grupo (GMSA) es una cuenta de dominio administrada para varios servidores que proporciona administración automática de contraseñas, administración simplificada de nombres de entidad de seguridad de servicio (SPN) y la posibilidad de delegar la administración a otros administradores. Con Azure Kubernetes Service (AKS), puede habilitar GMSA en los nodos de Windows Server, lo que permite que los contenedores que se ejecutan en nodos de Windows Server se integren y administren mediante GMSA.

Requisitos previos

  • Kubernetes 1.19 o superior. Para comprobar la versión, consulte Buscar actualizaciones disponibles. Para actualizar la versión, consulte Actualización del clúster de AKS.
  • CLI de Azure, versión 2.35.0 o posterior. Ejecute az --version para encontrar la versión. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.
  • Identidades administradas habilitadas en su clúster de AKS.
  • Permisos para crear o actualizar una instancia de Azure Key Vault.
  • Permisos para configurar GMSA en el servicio Dominio de Active Directory o en la instancia local de Active Directory.
  • El controlador de dominio debe tener Active Directory Web Services habilitado y debe ser accesible en el puerto 9389 por el clúster de AKS.

Nota

Microsoft también proporciona un módulo de PowerShell diseñado específicamente para configurar gMSA en AKS. Para más información, vea gMSA en Azure Kubernetes Service.

Configuración de GMSA en el controlador de dominio de Active Directory

Para usar GMSA con AKS, necesita una credencial de usuario de dominio estándar a fin de acceder a la credencial de GMSA configurada en el controlador de dominio. Para configurar GMSA en el controlador de dominio, vea Introducción a las cuentas de servicio administradas de grupo. Para la credencial de usuario de dominio estándar, puede utilizar un usuario existente o crear uno, siempre que tenga acceso a la credencial de GMSA.

Importante

Debe usar el servicio Dominio de Active Directory o Active Directory local. En este momento, no puede usar Microsoft Entra ID para configurar GMSA con un clúster de AKS.

Almacene las credenciales de usuario de dominio estándar en Azure Key Vault

El clúster de AKS usa las credenciales de usuario de dominio estándar para acceder a las credenciales de GMSA desde el controlador de dominio. Para proporcionar un acceso seguro a esas credenciales para el clúster de AKS, debe almacenarlas en Azure Key Vault.

  1. Si aún no dispone de un almacén de claves de Azure, cree uno usando el comando az keyvault create.

    az keyvault create --resource-group myResourceGroup --name myGMSAVault
    
  2. Almacene la credencial de usuario de dominio estándar como secreto en su almacén de claves usando el comando az keyvault secret set. En el ejemplo siguiente se almacena la credencial de usuario de dominio con la clave GMSADomainUserCred en el almacén de claves myGMSAVault.

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

    Nota:

    Asegúrese de usar el nombre de dominio completo para el dominio.

Opcional: Uso de una red virtual personalizada con DNS personalizado

Debe configurar el controlador de dominio a través de DNS para que el clúster de AKS pueda acceder a él. Puede configurar la red y el DNS fuera del clúster de AKS para permitir que el clúster acceda al controlador de dominio. Como alternativa, puede usar Azure CNI para configurar una red virtual personalizada con un DNS personalizado en su clúster de AKS para proporcionar acceso a su controlador de dominio. Para más información, consulte Configuración de redes de Azure CNI en Azure Kubernetes Service (AKS).

Opcional: configurar más de un servidor DNS

Si quiere configurar más de un servidor DNS para GMSA de Windows en el clúster de AKS, no especifique --gmsa-dns-server ni v--gmsa-root-domain-name. En su lugar, puede agregar varios servidores DNS en la red virtual si selecciona DNS personalizado y agrega los servidores DNS.

Opcional: Uso de una identidad de kubelet propia para el clúster

Para proporcionar al clúster de AKS acceso al almacén de claves, la identidad del kubelet del clúster necesita acceso al almacén de claves. Cuando crea un clúster con la identidad administrada habilitada, se crea automáticamente de manera predeterminada una identidad kubelet.

Puede conceder acceso al almacén de claves para la identidad después de la creación del clúster o crear su propia identidad para usarla antes de la creación del clúster mediante los pasos siguientes:

  1. Cree una identidad de kubelet usando el comando az identity create.

    az identity create --name myIdentity --resource-group myResourceGroup
    
  2. Obtenga el identificador de la identidad con el comando az identity list y establézcalo en una variable denominada MANAGED_ID.

    MANAGED_ID=$(az identity list --query "[].id" -o tsv)
    
  3. Conceda a la identidad acceso a su almacén de claves usando el comando az keyvault set-policy.

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

Habilitar GMSA en un nuevo clúster de AKS

  1. Cree credenciales de administrador para usarlas durante la creación del clúster. Los comandos siguientes le solicitan un nombre de usuario y lo establecen en WINDOWS_USERNAME para su uso en un comando posterior.

    echo "Please enter the username to use as administrator credentials for Windows Server nodes on your cluster: " && read WINDOWS_USERNAME 
    
  2. Cree un clúster de AKS mediante el comando az aks create con los parámetros siguientes:

    • --enable-managed-identity: habilita la identidad administrada para el clúster.
    • --enable-windows-gmsa: habilita GMSA para el clúster.
    • --gmsa-dns-server: la dirección IP del servidor DNS.
    • --gmsa-root-domain-name: nombre de dominio raíz del servidor 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
    

    Nota:

    • Si está usando una red virtual personalizada, deberá especificar el identificador de la red virtual usando el parámetro vnet-subnet-id, y puede que necesite agregar también los parámetros docker-bridge-address, dns-service-ip y service-cidr dependiendo de su configuración.

    • Si ha creado una identidad propia para la identidad de kubelet, use el parámetro assign-kubelet-identity para especificar la identidad.

    • Al especificar los parámetros --gmsa-dns-server y --gmsa-root-domain-name, se agrega una regla de reenvío DNS a ConfigMap kube-system/coredns. Esta regla reenvía las solicitudes DNS para $ROOT_DOMAIN_NAME de los pods a $DNS_SERVER.

      $ROOT_DOMAIN_NAME:53 {
          errors
          cache 30
          log
          forward . $DNS_SERVER
      }
      
  3. Agregue un grupo de nodos de Windows Server mediante el comando az aks nodepool add.

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

Habilitación de GMSA en un clúster existente

  • Habilite GMSA en un clúster existente con nodos de Windows Server e identidades administradas habilitadas mediante el comando az aks update.

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

Concesión de acceso al almacén de claves para la identidad de kubelet

Nota:

Omita este paso si proporcionó su propia identidad para la identidad de kubelet.

  • Conceda acceso al almacén de claves para la identidad de kubelet mediante el comando az keyvault set-policy.

    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
    

Instalación de especificaciones de credenciales de GMSA

  1. Para configurar kubectl para conectarse a su clúster de Kubernetes, use el comando az aks get-credentials.

    az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
    
  2. Cree un nuevo YAML denominado gmsa-spec.yaml y pegue el código YAML siguiente. Asegúrese de reemplazar los marcadores de posición por sus propios valores.

    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
    

Nota:

AKS ha actualizado apiVersion de GMSACredentialSpec de windows.k8s.io/v1alpha1 a windows.k8s.io/v1 en la versión v20230903.

  1. Cree un nuevo YAML denominado gmsa-role.yaml y pegue el código YAML siguiente.

    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. Cree un nuevo YAML denominado gmsa-role-binding.yaml y pegue el código YAML siguiente.

    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. Aplique los cambios de gmsa-spec.yaml, gmsa-role.yaml y gmsa-role-binding.yaml usando el comando kubectl apply.

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

Comprobación de la instalación de GMSA

  1. Cree un nuevo YAML denominado gmsa-demo.yaml y pegue el código YAML siguiente.

    ---
    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. Aplique los cambios de gmsa-demo.yaml mediante el comando kubectl apply.

    kubectl apply -f gmsa-demo.yaml
    
  3. Obtenga la dirección IP de la aplicación de ejemplo mediante el comando kubectl get service.

    kubectl get service gmsa-demo --watch
    

    En un primer momento, el parámetro EXTERNAL-IP del servicio gmsa-demo aparece como pendiente:

    NAME               TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    gmsa-demo          LoadBalancer   10.0.37.27   <pending>     80:30572/TCP   6s
    
  4. Cuando la dirección EXTERNAL-IPcambie de pendiente a una dirección IP pública real, use CTRL-C para detener el proceso de inspección de kubectl.

    En la salida del ejemplo siguiente se muestra una dirección IP pública válida asignada al servicio:

    gmsa-demo  LoadBalancer   10.0.37.27   EXTERNAL-IP   80:30572/TCP   2m
    
  5. Abra un explorador web a la dirección IP externa del servicio gmsa-demo.

  6. Autentíquese con $NETBIOS_DOMAIN_NAME\$AD_USERNAME y la contraseña, y confirme que ve Authenticated as $NETBIOS_DOMAIN_NAME\$AD_USERNAME, Type of Authentication: Negotiate.

Deshabilitación de GMSA en un clúster existente

  • Deshabilite GMSA en un clúster existente con nodos de Windows Server mediante el comando az aks update.

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

Nota:

Puede volver a habilitar GMSA en un clúster existente mediante el comando az aks update.

Solucionar problemas

No se solicita autenticación al cargar la página

Si se carga la página, pero no se le pide que se autentique, use el comando kubectl logs POD_NAME para mostrar los registros del pod y comprobar que ve que IIS con autenticación está listo.

Nota:

Los contenedores de Windows no mostrarán registros en kubectl de forma predeterminada. Para permitir que los contenedores de Windows muestren los registros, debe insertar la herramienta Monitor de registros en la imagen de Windows. Para más información, consulte Herramientas de contenedores de Windows.

Tiempo de espera de conexión al intentar cargar la página

Si recibe un tiempo de espera de conexión al intentar cargar la página, verifique que la aplicación de muestra se está ejecutando usando el comando kubectl get pods --watch. A veces, la dirección IP externa del servicio de aplicación de ejemplo está disponible antes de que se ejecute el pod de la aplicación de ejemplo.

El pod no se inicia y se muestra un error winapi en los eventos del pod

Si el pod no se inicia después de ejecutar el comando kubectl get pods --watch y esperar varios minutos, use el comando kubectl describe pod POD_NAME. Si ve un error winapi en los eventos de pod, es probable que se trate de un error en la configuración de la especificación de credenciales de GMSA. Compruebe que todos los valores de reemplazo de gmsa-spec.yaml sean correctos, vuelva a ejecutar kubectl apply -f gmsa-spec.yaml y vuelva a implementar la aplicación de ejemplo.

Pasos siguientes