Solucionar problemas de autenticación de GKE

En esta página se explica cómo resolver problemas relacionados con las configuraciones de seguridad de los clústeres Autopilot y Estándar de Google Kubernetes Engine (GKE).

RBAC e IAM

Las cuentas de gestión de identidades y accesos autenticadas no pueden realizar acciones en el clúster

El siguiente problema se produce cuando intentas realizar una acción en el clúster, pero GKE no encuentra una política de RBAC que autorice la acción. GKE intenta encontrar una política de gestión de identidades y accesos que conceda el mismo permiso. Si no funciona, verás un mensaje de error similar al siguiente:

Error from server (Forbidden): roles.rbac.authorization.k8s.io is forbidden:
User "example-account@example-project.iam.gserviceaccount.com" cannot list resource "roles" in
API group "rbac.authorization.k8s.io" in the namespace "kube-system": requires
one of ["container.roles.list"] permission(s).

Para resolver este problema, utilice una política de control de acceso basado en roles para conceder los permisos de la acción intentada. Por ejemplo, para solucionar el problema del ejemplo anterior, concede un rol que tenga el permiso list en los objetos roles del espacio de nombres kube-system. Para obtener instrucciones, consulta Autorizar acciones en clústeres mediante el control de acceso basado en roles.

Workload Identity Federation para GKE

El pod no puede autenticarse en Google Cloud

Si tu aplicación no puede autenticarse en Google Cloud, asegúrate de que los siguientes ajustes estén configurados correctamente:

  1. Comprueba que hayas habilitado la API Service Account Credentials de gestión de identidades y accesos en el proyecto que contiene el clúster de GKE.

    Habilitar la API IAM Credentials

  2. Confirma que Workload Identity Federation for GKE está habilitado en el clúster comprobando que tiene un grupo de identidades de carga de trabajo configurado:

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

    Sustituye CLUSTER_NAME por el nombre de tu clúster de GKE.

    Si aún no has especificado una zona o región predeterminada para gcloud, también es posible que tengas que especificar un indicador --region o --zone al ejecutar este comando.

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

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --format="value(config.workloadMetadataConfig.mode)"
    

    Haz los cambios siguientes:

    • NODEPOOL_NAME con el nombre de tu nodepool.
    • CLUSTER_NAME por el nombre de tu clúster de GKE.
  4. Verifica que la cuenta de servicio de Kubernetes esté anotada correctamente:

    kubectl describe serviceaccount \
        --namespace NAMESPACE KSA_NAME
    

    Haz los cambios siguientes:

    • NAMESPACE con el espacio de nombres de tu clúster de GKE.
    • KSA con el nombre de tu cuenta de servicio de Kubernetes.

    La salida esperada contiene una anotación similar a la siguiente:

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  5. Comprueba que la cuenta de servicio de gestión de identidades y accesos esté configurada correctamente:

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

    El resultado esperado contiene un enlace similar al siguiente:

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    
  6. Si tienes una política de red de clúster, debes permitir el tráfico saliente a 127.0.0.1/32 en el puerto 988 para los clústeres que ejecuten versiones de GKE anteriores a la 1.21.0-gke.1000, o a 169.254.169.252/32 en el puerto 988 para los clústeres que ejecuten la versión 1.21.0-gke.1000 de GKE o una posterior. En los clústeres que ejecutan GKE Dataplane V2, debes permitir el tráfico saliente a 169.254.169.254/32 en el puerto 80.

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

    Sustituye NETWORK_POLICY_NAME por el nombre de tu política de red de GKE.

Acceso denegado a la cuenta de servicio de gestión de identidades y accesos

Es posible que los pods no puedan acceder a un recurso con Workload Identity Federation para GKE inmediatamente después de añadir vinculaciones de roles de gestión de identidades y accesos. Es más probable que se produzca un error de acceso en las pipelines de implementación o en las configuraciones declarativas Google Cloud , donde se crean recursos como las políticas de gestión de identidades y accesos, las vinculaciones de roles y los pods de Kubernetes. Aparece el siguiente mensaje de error en los registros de Pod:

HTTP/403: generic::permission_denied: loading: GenerateAccessToken("SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com", ""): googleapi: Error 403: Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).

Este error puede deberse a la propagación de cambios de acceso en IAM, lo que significa que los cambios de acceso, como la concesión de roles, tardan en propagarse por el sistema. En el caso de las concesiones de roles, la propagación suele tardar unos dos minutos, pero a veces puede tardar siete minutos o más. Para obtener más información, consulta Propagación de cambios de acceso.

Para solucionar este error, puede añadir un retraso antes de que sus pods intenten acceder a los recursos de Google Cloud después de crearse.

Problemas de resolución de DNS

En esta sección se describe cómo identificar y resolver errores de conexión de pods a APIs Google Cloud causados por problemas de resolución de DNS. Si los pasos de esta sección no resuelven los errores de conexión, consulta la sección Errores de tiempo de espera al iniciar el pod.

Algunas bibliotecas de cliente están configuradas para conectarse a los servidores de metadatos de GKE y Compute Engine resolviendo el nombre DNS metadata.google.internal. En el caso de estas bibliotecas, una resolución de DNS correcta en el clúster es una dependencia fundamental para que tus cargas de trabajo se autentiquen en los servicios deGoogle Cloud . Google Cloud

La forma de detectar este problema depende de los detalles de la aplicación implementada, incluida su configuración de registro. Busca mensajes de error que te indiquen que debes configurar GOOGLE_APPLICATION_CREDENTIALS, que tus solicitudes a un servicioGoogle Cloud se han rechazado porque no tenían credenciales o que no se ha encontrado el servidor de metadatos.

Por ejemplo, el siguiente mensaje de error puede indicar que hay un problema de resolución de DNS:

ComputeEngineCredentials cannot find the metadata server. This is likely because code is not running on Google Compute Engine

Si tienes problemas con la resolución de DNS de metadata.google.internal, algunas Google Cloud bibliotecas de cliente pueden saltarse la resolución de DNS si se asigna el valor 169.254.169.254 a la variable de entorno GCE_METADATA_HOST:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  namespace: default
spec:
  containers:
  - image: debian
    name: main
    command: ["sleep", "infinity"]
    env:
    - name: GCE_METADATA_HOST
      value: "169.254.169.254"

Esta es la dirección IP codificada en la que el servicio de metadatos siempre está disponible en las plataformas de computación. Google Cloud

Se admiten las siguientes bibliotecas: Google Cloud

  • Python
  • Java
  • Node.js
  • Golang

    De forma predeterminada, la biblioteca de cliente de Go se conecta mediante la dirección IP.

Errores de tiempo de espera al iniciar el pod

El servidor de metadatos de GKE necesita unos segundos antes de poder empezar a aceptar solicitudes en un nuevo pod. Si se intenta autenticar mediante la federación de identidades de carga de trabajo para GKE en los primeros segundos de la vida de un pod, es posible que se produzca un error en las aplicaciones y las bibliotecas de cliente configuradas con un tiempo de espera corto. Google Cloud

Si se producen errores de tiempo de espera, prueba lo siguiente:

  • Actualiza las bibliotecas de cliente de Google Cloud que usan tus cargas de trabajo.
  • Cambia el código de la aplicación para que espere unos segundos y vuelva a intentarlo.
  • Implementa un initContainer que espere hasta que el servidor de metadatos de GKE esté listo antes de ejecutar el contenedor principal del pod.

    Por ejemplo, el siguiente manifiesto es de un Pod con un initContainer:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-with-initcontainer
    spec:
      serviceAccountName: KSA_NAME
      initContainers:
      - image:  gcr.io/google.com/cloudsdktool/cloud-sdk:alpine
        name: workload-identity-initcontainer
        command:
        - '/bin/bash'
        - '-c'
        - |
          curl -sS -H 'Metadata-Flavor: Google' 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token' --retry 30 --retry-connrefused --retry-max-time 60 --connect-timeout 3 --fail --retry-all-errors > /dev/null && exit 0 || echo 'Retry limit exceeded. Failed to wait for metadata server to be available. Check if the gke-metadata-server Pod in the kube-system namespace is healthy.' >&2; exit 1
      containers:
      - image: gcr.io/your-project/your-image
        name: your-main-application-container
    

Workload Identity Federation for GKE falla debido a que el plano de control no está disponible

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

Una entrada de registro puede tener un aspecto similar al siguiente en el Explorador de registros:

dial tcp 35.232.136.58:443: connect: connection refused

Este comportamiento provoca que Workload Identity Federation for GKE no esté disponible.

Es posible que el plano de control no esté disponible en los clústeres zonales durante el mantenimiento del clúster, como la rotación de IPs, la actualización de las VMs del plano de control o el cambio de tamaño de los clústeres o los grupos de nodos. Consulta Elegir un plano de control regional o de zona para obtener información sobre la disponibilidad del plano de control. Si cambias a un clúster regional, este problema se soluciona.

La autenticación de Workload Identity Federation for GKE falla en clústeres que usan Istio

Es posible que veas errores similares a los siguientes cuando se inicie tu aplicación e intente comunicarse con un endpoint:

Connection refused (169.254.169.254:80)
Connection timeout

Estos errores pueden producirse cuando tu aplicación intenta establecer una conexión de red antes de que el contenedor istio-proxy esté listo. De forma predeterminada, Istio y Cloud Service Mesh permiten que las cargas de trabajo envíen solicitudes en cuanto se inician, independientemente de si se está ejecutando la carga de trabajo del proxy de la malla de servicios que intercepta y redirige el tráfico. En el caso de los pods que usan Workload Identity Federation for GKE, es posible que estas solicitudes iniciales que se producen antes de que se inicie el proxy no lleguen al servidor de metadatos de GKE. Por lo tanto, no se puede autenticar en las APIs de Google Cloud . Si no configuras tus aplicaciones para que vuelvan a intentar las solicitudes, es posible que tus cargas de trabajo fallen.

Para confirmar que este problema es la causa de los errores, consulte los registros y compruebe si el contenedor istio-proxy se ha iniciado correctamente:

  1. En la Google Cloud consola, ve a la página Explorador de registros.

    Ir a Explorador de registros

  2. En el panel de consultas, introduce la siguiente consulta:

    (resource.type="k8s_container"
    resource.labels.pod_name="POD_NAME"
    textPayload:"Envoy proxy is ready" OR textPayload:"ERROR_MESSAGE")
    OR
    (resource.type="k8s_pod"
    logName:"events"
    jsonPayload.involvedObject.name="POD_NAME")
    

    Haz los cambios siguientes:

    • POD_NAME: el nombre del pod con la carga de trabajo afectada.
    • ERROR_MESSAGE: el error que ha recibido la aplicación (connection timeout o connection refused).
  3. Haz clic en Realizar una consulta.

  4. Revisa el resultado y comprueba cuándo se ha preparado el contenedor istio-proxy.

    En el siguiente ejemplo, la aplicación ha intentado hacer una llamada gRPC. Sin embargo, como el contenedor istio-proxy aún se estaba inicializando, la aplicación recibió un error Connection refused. La marca de tiempo situada junto al mensaje Envoy proxy is ready indica cuándo el contenedor istio-proxy se ha preparado para recibir solicitudes de conexión:

    2024-11-11T18:37:03Z started container istio-init
    2024-11-11T18:37:12Z started container gcs-fetch
    2024-11-11T18:37:42Z Initializing environment
    2024-11-11T18:37:55Z Started container istio-proxy
    2024-11-11T18:38:06Z StatusCode="Unavailable", Detail="Error starting gRPC call. HttpRequestException: Connection refused (169.254.169.254:80)
    2024-11-11T18:38:13Z Envoy proxy is ready
    

Para solucionar este problema y evitar que vuelva a ocurrir, prueba una de las siguientes opciones de configuración por carga de trabajo:

  • Evita que tus aplicaciones envíen solicitudes hasta que la carga de trabajo del proxy esté lista. Añade la siguiente anotación al campo metadata.annotations de la especificación de tu pod:

    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  • Configura Istio o Cloud Service Mesh para excluir la dirección IP del servidor de metadatos de GKE de la redirección. Añade la siguiente anotación al campo metadata.annotations de la especificación de tu pod:

    traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32
    

En Istio de código abierto, puede mitigar este problema en todos los pods si define una de las siguientes opciones de configuración global:

  • Excluye la dirección IP del servidor de metadatos de GKE de la redirección: actualiza la opción de configuración global global.proxy.excludeIPRanges para añadir el intervalo de direcciones IP 169.254.169.254/32.

  • Impedir que las aplicaciones envíen solicitudes hasta que se inicie el proxy: añade la opción de configuración global global.proxy.holdApplicationUntilProxyStarts con el valor true a tu configuración de Istio.

gke-metadata-server Pod falla

El pod de DaemonSet del sistema gke-metadata-server facilita Workload Identity Federation para GKE en tus nodos. El pod usa recursos de memoria proporcionales al número de cuentas de servicio de Kubernetes de tu clúster.

El siguiente problema se produce cuando el uso de recursos del gke-metadata-server Pod supera sus límites. Kubelet expulsa el pod con un error de falta de memoria. Puede que tengas este problema si tu clúster tiene más de 3000 cuentas de servicio de Kubernetes.

Para identificar el problema, sigue estos pasos:

  1. Busca los pods de gke-metadata-server que fallan en el espacio de nombres kube-system:

    kubectl get pods -n=kube-system | grep CrashLoopBackOff
    

    El resultado debería ser similar al siguiente:

    NAMESPACE     NAME                        READY     STATUS             RESTARTS   AGE
    kube-system   gke-metadata-server-8sm2l   0/1       CrashLoopBackOff   194        16h
    kube-system   gke-metadata-server-hfs6l   0/1       CrashLoopBackOff   1369       111d
    kube-system   gke-metadata-server-hvtzn   0/1       CrashLoopBackOff   669        111d
    kube-system   gke-metadata-server-swhbb   0/1       CrashLoopBackOff   30         136m
    kube-system   gke-metadata-server-x4bl4   0/1       CrashLoopBackOff   7          15m
    
  2. Describe el pod que falla para confirmar que la causa es una expulsión por falta de memoria:

    kubectl describe pod POD_NAME --namespace=kube-system | grep OOMKilled
    

    Sustituye POD_NAME por el nombre del Pod que quieras comprobar.

Para restaurar la funcionalidad del servidor de metadatos de GKE, reduce el número de cuentas de servicio de tu clúster a menos de 3000.

No se puede habilitar Workload Identity Federation para GKE y aparece el mensaje de error "DeployPatch failed"

GKE usa el Google Cloudgestionado por el usuarioagente de servicio de Kubernetes Engine para facilitar la federación de identidades de carga de trabajo para GKE en tus clústeres. Google Cloud automáticamente concede a este agente de servicio el rol de agente de servicio de Kubernetes Engine (roles/container.serviceAgent) en tu proyecto cuando habilitas la API de Google Kubernetes Engine.

Si intentas habilitar la federación de identidades de carga de trabajo para GKE en clústeres de un proyecto en el que el agente de servicio no tiene el rol Agente de servicio de Kubernetes Engine, la operación fallará y se mostrará un mensaje de error similar al siguiente:

Error waiting for updating GKE cluster workload identity config: DeployPatch failed

Para solucionar este problema, sigue estos pasos:

  1. Comprueba si el agente de servicio existe en tu proyecto y si está configurado correctamente:

    gcloud projects get-iam-policy PROJECT_ID \
        --flatten=bindings \
        --filter=bindings.role=roles/container.serviceAgent \
        --format="value[delimiter='\\n'](bindings.members)"
    

    Sustituye PROJECT_ID por el ID de tu proyecto. Google Cloud

    Si el agente de servicio está configurado correctamente, el resultado muestra la identidad completa del agente de servicio:

    serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
    

    Si el resultado no muestra el agente de servicio, debes concederle el rol Agente de servicio de Kubernetes Engine. Para conceder este rol, sigue estos pasos.

  2. Obtén el número de tu proyecto: Google Cloud

    gcloud projects describe PROJECT_ID \
        --format="value(projectNumber)"
    

    El resultado debería ser similar al siguiente:

    123456789012
    
  3. Asigna el rol al agente de servicio:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com \
        --role=roles/container.serviceAgent \
        --condition=None
    

    Sustituye PROJECT_NUMBER por el número de tu proyecto. Google Cloud

  4. Intenta habilitar Workload Identity Federation para GKE de nuevo.

Siguientes pasos