Usa Workload Identity

En este documento, se muestra cómo habilitar y configurar Workload Identity en los clústeres de Google Kubernetes Engine (GKE). Workload Identity permite que las cargas de trabajo de los clústeres de GKE actúen en nombre de las cuentas de servicio de la administración de identidades y accesos (IAM) para acceder a los servicios de Google Cloud.

Para obtener más información sobre cómo funciona Workload Identity, consulta Workload Identity.

Limitaciones

  • GKE crea un grupo de identidades de carga de trabajo fijo para cada proyecto de Google Cloud, con el formato PROJECT_ID.svc.id.goog.

  • Workload Identity reemplaza la necesidad de usar ocultamiento de metadatos. Workload Identity también protege los metadatos sensibles protegidos con la ocultación de metadatos.

  • Cuando GKE habilita el servidor de metadatos de GKE en un grupo de nodos, los Pods ya no pueden acceder al servidor de metadatos de Compute Engine. En cambio, el servidor de metadatos de GKE intercepta las solicitudes realizadas de estos Pods a los extremos de metadatos, excepto los Pods que se ejecutan en la red del host.

  • No se puede usar Workload Identity en los Pods que se ejecutan en la red del host. Las solicitudes realizadas desde estos pods a los extremos de metadatos se enrutan al servidor de metadatos de Compute Engine.

  • El servidor de metadatos de GKE toma unos segundos en comenzar a aceptar solicitudes en un Pod recién creado. Por lo tanto, los intentos de autenticación mediante Workload Identity en los primeros segundos de la vida del Pod podrían fallar. Volver a intentar la llamada resolverá el problema. Si quieres obtener más información, revisa la sección de solución de problemas que se encuentra más abajo.

  • Los agentes integrados de supervisión y registro de GKE seguirán usando la cuenta de servicio del nodo.

  • Workload Identity requiere una configuración manual para Cloud Run for Anthos a fin de continuar lanzando métricas de solicitudes.

  • Workload Identity instala ip-masq-agent si el clúster se crea sin la marca --disable-default-snat.

  • Workload Identity establece un límite de 200 conexiones al servidor de metadatos de GKE para cada nodo a fin de evitar problemas de memoria. Es posible que experimentes tiempos de espera si los nodos exceden este límite.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Asegúrate de que habilitaste la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Asegúrate de que instalaste el SDK de Cloud.
  • Establece la configuración predeterminada de la herramienta de línea de comandos de gcloud para tu proyecto mediante uno de los siguientes métodos:
    • Usa gcloud init si deseas ver una explicación sobre cómo configurar los valores predeterminados del proyecto.
    • Usa gcloud config para configurar el ID, la zona y la región del proyecto de manera individual.

    gcloud init

    1. Ejecuta gcloud init y sigue las instrucciones:

      gcloud init

      Si usas SSH en un servidor remoto, usa la marca --console-only para evitar que el comando abra un navegador:

      gcloud init --console-only
    2. Sigue las instrucciones para autorizar a la herramienta de gcloud a usar tu cuenta de Google Cloud.
    3. Crea una configuración nueva o selecciona una existente.
    4. Elige un proyecto de Google Cloud.
    5. Elige una zona de Compute Engine predeterminada.
    6. Elige una región de Compute Engine predeterminada.

    gcloud config

    1. Establece tu ID del proyecto predeterminado:
      gcloud config set project PROJECT_ID
    2. Configura la región de Compute Engine predeterminada (por ejemplo, us-central1):
      gcloud config set compute/region COMPUTE_REGION
    3. Configura la zona de Compute Engine predeterminada (por ejemplo, us-central1-c):
      gcloud config set compute/zone COMPUTE_ZONE
    4. Actualiza gcloud a la versión más reciente:
      gcloud components update

    Cuando configuras las ubicaciones predeterminadas, puedes evitar errores en la herramienta gcloud como el siguiente: One of [--zone, --region] must be supplied: Please specify location.

Habilita Workload Identity en un clúster

Puedes habilitar Workload Identity en un clúster estándar de GKE nuevo o existente con la herramienta de gcloud. De forma predeterminada, Workload Identity está habilitada en clústeres de Autopilot de GKE.

  1. Asegúrate de que habilitaste la API de credenciales de la cuenta de servicio de IAM.

    Habilitar la API de credenciales IAM

  2. Para crear un clúster nuevo con Workload Identity habilitado, usa el siguiente comando:

    gcloud container clusters create CLUSTER_NAME \
        --workload-pool=PROJECT_ID.svc.id.goog
    

    Reemplaza los siguientes elementos:

    • CLUSTER_NAME: Es el nombre de tu clúster.
    • PROJECT_ID: El ID del proyecto de Google Cloud.
  3. Para habilitar Workload Identity en un clúster existente, modifica el clúster con el siguiente comando:

    gcloud container clusters update CLUSTER_NAME \
        --workload-pool=PROJECT_ID.svc.id.goog
    

    Los grupos de nodos existentes no se ven afectados; los grupos de nodos nuevos se establecen de forma predeterminada como --workload-metadata=GKE_METADATA.

Migra aplicaciones a Workload Identity

Selecciona la estrategia de migración ideal para tu entorno. Los grupos de nodos se pueden migrar en el lugar o puedes crear grupos de nodos nuevos con Workload Identity habilitada. Te recomendamos crear grupos de nodos nuevos si también necesitas modificar la aplicación para que sea compatible con esta característica.

Agrega un grupo de nodos nuevo al clúster con Workload Identity habilitado y migra cargas de trabajo a ese grupo de forma manual. Esto tiene éxito solo si Workload Identity está habilitada en el clúster.

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --workload-metadata=GKE_METADATA

Si un clúster tiene Workload Identity habilitada, puedes inhabilitarla de forma selectiva en un grupo de nodos en particular si especificas --workload-metadata=GCE_METADATA explícitamente. Para obtener más información, consulta Protege metadatos del clúster.

Opción 2: modificación del grupo de nodos

Modifica un grupo de nodos existente para usar el servidor de metadatos de GKE. Esta actualización tiene éxito solo si Workload Identity está habilitada en el clúster. La modificación inmediata del grupo de nodos habilita Workload Identity para las cargas de trabajo implementadas en el grupo de nodos. Este cambio evita que las cargas de trabajo usen la cuenta de servicio de Compute Engine y se debe implementar con mucho cuidado.

gcloud container node-pools update NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --workload-metadata=GKE_METADATA

Autentica en Google Cloud

En esta sección, se explica cómo una aplicación puede autenticarse en Google Cloud mediante Workload Identity. Asigna una cuenta de servicio de Kubernetes a la aplicación y configúrala para que actúe como una cuenta de servicio de IAM.

  1. Configura kubectl para comunicarse con el clúster:

    gcloud container clusters get-credentials CLUSTER_NAME
    

    Reemplaza CLUSTER_NAME por el nombre del clúster que creaste en el paso anterior.

  2. Como la mayoría de los otros recursos, las cuentas de servicio de Kubernetes se alojan en un espacio de nombres. Crea el espacio de nombres para usar en la cuenta de servicio de Kubernetes.

    kubectl create namespace K8S_NAMESPACE
    
  3. Crea la cuenta de servicio de Kubernetes para usar en la aplicación:

    kubectl create serviceaccount KSA_NAME \
        --namespace K8S_NAMESPACE
    

    Reemplaza lo siguiente:

    • KSA_NAME: Es el nombre de tu cuenta de servicio de Kubernetes nueva.
    • K8S_NAMESPACE: El nombre del espacio de nombres de Kubernetes que creaste en el paso anterior.
  4. Configura tu aplicación para usar la cuenta de servicio de Kubernetes:

    spec:
      serviceAccountName: KSA_NAME
    
  5. Crea una cuenta de servicio de IAM para tu aplicación o usa una cuenta de servicio de IAM existente en su lugar. Puedes usar cualquier cuenta de servicio de IAM en cualquier proyecto de tu organización. En Config Connector, aplica el objeto IAMServiceAccount para la cuenta de servicio elegida.

    gcloud

    Para crear una nueva cuenta de servicio de IAM con la herramienta de gcloud, ejecuta el siguiente comando.

    gcloud iam service-accounts create GSA_NAME
    

    Reemplaza GSA_NAME con el nombre de la nueva cuenta de servicio de IAM.

    Config Connector

    Para usar una cuenta de servicio de IAM nueva o existente con Config Connector, aplica el siguiente archivo de configuración.

    Nota: En este paso, se necesita Config Connector. Sigue las instrucciones de instalación para instalar Config Connector en el clúster.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMServiceAccount
    metadata:
      name: [GSA_NAME]
    spec:
      displayName: [GSA_NAME]
    Para implementar este manifiesto, descárgalo en tu equipo como service-account.yaml.

    Usa kubectl para aplicar el manifiesto:

    kubectl apply -f service-account.yaml
    

    Para obtener información sobre la autorización de cuentas de servicio de IAM a fin de acceder a las API de Google Cloud, consulta la página Comprende las cuentas de servicio.

  6. Asegúrate de que tu cuenta de servicio de Google tenga las funciones de IAM que necesitas. Puedes otorgar funciones adicionales con el siguiente comando:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:GSA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
        --role "ROLE_NAME"
    

    Reemplaza lo siguiente:

    • PROJECT_ID: Es el ID de tu proyecto de Google Cloud.
    • GSA_NAME: es el nombre de tu cuenta de servicio de Google.
    • ROLE_NAME: es la función de IAM que se asignará a la cuenta de servicio, como roles/spanner.viewer.
  7. Para permitir que la cuenta de servicio de Kubernetes actúe en nombre de la cuenta de servicio de Google, crea una vinculación de política de IAM entre las dos. Esta vinculación permite que la cuenta de servicio de Kubernetes actúe como la cuenta de servicio de IAM.

    gcloud

    gcloud iam service-accounts add-iam-policy-binding GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]"
    

    Config Connector

    Nota: En este paso, se necesita Config Connector. Sigue las instrucciones de instalación para instalar Config Connector en el clúster.

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicy
    metadata:
      name: iampolicy-workload-identity-sample
    spec:
      resourceRef:
        apiVersion: iam.cnrm.cloud.google.com/v1beta1
        kind: IAMServiceAccount
        name: [GSA_NAME]
      bindings:
        - role: roles/iam.workloadIdentityUser
          members:
            - serviceAccount:[PROJECT_ID].svc.id.goog[[K8S_NAMESPACE]/[KSA_NAME]]
    Para implementar este manifiesto, descárgalo en tu equipo como policy-binding.yaml. Reemplaza GSA_NAME, PROJECT_ID, K8S_NAMESPACE y KSA_NAME por los valores para tu entorno. Luego, ejecuta lo siguiente:

    kubectl apply -f policy-binding.yaml
    
  8. Agrega la anotación iam.gke.io/gcp-service-account=GSA_NAME@PROJECT_ID a la cuenta de servicio de Kubernetes mediante la dirección de correo electrónico de la cuenta de servicio de IAM.

    kubectl

    kubectl annotate serviceaccount KSA_NAME \
        --namespace K8S_NAMESPACE \
        iam.gke.io/gcp-service-account=GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    

    yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        iam.gke.io/gcp-service-account:GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
      name: KSA_NAME
      namespace: K8S_NAMESPACE
    
  9. Para verificar que las cuentas de servicio estén configuradas de forma correcta, crea un Pod con la cuenta de servicio de Kubernetes que ejecute la imagen de contenedor específica del SO y, a continuación, conéctate a ella con una sesión interactiva.

    Para los nodos de Linux

    1. Crea un Pod con la cuenta de servicio de Kubernetes que ejecuta la imagen de contenedor cloud-sdk:

      Guarda la siguiente configuración como wi-test.yaml.

      apiVersion: v1
      kind: Pod
      metadata:
        name: workload-identity-test
        namespace: K8S_NAMESPACE
      spec:
        containers:
        - image: google/cloud-sdk:slim
          name: workload-identity-test
          command: ["sleep","infinity"]
        serviceAccountName: KSA_NAME
      

      Crea un Pod:

      kubectl apply -f wi-test.yaml
      

      Abre una sesión interactiva en el Pod:

      kubectl exec -it workload-identity-test \
          --namespace K8S_NAMESPACE -- /bin/bash
      

      La imagen google/cloud-sdk incluye la herramienta de línea de comandos de gcloud, que es una manera conveniente de usar las API de Google Cloud. La descarga de la imagen puede tomar un tiempo.

    2. Ahora estás conectado a un shell interactivo dentro del Pod creado. Ejecuta el siguiente comando dentro del Pod:

      curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/
      

      Si las cuentas de servicio están configuradas de forma correcta, la dirección de correo electrónico de la cuenta de servicio de IAM aparece como la identidad activa (y única). Esto demuestra que, de forma predeterminada, el pod actúa como la autoridad de la cuenta de servicio de IAM cuando se llama a las API de Google Cloud.

    Para los nodos de Windows Server

    1. Crea un Pod con la cuenta de servicio de Kubernetes que ejecuta la imagen de contenedor servercore:

      apiVersion: v1
      kind: Pod
      metadata:
        name: workload-identity-test
        namespace: K8S_NAMESPACE
      spec:
        containers:
        - image: IMAGE_NAME
          name: workload-identity-test
          command: ["powershell.exe", "sleep", "3600"]
        serviceAccountName: KSA_NAME
        nodeSelector:
          kubernetes.io/os: windows
          cloud.google.com/gke-os-distribution: windows_ltsc
      

      Reemplaza IMAGE_NAME por uno de los siguientes valores de imagen de contenedor servercore:

      Imagen de nodo de Windows Server Imagen de contenedor servercore
      WINDOWS_LTSC,
      WINDOWS_LTSC_CONTAINERD
      mcr.microsoft.com/windows/servercore:ltsc2019
      WINDOWS_SAC,
      WINDOWS_SAC_CONTAINERD
      Verifica la asignación de versiones entre la versión de nodo de GKE y la versión de Windows SAC. En la versión 1909 de Windows Server, especifica mcr.microsoft.com/windows/servercore:1909. De lo contrario, especifica mcr.microsoft.com/windows/servercore:20H2.

      Abre una sesión interactiva en el Pod:

      kubectl exec -it workload-identity-test \
          --namespace K8S_NAMESPACE -- powershell
      
    2. Ahora estás conectado a un shell interactivo dentro del Pod creado. Ejecuta el siguiente comando dentro del Pod:

      Invoke-WebRequest  -Headers @{"Metadata-Flavor"="Google"} -Uri  http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email  -UseBasicParsing
      

      Si las cuentas de servicio están configuradas de forma correcta, la dirección de correo electrónico de la cuenta de servicio de IAM aparece como la identidad activa (y única). Esto demuestra que, de forma predeterminada, el Pod usa la autoridad de la cuenta de servicio de IAM cuando llama a las API de Google Cloud.

Usa Workload Identity desde el código

La autenticación en los servicios de Google Cloud desde tu código es el mismo proceso que la autenticación mediante el servidor de metadatos de Compute Engine. Cuando usas Workload Identity, las solicitudes al servidor de metadatos de la instancia se enrutan al servidor de metadatos de GKE. El código existente que se autentica mediante el servidor de metadatos de la instancia (como el código que usa las bibliotecas cliente de Google Cloud) debería funcionar sin modificaciones.

Revoca acceso

  1. Revoca el acceso a la cuenta de servicio de IAM:

    gcloud

    gcloud iam service-accounts remove-iam-policy-binding GSA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]"
    

    Reemplaza lo siguiente:

    • PROJECT_ID: Es el ID del proyecto del clúster de GKE.
    • K8S_NAMESPACE: El nombre del espacio de nombres de Kubernetes en el que se encuentra la cuenta de servicio de Kubernetes.
    • KSA_NAME: El nombre de la cuenta de servicio de Kubernetes a la que se le revocará el acceso.
    • GSA_NAME: Es el nombre de la cuenta de servicio de IAM.
    • GSA_PROJECT_ID: Es el ID del proyecto de la cuenta de servicio de IAM.

    Config Connector

    Si usaste Config Connector para crear la cuenta de servicio, borra la cuenta de servicio con kubectl.

    kubectl delete -f service-account.yaml
    

    Esta acción requiere permisos iam.serviceAccounts.setIamPolicy en la cuenta de servicio.

    Los tokens almacenados en caché pueden tardar hasta 30 minutos en caducar. Puedes verificar si los tokens almacenados en caché caducaron con este comando:

    gcloud auth list
    

    Los tokens almacenados en caché caducaron si la salida de ese comando ya no incluye GSA_NAME@PROJECT_ID.iam.gserviceaccount.com.

  2. Quita la anotación de la cuenta de servicio de Kubernetes. Este paso es opcional porque IAM revocó el acceso.

    kubectl annotate serviceaccount KSA_NAME \
        --namespace K8S_NAMESPACE iam.gke.io/gcp-service-account-
    

Soluciona problemas

El Pod no se puede autenticar en Google Cloud

Si la aplicación no puede autenticarse en Google Cloud, asegúrate de que estas opciones estén configuradas de forma correcta:

  1. Asegúrate de tener habilitada la API de credenciales de la cuenta de servicio de IAM en el proyecto que contiene el clúster de GKE.

    Habilitar la API de credenciales IAM

  2. Asegúrate de que Workload Identity esté habilitado en el clúster mediante la verificación de que tiene un grupo de identidades de cargas de trabajo configurado:

    gcloud container clusters describe CLUSTER_NAME \
        --format="value(workloadIdentityConfig.workloadPool)"
    

    Si aún no especificaste una zona o región predeterminada para gcloud, es posible que también debas especificar una marca --region o --zone cuando ejecutes este comando.

  3. Asegúrate de que el servidor de metadatos de GKE (GKE_METADATA) esté configurado en el grupo de nodos en el que se ejecuta la aplicación:

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --format="value(config.workloadMetadataConfig.mode)"
    
  4. Asegúrate de que la cuenta de servicio de Kubernetes esté anotada de forma correcta

    kubectl describe serviceaccount \
        --namespace K8S_NAMESPACE KSA_NAME
    

    Debería haber una anotación en el siguiente formato:

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  5. Asegúrate de que la cuenta de servicio de IAM esté configurada de forma correcta

    gcloud iam service-accounts get-iam-policy \
        GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    

    Verifica que haya una vinculación con el siguiente formato:

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    
  6. Si tienes una política de red del clúster, asegúrate de que permitiste la salida a 127.0.0.1/32 en el puerto 988 para los clústeres que ejecutan versiones de GKE anteriores a 1.21.0-gke.1000, o a 169.254.169.252/32 en el puerto 988 para clústeres que ejecutan la versión 1.21.0-gke.1000 de GKE y versiones posteriores.

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

Errores de tiempo de espera en el inicio del Pod

El servidor de metadatos de GKE necesita unos segundos antes de comenzar a aceptar solicitudes en un Pod recién creado. Por lo tanto, los intentos de autenticarse con Workload Identity en los primeros segundos de la vida del Pod pueden fallar para aplicaciones y bibliotecas cliente de Google Cloud configuradas con un tiempo de espera breve.

Si encuentras errores de tiempo de espera, puedes cambiar el código de la aplicación para esperar unos segundos y volver a intentarlo. Como alternativa, puedes implementar un initContainer que espere hasta que el servidor de metadatos de GKE esté listo antes de ejecutar el contenedor principal del Pod.

A continuación, se muestra un Pod con un initContainer de ejemplo:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-initcontainer
spec:
  serviceAccountName: KSA_NAME
  initContainers:
  - image:  gcr.io/google.com/cloudsdktool/cloud-sdk:326.0.0-alpine
    name: workload-identity-initcontainer
    command:
    - '/bin/bash'
    - '-c'
    - |
      curl -s -H 'Metadata-Flavor: Google' 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' --retry 30 --retry-connrefused --retry-max-time 30 > /dev/null || exit 1
  containers:
  - image: gcr.io/your-project/your-image
    name: your-main-application-container

Workload Identity falla debido a la falta de disponibilidad del plano de control

El servidor de metadatos no puede mostrar Workload Identity cuando el plano de control del clúster no está disponible. Las llamadas al servidor de metadatos muestran el código de estado 500.

La entrada de registro puede ser similar a la siguiente en el Explorador de registros:

dial tcp 35.232.136.58:443: connect: connection refused

Esto generará una falta de disponibilidad esperada de Workload Identity.

Es posible que el plano de control no esté disponible en clústeres zonales durante el mantenimiento de los clústeres, como la rotación de las IP, la actualización de las VM del plano de control o el cambio de tamaño de clústeres o grupos de nodos. Consulta Elige un plano de control regional o zonal para obtener información sobre la disponibilidad del plano de control. Cambiar al clúster regional elimina este problema.

Workload Identity falla

Si el servidor de metadatos de GKE se bloquea por algún motivo, Workload Identity fallará.

Si usas Istio, debes agregar la siguiente anotación a nivel de la aplicación a todas las cargas de trabajo que usan Workload Identity:

"traffic.sidecar.istio.io/excludeOutboundIPRanges=169.254.169.254/32"

Como alternativa, puedes cambiar la clave global.proxy.excludeIPRanges de ConfigMap de Istio para hacer lo mismo.

Inhabilita Workload Identity en un clúster

Solo puedes inhabilitar Workload Identity en los clústeres estándar de GKE.

  1. Inhabilita Workload Identity en cada grupo de nodos:

    gcloud container node-pools update NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --workload-metadata=GCE_METADATA
    

    Repite este comando para cada grupo de nodos del clúster.

  2. Inhabilita Workload Identity en el clúster:

    gcloud container clusters update CLUSTER_NAME --disable-workload-identity
    

    Esta acción requiere permisos container.clusters.update en el clúster.

Inhabilita Workload Identity en la organización

Desde la perspectiva de seguridad, Workload Identity permite que GKE confirme las identidades de las cuentas de servicio de Kubernetes que se pueden autenticar y autorizar en los recursos de Google Cloud. Los administradores que realizaron acciones con el fin de aislar las cargas de trabajo de los recursos de Google Cloud, como inhabilitar la creación de cuentas de servicio o inhabilitar la creación de claves de cuentas de servicio, también podrían querer inhabilitar Workload Identity en la organización.

Consulta estas instrucciones para inhabilitar Workload Identity en la organización.

¿Qué sigue?