Cette page vous aide à résoudre les problèmes liés au pipeline de journalisation Google Kubernetes Engine (GKE) lui-même, par exemple lorsque les journaux n'apparaissent pas dans Cloud Logging. Pour en savoir plus sur l'utilisation des journaux pour résoudre les problèmes liés à vos charges de travail et clusters, consultez Présentation du dépannage GKE.
Journaux de clusters manquants dans Cloud Logging
Vérifiez que la journalisation est activée dans le projet
Répertoriez les services activés :
gcloud services list --enabled --filter="NAME=logging.googleapis.com"
Le résultat suivant indique que la journalisation est activée pour le projet :
NAME TITLE logging.googleapis.com Cloud Logging API
Facultatif: Consultez les journaux dans la visionneuse de journaux pour déterminer qui a désactivé l'API et quand :
protoPayload.methodName="google.api.serviceusage.v1.ServiceUsage.DisableService" protoPayload.response.services="logging.googleapis.com"
Si la journalisation est désactivée, activez-là :
gcloud services enable logging.googleapis.com
Vérifiez que la journalisation est activée sur le cluster
Répertoriez les clusters :
gcloud container clusters list \ --project=PROJECT_ID \ '--format=value(name,loggingConfig.componentConfig.enableComponents)' \ --sort-by=name | column -t
Remplacez les éléments suivants :
PROJECT_ID
: ID de votre projet Trusted Cloud by S3NS .
Le résultat ressemble à ce qui suit :
cluster-1 SYSTEM_COMPONENTS cluster-2 SYSTEM_COMPONENTS;WORKLOADS cluster-3
Si la valeur correspondant à votre cluster est vide, la journalisation est désactivée. Par exemple,
cluster-3
dans cette sortie a la journalisation désactivée.Activez la journalisation des clusters si elle est définie sur
NONE
:gcloud container clusters update CLUSTER_NAME \ --logging=SYSTEM,WORKLOAD \ --location=COMPUTE_LOCATION
Remplacez les éléments suivants :
CLUSTER_NAME
: nom du clusterCOMPUTE_LOCATION
: emplacement Compute Engine de votre cluster.
Après avoir vérifié que vous avez activé la journalisation dans votre projet et sur le cluster, envisagez d'utiliser les enquêtes Gemini Cloud Assist pour obtenir des informations supplémentaires sur vos journaux et résoudre les problèmes. Pour en savoir plus sur les différentes façons de lancer une investigation à l'aide de l'explorateur de journaux, consultez Résoudre les problèmes liés aux investigations Gemini Cloud Assist dans la documentation Gemini.
Vérifier que les nœuds des pools de nœuds disposent du niveau d'accès à Cloud Logging
L'un des champs d'application suivants est nécessaire pour que les nœuds écrivent des journaux dans Cloud Logging :
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/logging.admin
Vérifiez les champs d'application configurés sur chaque pool de nœuds du cluster :
gcloud container node-pools list --cluster=CLUSTER_NAME \ --format="table(name,config.oauthScopes)" \ --location COMPUTE_LOCATION
Remplacez les éléments suivants :
CLUSTER_NAME
: nom du clusterCOMPUTE_LOCATION
: emplacement Compute Engine de votre cluster.
Migrez vos charges de travail de l'ancien pool de nœuds vers le nouveau pool de nœuds et surveillez la progression.
Créez des pools de nœuds avec le champ d'application de journalisation approprié :
gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --scopes="gke-default"
Remplacez les éléments suivants :
CLUSTER_NAME
: nom du clusterCOMPUTE_LOCATION
: emplacement Compute Engine de votre cluster.
Identifier les clusters dont les comptes de service de nœud ne disposent pas d'autorisations critiques
Pour identifier les clusters dont les comptes de service de nœuds ne disposent pas des autorisations critiques, utilisez les recommandations GKE du sous-type de recommandation NODE_SA_MISSING_PERMISSIONS
:
- Utilisez la console Trusted Cloud . Accédez à la page Clusters Kubernetes. Dans la colonne Notifications pour des clusters spécifiques, recherchez la recommandation Accorder des autorisations critiques.
Utilisez la gcloud CLI ou l'API Recommender en spécifiant le sous-type de recommandation
NODE_SA_MISSING_PERMISSIONS
.Pour interroger cette recommandation, exécutez la commande suivante :
gcloud recommender recommendations list \ --recommender=google.container.DiagnosisRecommender \ --location LOCATION \ --project PROJECT_ID \ --format yaml \ --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
Pour appliquer cette recommandation, attribuez le rôle roles/container.defaultNodeServiceAccount
au compte de service du nœud.
Vous pouvez exécuter un script qui recherche les comptes de service de nœud dans les clusters Standard et Autopilot de votre projet 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}-compute@developer.s3ns-system.iam.gserviceaccount.com"
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}-compute@developer.s3ns-system.iam.gserviceaccount.com"
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
Identifier les comptes de service de nœud qui ne disposent pas d'autorisations critiques dans un cluster
GKE utilise des comptes de service IAM associés à vos nœuds pour exécuter des tâches système telles que la journalisation et la surveillance. Au minimum, ces comptes de service de nœud doivent disposer du rôle Compte de service de nœud par défaut Kubernetes Engine (roles/container.defaultNodeServiceAccount
) sur votre projet. Par défaut, GKE utilise le compte de service Compute Engine par défaut, qui est créé automatiquement dans votre projet, en tant que compte de service de nœud.
Si votre organisation applique la contrainte de règle d'administration iam.automaticIamGrantsForDefaultServiceAccounts
, il est possible que le compte de service Compute Engine par défaut de votre projet n'obtienne pas automatiquement les autorisations requises pour GKE.
Pour vérifier si des autorisations de journalisation sont manquantes, recherchez les erreurs
401
dans la journalisation de votre cluster :[[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"
Si le résultat est
true
, cela signifie que la charge de travail du système rencontre des erreurs401
, qui indiquent un manque d'autorisations. Si le résultat estfalse
, ignorez le reste de ces étapes et essayez une autre procédure de dépannage.Pour identifier toutes les autorisations critiques manquantes, consultez le script.
-
Recherchez le nom du compte de service utilisé par vos nœuds :
Console
- Accédez à la page Clusters Kubernetes :
- Dans la liste des clusters, cliquez sur le nom du cluster que vous souhaitez inspecter.
- En fonction du mode de fonctionnement du cluster, effectuez l'une des opérations suivantes :
- 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 requis à un compte de service personnalisé, consultez Utiliser le principe du moindre privilège pour les comptes de service IAM.gcloud
Pour les clusters en mode Autopilot, exécutez la commande suivante :
gcloud container clusters describe
CLUSTER_NAME
\ --location=LOCATION
\ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccountPour 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 le résultat est
default
, vos nœuds utilisent le compte de service Compute Engine par défaut. Si le résultat n'est pasdefault
, vos nœuds utilisent un compte de service personnalisé. Pour attribuer le rôle requis à un compte de service personnalisé, consultez Utiliser le principe du moindre privilège pour les comptes de service IAM. -
Pour attribuer le rôle
roles/container.defaultNodeServiceAccount
au compte de service Compute Engine par défaut, procédez comme suit :Console
- 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 la valeur suivante :
RemplacezPROJECT_NUMBER-compute@developer.s3ns-system.iam.gserviceaccount.com
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.
gcloud
- Recherchez le numéro de votre projet Trusted Cloud :
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 Compute Engine par défaut :gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.s3ns-system.iam.gserviceaccount.com" \ --role="roles/container.defaultNodeServiceAccount"
Remplacez
PROJECT_NUMBER
par le numéro de projet de l'étape précédente.
- Vérifiez que les comptes de service des nœuds disposent des autorisations requises. Vérifiez le script pour le confirmer.
Script permettant d'identifier les autorisations manquantes pour le compte de service des nœuds GKE
Vous pouvez exécuter un script qui recherche les comptes de service de nœud dans les clusters Standard et Autopilot de votre projet 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}-compute@developer.s3ns-system.iam.gserviceaccount.com"
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}-compute@developer.s3ns-system.iam.gserviceaccount.com"
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
Vérifier que les quotas d'écriture de l'API Cloud Logging n'ont pas été atteints
Vérifiez que vous n'avez pas atteint les quotas d'écriture de l'API Cloud Logging.
Accédez à la page Quotas de la console Trusted Cloud .
Filtrez le tableau avec l'expression "Cloud Logging API".
Vérifiez que vous n'avez atteint aucun quota.