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.
Workload Identity Federation for GKE
Le 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:
Assurez-vous d'avoir activé l'API IAM Service Account Credentials dans le projet contenant le cluster GKE.
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.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.
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
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
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 port988
pour les clusters exécutant des versions GKE antérieures à 1.21.0-gke.1000, ou169.254.169.252/32
sur le port988
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 vers169.254.169.254/32
sur le port80
.kubectl describe networkpolicy NETWORK_POLICY_NAME
Remplacez
NETWORK_POLICY_NAME
par le nom de votre règle de réseau GKE.
Accès au compte de service IAM refusé
Il est possible que les pods ne parviennent pas à accéder à une ressource avec la fédération d'identité de charge de travail pour GKE immédiatement après avoir ajouté des liaisons de rôle IAM. L'échec de l'accès est plus susceptible de se produire dans les pipelines de déploiement ou dans les configurations déclaratives où des ressources telles que les stratégies d'autorisation IAM, les liaisons de rôle et les pods Kubernetes sont créées ensemble. Google Cloud Le message d'erreur suivant s'affiche dans les journaux du 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).
Cette erreur peut être due à la propagation des modifications d'accès dans IAM, ce qui signifie que la propagation des modifications d'accès telles que les autorisations de rôle prend du temps dans le système. Pour les autorisations de rôle, la propagation prend généralement environ deux minutes, mais peut parfois prendre sept minutes ou plus. Pour en savoir plus, consultez la page Propagation des modifications d'accès.
Pour résoudre cette erreur, envisagez d'ajouter un délai avant que vos pods ne tentent d'accéder aux ressources Google Cloud après leur création.
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 servicesGoogle 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 contenait 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
Des erreurs semblables à celles-ci peuvent s'afficher lorsque votre application démarre et tente de communiquer avec un point de terminaison:
Connection refused (169.254.169.254:80)
Connection timeout
Ces erreurs peuvent se produire lorsque votre application tente d'établir une connexion réseau avant que le conteneur istio-proxy
ne soit prêt. Par défaut, Istio et Cloud Service Mesh autorisent les charges de travail à envoyer des requêtes dès qu'elles démarrent, que la charge de travail du proxy de service mesh qui intercepte et redirige le trafic soit en cours d'exécution ou non. Pour les pods qui utilisent la fédération d'identité de charge de travail pour GKE, ces requêtes initiales qui se produisent avant le démarrage du proxy peuvent ne pas atteindre le serveur de métadonnées GKE. Par conséquent, l'authentification aux API Google Cloud échoue.
Si vous ne configurez pas vos applications pour qu'elles relancent les requêtes, vos charges de travail risquent d'échouer.
Pour vérifier que ce problème est bien à l'origine de vos erreurs, consultez vos journaux et vérifiez si le conteneur istio-proxy
a démarré correctement:
Dans Google Cloud Console, accédez à la page Explorateur de journaux.
Dans le volet de requête, saisissez la requête suivante:
(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")
Remplacez les éléments suivants :
POD_NAME
: nom du pod avec la charge de travail affectée.ERROR_MESSAGE
: erreur reçue par l'application (connection timeout
ouconnection refused
).
Cliquez sur Exécuter la requête.
Examinez la sortie et vérifiez quand le conteneur
istio-proxy
est devenu prêt.Dans l'exemple suivant, l'application a tenté d'effectuer un appel gRPC. Toutefois, comme le conteneur
istio-proxy
était toujours en cours d'initialisation, l'application a reçu une erreurConnection refused
. Le code temporel à côté du messageEnvoy proxy is ready
indique à quel moment le conteneuristio-proxy
est devenu prêt à recevoir des requêtes de connexion: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
Pour résoudre ce problème et l'empêcher de se reproduire, essayez l'une des options de configuration par charge de travail suivantes:
Empêchez vos applications d'envoyer des requêtes tant que la charge de travail du proxy n'est pas prête. Ajoutez l'annotation suivante au champ
metadata.annotations
dans la spécification de votre pod:proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
Configurez Istio ou Cloud Service Mesh pour exclure l'adresse IP du serveur de métadonnées GKE de la redirection. Ajoutez l'annotation suivante au champ
metadata.annotations
de la spécification de votre pod:traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32
Dans Istio Open Source, vous pouvez atténuer ce problème pour tous les pods en définissant l'une des options de configuration globales suivantes:
Exclure l'adresse IP du serveur de métadonnées GKE de la redirection : modifiez l'option de configuration globale
global.proxy.excludeIPRanges
pour ajouter la plage d'adresses IP169.254.169.254/32
.Empêcher les applications d'envoyer des requêtes jusqu'au démarrage du proxy : ajoutez l'option de configuration globale
global.proxy.holdApplicationUntilProxyStarts
avec une valeur detrue
à votre configuration 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 :
Recherchez les pods
gke-metadata-server
qui plantent dans l'espace de nomskube-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
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 Cloudpour 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 :
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 Google Cloudprojet.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.
Obtenez votre numéro de projet Google Cloud :
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Le résultat ressemble à ce qui suit :
123456789012
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.Essayez d'activer à nouveau la fédération d'identité de charge de travail pour GKE.