Cette page explique comment résoudre les problèmes liés aux comptes de service Google Kubernetes Engine (GKE).
Attribuer le rôle requis pour GKE aux comptes de service de nœud
Les comptes de service IAM utilisés par vos nœuds GKE doivent disposer de toutes les autorisations incluses dans le rôle IAM Compte de service de nœud par défaut Kubernetes Engine (roles/container.defaultNodeServiceAccount
). Si un compte de service de nœud GKE ne dispose pas d'une ou de plusieurs de ces autorisations, GKE ne peut pas effectuer les tâches système suivantes:
- Envoyer les journaux système et d'application des nœuds à Cloud Logging.
- Envoyer des métriques système et d'application à partir de nœuds vers Cloud Monitoring.
- Utilisez le profil de performances de l'autoscaler horizontal des pods.
Il est possible que les comptes de service de nœud ne disposent pas de certaines autorisations requises pour des raisons telles que les suivantes:
- L'organisation applique la contrainte liée aux règles d'administration
iam.automaticIamGrantsForDefaultServiceAccounts
, qui empêche Google Cloud d'attribuer automatiquement des rôles IAM aux comptes de service IAM par défaut. - Le rôle IAM que vous accordez aux comptes de service de nœud personnalisés n'inclut pas toutes les autorisations requises incluses dans le rôle
roles/container.defaultNodeServiceAccount
.
Si les autorisations requises par GKE ne sont pas accordées à votre compte de service de nœud, des erreurs et des notifications semblables aux suivantes peuvent s'afficher:
- Dans la console Google Cloud , sur la page Clusters Kubernetes, un message d'erreur Accorder des autorisations critiques s'affiche dans la colonne Notifications pour un cluster spécifique.
Dans la console Google Cloud , sur la page des détails d'un cluster spécifique, le message d'erreur suivant s'affiche:
Grant roles/container.defaultNodeServiceAccount role to Node service account to allow for non-degraded operations.
Dans Cloud Audit Logs, les journaux des activités d'administration pour les API Google Cloud telles que
monitoring.googleapis.com
ont les valeurs suivantes si les autorisations correspondantes pour accéder à ces API sont manquantes dans le compte de service du nœud:- Gravité :
ERROR
- Message :
Permission denied (or the resource may not exist)
- Gravité :
Les journaux de nœuds spécifiques sont manquants dans Cloud Logging, et les journaux de pod pour l'agent de journalisation sur ces nœuds affichent des erreurs
401
. Pour obtenir ces journaux de pod, exécutez la commande suivante:[[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"
Si la sortie est
true
, la charge de travail du système rencontre des erreurs401
, ce qui indique un manque d'autorisations.
Pour résoudre ce problème, accordez le rôle de compte de service de nœud par défaut Kubernetes Engine (roles/container.defaultNodeServiceAccount
) au projet au compte de service à l'origine des erreurs. Sélectionnez l'une des options suivantes :
Console
Pour trouver le nom du compte de service utilisé par vos nœuds, procédez comme suit:
Accédez à la page Clusters Kubernetes:
Dans la liste des clusters, cliquez sur le nom du cluster que vous souhaitez inspecter.
Recherchez le nom du compte de service de nœud. Vous aurez besoin de ce nom ultérieurement.
- Pour les clusters en mode Autopilot, dans la section Sécurité, recherchez le champ Compte de service.
- Pour les clusters en mode Standard, procédez comme suit:
- Cliquez sur l'onglet Nœuds.
- Dans le tableau Pools de nœuds, cliquez sur le nom d'un pool de nœuds. La page Détails du pool de nœuds s'affiche.
- Dans la section Sécurité, recherchez le champ Compte de service.
Si la valeur du champ Compte de service est
default
, vos nœuds utilisent le compte de service Compute Engine par défaut. Si la valeur de ce champ n'est pasdefault
, vos nœuds utilisent un compte de service personnalisé.
Pour attribuer le rôle Kubernetes Engine Default Node Service Account
au compte de service, procédez comme suit:
Accédez à la page Bienvenue:
Dans le champ Numéro du projet, cliquez sur
Copier dans le presse-papiers.Accédez à la page IAM :
Cliquez sur
Accorder l'accès.Dans le champ Nouveaux comptes principaux, spécifiez le nom de votre compte de service de nœud. Si vos nœuds utilisent le compte de service Compute Engine par défaut, spécifiez la valeur suivante:
PROJECT_NUMBER[email protected]
Remplacez
PROJECT_NUMBER
par le numéro de projet que vous avez copié.Dans le menu Sélectionner un rôle, sélectionnez le rôle Compte de service de nœud par défaut Kubernetes Engine.
Cliquez sur Enregistrer.
Pour vérifier que le rôle a été attribué, procédez comme suit:
- Sur la page IAM, cliquez sur l'onglet Afficher par rôle.
- Développez la section Compte de service de nœud par défaut Kubernetes Engine. La liste des comptes principaux disposant de ce rôle s'affiche.
- Recherchez votre compte de service de nœud dans la liste des comptes principaux.
gcloud
Recherchez le nom du compte de service utilisé par vos nœuds:
- Pour les clusters en mode Autopilot, exécutez la commande suivante:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
- Pour les clusters en mode Standard, exécutez la commande suivante:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="table(nodePools.name,nodePools.config.serviceAccount)"
Si la sortie est
default
, vos nœuds utilisent le compte de service Compute Engine par défaut. Si la sortie n'est pasdefault
, vos nœuds utilisent un compte de service personnalisé.Recherchez le numéro de votre Google Cloud projet:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Remplacez
PROJECT_ID
par l'ID du projet.Le résultat ressemble à ce qui suit :
12345678901
Attribuez le rôle
roles/container.defaultNodeServiceAccount
au compte de service:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="SERVICE_ACCOUNT_NAME" \ --role="roles/container.defaultNodeServiceAccount"
Remplacez
SERVICE_ACCOUNT_NAME
par le nom du compte de service que vous avez trouvé à l'étape précédente. Si vos nœuds utilisent le compte de service Compute Engine par défaut, spécifiez la valeur suivante:serviceAccount:PROJECT_NUMBER[email protected]
Remplacez
PROJECT_NUMBER
par le numéro de projet de l'étape précédente.Vérifiez que le rôle a bien été attribué:
gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \ --format='value(bindings.members)'
La sortie indique le nom de votre compte de service.
Identifier les comptes de service de nœud qui ne disposent pas des autorisations requises
Les sections suivantes décrivent comment identifier les comptes de service de nœud qui ne disposent pas des autorisations requises pour GKE.
Identifier les clusters dont les comptes de service de nœud ne disposent pas des autorisations nécessaires
Utilisez les recommandations GKE du sous-type de recommandateur NODE_SA_MISSING_PERMISSIONS
pour identifier les clusters Autopilot et standards dont les comptes de service de nœuds ne disposent pas d'autorisations. Le recommender n'identifie que les clusters créés à compter du 1er janvier 2024. Pour rechercher et corriger les autorisations manquantes à l'aide de l'outil de recommandation, procédez comme suit:
Recherchez les recommandations actives dans votre projet pour le sous-type de recommandateur
NODE_SA_MISSING_PERMISSIONS
:gcloud recommender recommendations list \ --recommender=google.container.DiagnosisRecommender \ --location LOCATION \ --project PROJECT_ID \ --format yaml \ --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
Remplacez les éléments suivants :
LOCATION
: emplacement dans lequel trouver des recommandations.PROJECT_ID
: ID de votre Google Cloud projet.
Le résultat ressemble à ce qui suit, ce qui indique qu'un cluster dispose d'un compte de service de nœud dont les autorisations sont manquantes:
associatedInsights: # lines omitted for clarity recommenderSubtype: NODE_SA_MISSING_PERMISSIONS stateInfo: state: ACTIVE targetResources: - //container.googleapis.com/projects/12345678901/locations/us-central1/clusters/cluster-1
L'affichage de la recommandation peut prendre jusqu'à 24 heures. Pour obtenir des instructions détaillées, consultez la section Afficher les insights et les recommandations.
Pour chaque cluster figurant dans la sortie de l'étape précédente, recherchez les comptes de service de nœud associés et accordez-leur le rôle requis. Pour en savoir plus, consultez les instructions de la section Attribuer le rôle requis aux comptes de service de nœud pour GKE.
Une fois que vous avez attribué le rôle requis aux comptes de service de nœud identifiés, la recommandation peut persister jusqu'à 24 heures, sauf si vous la fermez manuellement.
Identifier tous les comptes de service de nœud dont les autorisations sont manquantes
Vous pouvez exécuter un script qui recherche dans les pools de nœuds des clusters Standard et Autopilot de votre projet tous les comptes de service de nœuds qui ne disposent pas des autorisations requises pour GKE. Ce script utilise gcloud CLI et l'utilitaire jq
. Pour afficher le script, développez la section suivante:
Afficher le script
#!/bin/bash
# Set your project ID
project_id=PROJECT_ID
project_number=$(gcloud projects describe "$project_id" --format="value(projectNumber)")
declare -a all_service_accounts
declare -a sa_missing_permissions
# Function to check if a service account has a specific permission
# $1: project_id
# $2: service_account
# $3: permission
service_account_has_permission() {
local project_id="$1"
local service_account="$2"
local permission="$3"
local roles=$(gcloud projects get-iam-policy "$project_id" \
--flatten="bindings[].members" \
--format="table[no-heading](bindings.role)" \
--filter="bindings.members:\"$service_account\"")
for role in $roles; do
if role_has_permission "$role" "$permission"; then
echo "Yes" # Has permission
return
fi
done
echo "No" # Does not have permission
}
# Function to check if a role has the specific permission
# $1: role
# $2: permission
role_has_permission() {
local role="$1"
local permission="$2"
gcloud iam roles describe "$role" --format="json" | \
jq -r ".includedPermissions" | \
grep -q "$permission"
}
# Function to add $1 into the service account array all_service_accounts
# $1: service account
add_service_account() {
local service_account="$1"
all_service_accounts+=( ${service_account} )
}
# Function to add service accounts into the global array all_service_accounts for a Standard GKE cluster
# $1: project_id
# $2: location
# $3: cluster_name
add_service_accounts_for_standard() {
local project_id="$1"
local cluster_location="$2"
local cluster_name="$3"
while read nodepool; do
nodepool_name=$(echo "$nodepool" | awk '{print $1}')
if [[ "$nodepool_name" == "" ]]; then
# skip the empty line which is from running `gcloud container node-pools list` in GCP console
continue
fi
while read nodepool_details; do
service_account=$(echo "$nodepool_details" | awk '{print $1}')
if [[ "$service_account" == "default" ]]; then
service_account="${project_number}[email protected]"
fi
if [[ -n "$service_account" ]]; then
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" $service_account $project_id $cluster_name $cluster_location $nodepool_name
add_service_account "${service_account}"
else
echo "cannot find service account for node pool $project_id\t$cluster_name\t$cluster_location\t$nodepool_details"
fi
done <<< "$(gcloud container node-pools describe "$nodepool_name" --cluster "$cluster_name" --zone "$cluster_location" --project "$project_id" --format="table[no-heading](config.serviceAccount)")"
done <<< "$(gcloud container node-pools list --cluster "$cluster_name" --zone "$cluster_location" --project "$project_id" --format="table[no-heading](name)")"
}
# Function to add service accounts into the global array all_service_accounts for an Autopilot GKE cluster
# Autopilot cluster only has one node service account.
# $1: project_id
# $2: location
# $3: cluster_name
add_service_account_for_autopilot(){
local project_id="$1"
local cluster_location="$2"
local cluster_name="$3"
while read service_account; do
if [[ "$service_account" == "default" ]]; then
service_account="${project_number}[email protected]"
fi
if [[ -n "$service_account" ]]; then
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" $service_account $project_id $cluster_name $cluster_location $nodepool_name
add_service_account "${service_account}"
else
echo "cannot find service account" for cluster "$project_id\t$cluster_name\t$cluster_location\t"
fi
done <<< "$(gcloud container clusters describe "$cluster_name" --location "$cluster_location" --project "$project_id" --format="table[no-heading](autoscaling.autoprovisioningNodePoolDefaults.serviceAccount)")"
}
# Function to check whether the cluster is an Autopilot cluster or not
# $1: project_id
# $2: location
# $3: cluster_name
is_autopilot_cluster() {
local project_id="$1"
local cluster_location="$2"
local cluster_name="$3"
autopilot=$(gcloud container clusters describe "$cluster_name" --location "$cluster_location" --format="table[no-heading](autopilot.enabled)")
echo "$autopilot"
}
echo "--- 1. List all service accounts in all GKE node pools"
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" "service_account" "project_id" "cluster_name" "cluster_location" "nodepool_name"
while read cluster; do
cluster_name=$(echo "$cluster" | awk '{print $1}')
cluster_location=$(echo "$cluster" | awk '{print $2}')
# how to find a cluster is a Standard cluster or an Autopilot cluster
autopilot=$(is_autopilot_cluster "$project_id" "$cluster_location" "$cluster_name")
if [[ "$autopilot" == "True" ]]; then
add_service_account_for_autopilot "$project_id" "$cluster_location" "$cluster_name"
else
add_service_accounts_for_standard "$project_id" "$cluster_location" "$cluster_name"
fi
done <<< "$(gcloud container clusters list --project "$project_id" --format="value(name,location)")"
echo "--- 2. Check if service accounts have permissions"
unique_service_accounts=($(echo "${all_service_accounts[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
echo "Service accounts: ${unique_service_accounts[@]}"
printf "%-60s| %-40s| %-40s| %-20s\n" "service_account" "has_logging_permission" "has_monitoring_permission" "has_performance_hpa_metric_write_permission"
for sa in "${unique_service_accounts[@]}"; do
logging_permission=$(service_account_has_permission "$project_id" "$sa" "logging.logEntries.create")
time_series_create_permission=$(service_account_has_permission "$project_id" "$sa" "monitoring.timeSeries.create")
metric_descriptors_create_permission=$(service_account_has_permission "$project_id" "$sa" "monitoring.metricDescriptors.create")
if [[ "$time_series_create_permission" == "No" || "$metric_descriptors_create_permission" == "No" ]]; then
monitoring_permission="No"
else
monitoring_permission="Yes"
fi
performance_hpa_metric_write_permission=$(service_account_has_permission "$project_id" "$sa" "autoscaling.sites.writeMetrics")
printf "%-60s| %-40s| %-40s| %-20s\n" $sa $logging_permission $monitoring_permission $performance_hpa_metric_write_permission
if [[ "$logging_permission" == "No" || "$monitoring_permission" == "No" || "$performance_hpa_metric_write_permission" == "No" ]]; then
sa_missing_permissions+=( ${sa} )
fi
done
echo "--- 3. List all service accounts that don't have the above permissions"
if [[ "${#sa_missing_permissions[@]}" -gt 0 ]]; then
printf "Grant roles/container.defaultNodeServiceAccount to the following service accounts: %s\n" "${sa_missing_permissions[@]}"
else
echo "All service accounts have the above permissions"
fi
Ce script s'applique à tous les clusters GKE de votre projet.
Après avoir identifié les noms des comptes de service dont les autorisations sont manquantes, attribuez-leur le rôle requis. Pour en savoir plus, consultez les instructions de la section Attribuer aux comptes de service de nœud le rôle requis pour GKE.
Restaurer le compte de service par défaut sur votre Google Cloud projet
Le compte de service par défaut de GKE, container-engine-robot
, peut être dissocié accidentellement d'un projet. Le rôle d'agent de service Kubernetes Engine (roles/container.serviceAgent
) est un rôle Identity and Access Management (IAM) qui accorde au compte de service les autorisations nécessaires pour gérer les ressources du cluster. Si vous supprimez cette liaison de rôle du compte de service, le compte de service par défaut est dissocié du projet, ce qui peut vous empêcher de déployer des applications et d'effectuer d'autres opérations sur le cluster.
Pour vérifier si le compte de service a été supprimé de votre projet, vous pouvez utiliser la console Google Cloud ou Google Cloud CLI.
Console
Dans la console Google Cloud , accédez à la page IAM et Administration.
gcloud
Exécutez la commande suivante :
gcloud projects get-iam-policy PROJECT_ID
Remplacez
PROJECT_ID
par l'ID du projet.
Si le tableau de bord ou la commande n'affiche pas container-engine-robot
parmi vos comptes de service, le rôle est dissocié.
Pour restaurer la liaison du rôle d'agent de service Kubernetes Engine (roles/container.serviceAgent
), exécutez les commandes suivantes :
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID" \
--format 'get(projectNumber)') \
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
Vérifiez que la liaison de rôle est restaurée :
gcloud projects get-iam-policy $PROJECT_ID
Si vous voyez le nom du compte de service avec le rôle container.serviceAgent
, la liaison de rôle est restaurée. Par exemple :
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Activer le compte de service Compute Engine par défaut
Le compte de service utilisé pour le pool de nœuds est généralement le compte de service Compute Engine par défaut. Si ce compte de service par défaut est désactivé, vos nœuds risquent de ne pas s'enregistrer auprès du cluster.
Pour vérifier si le compte de service est désactivé dans votre projet, vous pouvez utiliser la consoleGoogle Cloud ou gcloud CLI.
Console
Dans la console Google Cloud , accédez à la page IAM et Administration.
gcloud
- Exécutez la commande suivante :
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
Si le compte de service est désactivé, exécutez la commande suivante pour l'activer :
gcloud iam service-accounts enable PROJECT_ID[email protected]
Remplacez PROJECT_ID
par l'ID du projet.
Pour en savoir plus, consultez Résoudre les problèmes d'enregistrement de nœuds.
Erreur 400/403 : le compte n'est pas autorisé à apporter des modifications
Si votre compte de service est supprimé, une erreur d'autorisation de modification peut s'afficher. Pour savoir comment résoudre ce problème, consultez Erreur 400/403 : le compte n'est pas autorisé à apporter des modifications.
Étapes suivantes
Si vous ne trouvez pas de solution à votre problème dans la documentation, consultez la section Obtenir de l'aide pour obtenir une aide supplémentaire, y compris des conseils sur les sujets suivants:
- En ouvrant une demande d'assistance en contactant l'assistance client Cloud.
- Obtenir de l'aide de la communauté en posant des questions sur StackOverflow et en utilisant la balise
google-kubernetes-engine
pour rechercher des problèmes similaires. Vous pouvez également rejoindre le canal Slack#kubernetes-engine
pour obtenir plus d'aide de la communauté. - Signaler des bugs ou des demandes de fonctionnalités à l'aide de l'outil public de suivi des problèmes