Résoudre les problèmes d'authentification de GKE


Cette page explique comment résoudre les problèmes liés aux configurations de sécurité dans vos clusters Google Kubernetes Engine (GKE) Autopilot et Standard.

Si vous avez besoin d'une aide supplémentaire, contactez Cloud Customer Care.

RBAC et IAM

Les comptes IAM authentifiés ne parviennent pas à effectuer des actions dans le cluster

Le problème suivant se produit lorsque vous essayez d'effectuer une action dans le cluster, mais que GKE ne trouve pas de stratégie RBAC autorisant cette action. GKE tente de trouver une stratégie d'autorisation IAM qui accorde la même autorisation. Si cette opération échoue, un message d'erreur semblable à celui-ci s'affiche :

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).

Pour résoudre ce problème, utilisez une stratégie RBAC afin d'accorder les autorisations pour l'action tentée. Par exemple, pour résoudre le problème dans l'exemple précédent, attribuez un rôle disposant de l'autorisation list sur les objets roles de l'espace de noms kube-system. Pour obtenir des instructions, consultez la page Autoriser les actions dans les clusters à l'aide du contrôle des accès basé sur les rôles.

Fédération d'identité de charge de travail pour GKE

Un pod ne peut pas s'authentifier auprès de Google Cloud

Si votre application ne peut pas s'authentifier auprès de Google Cloud, assurez-vous que les paramètres suivants sont correctement configurés :

  1. Assurez-vous d'avoir activé l'API IAM Service Account Credentials dans le projet contenant le cluster GKE.

    Activer l'API des identifiants IAM

  2. Vérifiez que la fédération d'identité de charge de travail pour GKE est activée sur le cluster en vérifiant qu'un pool d'identités de charge de travail est défini :

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

    Remplacez CLUSTER_NAME par le nom de votre cluster GKE.

    Si vous n'avez pas encore spécifié une zone ou une région par défaut pour gcloud, vous devrez peut-être également spécifier une option --region ou --zone lors de l'exécution de cette commande.

  3. Assurez-vous que le serveur de métadonnées GKE est configuré sur le pool de nœuds dans lequel votre application s'exécute :

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

    Remplacez les éléments suivants :

    • NODEPOOL_NAME par le nom de votre pool de nœuds.
    • CLUSTER_NAME par le nom de votre cluster GKE.
  4. Assurez-vous que le compte de service Kubernetes est correctement annoté :

    kubectl describe serviceaccount \
        --namespace NAMESPACE KSA_NAME
    

    Remplacez les éléments suivants :

    • NAMESPACE par l'espace de noms de votre cluster GKE.
    • KSA par le nom de votre compte de service Kubernetes.

    Le résultat attendu contient une annotation semblable à celle-ci :

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  5. Vérifiez que le compte de service IAM est correctement configuré :

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

    Le résultat attendu contient une liaison semblable à celle-ci :

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    
  6. Si vous disposez d'une règle de réseau de cluster, vous devez autoriser la sortie vers 127.0.0.1/32 sur le port 988 pour les clusters exécutant des versions GKE antérieures à 1.21.0-gke.1000, ou 169.254.169.252/32 sur le port 988 pour les clusters exécutant une version GKE 1.21.0-gke.1000 ou ultérieure. Pour les clusters exécutant GKE Dataplane V2, vous devez autoriser la sortie vers 169.254.169.254/32 sur le port 80.

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

    Remplacez NETWORK_POLICY_NAME par le nom de votre règle de réseau GKE.

Problèmes de résolution DNS

Certaines bibliothèques clientes Google Cloud sont configurées pour se connecter aux serveurs de métadonnées GKE et Compute Engine en résolvant le nom DNS metadata.google.internal. Pour ces bibliothèques, la résolution DNS opérationnelle interne au cluster est une dépendance critique pour que vos charges de travail s'authentifient auprès des services Google Cloud.

La méthode de détection de ce problème dépend des détails de votre application déployée, y compris la configuration de sa journalisation. Recherchez les messages d'erreur qui :

  • vous indiquent de configurer GOOGLE_APPLICATION_CREDENTIALS ; ou
  • vous indiquent que vos requêtes adressées à un service Google Cloud ont été refusées du fait que la requête ne contienne pas d'identifiants.

Si vous rencontrez des problèmes avec la résolution DNS de metadata.google.internal, certaines bibliothèques clientes Google Cloud peuvent être invitées à ignorer la résolution DNS en définissant la variable d'environnement GCE_METADATA_HOST sur 169.254.169.254 :

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"

Il s'agit de l'adresse IP codée en dur sur laquelle le service de métadonnées est toujours disponible sur les plates-formes de calcul Google Cloud.

Bibliothèques Google Cloud compatibles :

  • Python
  • Java
  • Node.js
  • Golang (Notez cependant que la bibliothèque cliente Golang préfère déjà se connecter par adresse IP plutôt que par nom DNS.)

Erreurs d'expiration au démarrage du pod

Le serveur de métadonnées GKE a besoin de quelques secondes pour pouvoir commencer à accepter des requêtes sur un nouveau pod. Les tentatives d'authentification à l'aide de la fédération d'identité de charge de travail pour GKE dans les premières secondes de la vie d'un pod peuvent échouer pour les applications et les bibliothèques clientes Google Cloud configurées avec un délai avant expiration court.

Si vous rencontrez des erreurs d'expiration de délai, procédez comme suit :

  • Mettez à jour les bibliothèques clientes Google Cloud utilisées par vos charges de travail.
  • Modifiez le code d'application pendant quelques secondes, puis réessayez.
  • Déployez un conteneur initContainer qui attend que le serveur de métadonnées GKE soit prêt avant d'exécuter le conteneur principal du pod.

    Par exemple, le fichier manifeste suivant concerne un pod avec un conteneur 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
    

Échec de la fédération d'identité de charge de travail pour GKE en raison de l'indisponibilité du plan de contrôle

Le serveur de métadonnées ne peut pas renvoyer la fédération d'identité de charge de travail pour GKE lorsque le plan de contrôle du cluster n'est pas disponible. Les appels au serveur de métadonnées renvoient le code d'état 500.

Une entrée de journal peut ressembler à l'exemple suivant dans l'explorateur de journaux :

dial tcp 35.232.136.58:443: connect: connection refused

Ce comportement entraîne une indisponibilité de la fédération d'identité de charge de travail pour GKE.

Le plan de contrôle peut être indisponible sur les clusters zonaux pendant les opérations de maintenance du cluster, telles que le renouvellement des adresses IP, la mise à niveau des VM du plan de contrôle, ou le redimensionnement des clusters ou des pools de nœuds. Pour en savoir plus sur la disponibilité du plan de contrôle, consultez la page Choisir un plan de contrôle régional ou zonal. Le passage à un cluster régional élimine ce problème.

Échec de l'authentification de la fédération d'identité de charge de travail pour GKE dans les clusters utilisant Istio

Si le serveur de métadonnées GKE est bloqué pour une raison quelconque, la fédération d'identité de charge de travail pour GKE échoue.

Si vous utilisez Istio ou Anthos Service Mesh, ajoutez l'annotation suivante au niveau du pod à toutes les charges de travail qui utilisent la fédération d'identité de charge de travail pour GKE afin d'exclure l'adresse IP de la redirection :

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

Vous pouvez également modifier la clé global.proxy.excludeIPRanges ConfigMap Istio.

Vous pouvez aussi ajouter l'annotation suivante au niveau du pod à toutes les charges de travail qui utilisent la fédération d'identité de charge de travail pour GKE afin de retarder le démarrage du conteneur d'application jusqu'à ce que le side-car soit prêt :

proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'

Vous pouvez également modifier la clé global.proxy.holdApplicationUntilProxyStarts ConfigMap Istio.

Plantage du pod gke-metadata-server

Le pod DaemonSet système gke-metadata-server facilite la fédération d'identité de charge de travail pour GKE sur vos nœuds. Le pod utilise des ressources de mémoire proportionnellement au nombre de comptes de service Kubernetes dans votre cluster.

Le problème suivant se produit lorsque l'utilisation des ressources du pod gke-metadata-server dépasse ses limites. Le kubelet supprime le pod avec une erreur de mémoire insuffisante. Vous pouvez rencontrer ce problème si votre cluster possède plus de 3 000 comptes de service Kubernetes.

Pour identifier le problème, procédez comme suit :

  1. Recherchez les pods gke-metadata-server qui plantent dans l'espace de noms kube-system :

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

    Le résultat ressemble à ce qui suit :

    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. Décrivez le pod qui plante pour vérifier que la cause était une suppression avec mémoire insuffisante :

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

    Remplacez POD_NAME par le nom du pod à vérifier.

Pour restaurer la fonctionnalité du serveur de métadonnées GKE, réduisez le nombre de comptes de service de votre cluster à moins de 3 000.

L'activation de la fédération d'identité de charge de travail pour GKE échoue avec le message d'erreur "DeployPatch failed"

GKE utilise l'agent de service Kubernetes Engine géré par Google Cloud pour faciliter la fédération d'identité de charge de travail pour GKE dans vos clusters. Google Cloud attribue automatiquement à cet agent de service le rôle d'agent de service Kubernetes Engine (roles/container.serviceAgent) sur votre projet lorsque vous activez l'API Google Kubernetes Engine.

Si vous essayez d'activer la fédération d'identité de charge de travail pour GKE sur des clusters dans un projet où l'agent de service ne dispose pas du rôle d'agent de service Kubernetes Engine, l'opération échoue avec un message d'erreur semblable à celui-ci :

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

Essayez les solutions suivantes pour résoudre ce problème :

  1. Vérifiez si l'agent de service existe dans votre projet et s'il est configuré correctement :

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

    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud.

    Si l'agent de service est correctement configuré, le résultat affiche l'identité complète de l'agent de service :

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

    Si le résultat n'affiche pas l'agent de service, vous devez lui attribuer le rôle d'agent de service Kubernetes Engine. Pour accorder ce rôle, suivez la procédure suivante.

  2. Obtenez votre numéro de projet Google Cloud :

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

    Le résultat ressemble à ce qui suit :

    123456789012
    
  3. Attribuez le rôle à l'agent de service :

    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
    

    Remplacez PROJECT_NUMBER par votre numéro de projet Google Cloud.

  4. Essayez d'activer à nouveau la fédération d'identité de charge de travail pour GKE.

Étapes suivantes

Si vous avez besoin d'une aide supplémentaire, contactez Cloud Customer Care.