La configurazione errata o la mancanza di autorizzazioni per i service account di Google Kubernetes Engine (GKE) possono causare vari problemi, ad esempio la mancata registrazione dei nodi o l'impossibilità per i workload di accedere ai Google Cloud servizi.
Utilizza questo documento per mitigare i problemi causati da service account configurati in modo errato, disabilitati o eliminati.
Queste informazioni sono importanti per gli amministratori e gli operatori della piattaforma e per gli ingegneri della sicurezza che configurano e gestiscono le autorizzazioni IAM a livello di progetto per i nodi GKE e i componenti GKE di base. Per ulteriori informazioni sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei Google Cloud contenuti, consulta Ruoli e attività comuni degli utenti GKE.
Concedere il ruolo richiesto per GKE ai service account dei nodi
Per i cluster GKE che utilizzano la versione 1.33 o precedenti di Kubernetes, i
service account IAM utilizzati dai nodi GKE
devono disporre di tutte le autorizzazioni incluse nel
ruolo IAM Kubernetes Engine Default Node Service Account
(roles/container.defaultNodeServiceAccount). Se a un account di servizio dei nodi GKE mancano una o più di queste autorizzazioni, GKE non può eseguire attività di sistema come le seguenti:
- Inviare i log di sistema e delle applicazioni dai nodi a Cloud Logging.
- Inviare le metriche di sistema e delle applicazioni dai nodi a Cloud Monitoring.
- Gestire il profilo di prestazioni di Horizontal Pod Autoscaler.
I service account dei nodi potrebbero non disporre di determinate autorizzazioni richieste per motivi come i seguenti:
- L'organizzazione applica il
iam.automaticIamGrantsForDefaultServiceAccountsvincolo della policy dell'organizzazione, che impedisce Google Cloud di concedere automaticamente i ruoli IAM ai service account IAM predefiniti. - Il ruolo IAM che concedi ai service account dei nodi personalizzati non include tutte le autorizzazioni richieste incluse nel ruolo
roles/container.defaultNodeServiceAccount.
Se al account di servizio dei nodi mancano le autorizzazioni richieste da GKE, potresti visualizzare errori e avvisi come i seguenti:
- Nella Google Cloud console, nella pagina Cluster Kubernetes, viene visualizzato un messaggio di errore Concedi autorizzazioni critiche nella colonna Notifiche per un cluster specifico.
Nella Google Cloud console, nella pagina dei dettagli del cluster per un cluster specifico, viene visualizzato il seguente messaggio di errore:
Grant roles/container.defaultNodeServiceAccount role to Node service account to allow for non-degraded operations.In Audit log di Cloud, i log delle attività di amministrazione per Google Cloud le API come
monitoring.googleapis.comhanno i seguenti valori se al account di servizio dei nodi mancano le autorizzazioni corrispondenti per accedere a queste API:- Gravità:
ERROR - Messaggio:
Permission denied (or the resource may not exist)
- Gravità:
I log per nodi specifici non sono presenti in Cloud Logging e i log dei pod per l'agente di logging su questi nodi mostrano errori
401. Per ottenere questi log dei pod, esegui il comando seguente:[[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"Se l'output è
true, il workload di sistema sta riscontrando errori401, che indicano una mancanza di autorizzazioni.
Per risolvere il problema, concedi il ruolo Kubernetes Engine Default Node Service Account (roles/container.defaultNodeServiceAccount) nel progetto al service account che causa gli errori. Seleziona una delle seguenti opzioni:
console
Per trovare il nome del account di servizio utilizzato dai nodi:
Vai alla pagina Cluster Kubernetes:
Nell'elenco dei cluster, fai clic sul nome del cluster che vuoi ispezionare.
Trova il nome del account di servizio dei nodi. Avrai bisogno di questo nome in un secondo momento.
- Per i cluster in modalità Autopilot, nella sezione Sicurezza , trova il campo Service account.
- Per i cluster in modalità Standard:
- Fai clic sulla scheda Nodi.
- Nella tabella Node pool, fai clic sul nome di un pool di nodi. Si apre la pagina Dettagli del node pool.
- Nella sezione Sicurezza, trova il campo Service account.
Se il valore nel campo Service account è
default, i nodi utilizzano il account di servizio predefinito di Compute Engine. Se il valore in questo campo non èdefault, i nodi utilizzano un account di servizio personalizzato.
Per concedere il ruolo Kubernetes Engine Default Node Service Account al account di servizio:
Vai alla pagina Benvenuto:
Nel campo Numero progetto, fai clic Copia negli appunti.
Vai alla pagina IAM:
Fai clic su Concedi l'accesso.
Nel campo Nuove entità, specifica il nome del service account dei nodi. Se i nodi utilizzano il service account predefinito di Compute Engine, specifica il seguente valore:
PROJECT_NUMBER-compute@developer.gserviceaccount.comSostituisci
PROJECT_NUMBERcon il numero del progetto che hai copiato.Nel menu Seleziona un ruolo, seleziona il ruolo Kubernetes Engine Default Node Service Account.
Fai clic su Salva.
Per verificare che il ruolo sia stato concesso:
- Nella pagina IAM, fai clic sulla scheda Visualizza per ruoli.
- Espandi la sezione Kubernetes Engine Default Node Service Account. Viene visualizzato un elenco delle entità che hanno questo ruolo.
- Trova il account di servizio dei nodi nell'elenco delle entità.
gcloud
Trova il nome del account di servizio utilizzato dai nodi:
- Per i cluster in modalità Autopilot, esegui il comando seguente:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount- Per i cluster in modalità Standard, esegui il comando seguente:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="table(nodePools.name,nodePools.config.serviceAccount)"Se l'output è
default, i nodi utilizzano il account di servizio predefinito di Compute Engine. Se l'output non èdefault, i nodi utilizzano un account di servizio personalizzato.Trova il tuo Google Cloud numero di progetto:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"Sostituisci
PROJECT_IDcon l'ID progetto.L'output è simile al seguente:
12345678901Concedi il ruolo
roles/container.defaultNodeServiceAccountal account di servizio:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="SERVICE_ACCOUNT_NAME" \ --role="roles/container.defaultNodeServiceAccount"Sostituisci
SERVICE_ACCOUNT_NAMEcon il nome del account di servizio che hai trovato nel passaggio precedente. Se i nodi utilizzano il account di servizio predefinito di Compute Engine, specifica il seguente valore:serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.comSostituisci
PROJECT_NUMBERcon il numero del progetto del passaggio precedente.Verifica che il ruolo sia stato concesso correttamente:
gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \ --format='value(bindings.members)'L'output è il nome del tuo account di servizio.
Identificare i cluster con service account dei nodi a cui mancano le autorizzazioni
Utilizza i consigli di GKE del NODE_SA_MISSING_PERMISSIONS
sottotipo di recommender per
identificare i cluster Autopilot e Standard con service account dei nodi a cui mancano le autorizzazioni. Recommender identifica solo i cluster creati a partire dal 1° gennaio 2024. Per trovare e correggere le autorizzazioni mancanti utilizzando Recommender:
Trova i consigli attivi nel tuo progetto per il sottotipo di recommender
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"Sostituisci quanto segue:
LOCATION: la località in cui trovare i consigli.PROJECT_ID: l' Google Cloud ID progetto.
L'output è simile al seguente, che indica che un cluster ha un account di servizio dei nodi a cui mancano le autorizzazioni:
associatedInsights: # lines omitted for clarity recommenderSubtype: NODE_SA_MISSING_PERMISSIONS stateInfo: state: ACTIVE targetResources: - //container.googleapis.com/projects/12345678901/locations/us-central1/clusters/cluster-1Potrebbero essere necessarie fino a 24 ore prima che il consiglio venga visualizzato. Per istruzioni dettagliate, vedi Visualizzare approfondimenti e consigli.
Per ogni cluster nell'output del passaggio precedente, trova i service account dei nodi associati e concedi il ruolo richiesto a questi service account. Per maggiori dettagli, consulta le istruzioni nella sezione Concedere ai service account dei nodi il ruolo richiesto per GKE.
Dopo aver concesso il ruolo richiesto ai service account dei nodi identificati, il suggerimento potrebbe rimanere attivo per un massimo di 24 ore, a meno che tu non lo ignori manualmente.
Identificare tutti i service account dei nodi a cui mancano le autorizzazioni
Puoi eseguire uno script che cerca i node pool nei cluster Standard
e Autopilot del tuo progetto per trovare eventuali service account dei nodi che non dispongono delle autorizzazioni richieste
per GKE. Questo script utilizza gcloud CLI e l'
jq utilità. Per visualizzare lo script, espandi la sezione seguente:
Visualizza lo 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.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.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"
fiQuesto script si applica a tutti i cluster GKE del tuo progetto.
Dopo aver identificato i nomi dei service account a cui mancano le autorizzazioni, concedi loro il ruolo richiesto. Per maggiori dettagli, consulta le istruzioni nella sezione Concedere ai service account dei nodi il ruolo richiesto per GKE.
Ripristinare il account di servizio predefinito nel Google Cloud progetto
Il account di servizio predefinito di GKE, container-engine-robot, può essere scollegato accidentalmente da un progetto. Il
ruolo Kubernetes Engine Service Agent
(roles/container.serviceAgent) è un ruolo Identity and Access Management (IAM)
che concede al account di servizio le autorizzazioni per gestire le risorse del cluster. Se rimuovi questa associazione di ruoli dal account di servizio, il service account predefinito viene scollegato dal progetto, il che può impedirti di eseguire il deployment delle applicazioni e di eseguire altre operazioni del cluster.
Per verificare se il account di servizio è stato rimosso dal progetto, puoi utilizzare la Google Cloud console o Google Cloud CLI.
Console
Nella Google Cloud console, vai alla pagina IAM e amministrazione.
gcloud
Esegui questo comando:
gcloud projects get-iam-policy PROJECT_IDSostituisci
PROJECT_IDcon l'ID progetto.
Se la dashboard o il comando non visualizza container-engine-robot tra i tuoi service account, il ruolo non è associato.
Per ripristinare l'associazione del ruolo Kubernetes Engine Service Agent
(roles/container.serviceAgent), esegui questi comandi:
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
Verifica che l'associazione di ruoli sia stata ripristinata:
gcloud projects get-iam-policy PROJECT_ID
Se vedi il nome del account di servizio insieme al ruolo container.serviceAgent, l'associazione di ruoli è stata ripristinata. Ad esempio:
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Abilitare il account di servizio predefinito di Compute Engine
Il account di servizio utilizzato per il pool di nodi è in genere il service account predefinito di Compute Engine. Se questo account di servizio predefinito è disattivato, i nodi potrebbero non registrarsi nel cluster.
Per verificare se il account di servizio è disattivato nel tuo progetto, puoi utilizzare la Google Cloud console o gcloud CLI.
Console
Nella Google Cloud console, vai alla pagina IAM e amministrazione.
gcloud
- Esegui questo comando:
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
Se il account di servizio è disattivato, esegui questi comandi per attivarlo:
Trova il tuo Google Cloud numero di progetto:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"Sostituisci
PROJECT_IDcon l'ID progetto.L'output è simile al seguente:
12345678901Abilita il account di servizio:
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.comSostituisci
PROJECT_NUMBERcon il numero del progetto dell'output del passaggio precedente.
Per ulteriori informazioni, vedi Risolvere i problemi di registrazione dei nodi.
Errore 400/403: autorizzazioni di modifica mancanti nell'account
Se il account di servizio viene eliminato, potresti visualizzare un errore relativo alle autorizzazioni di modifica mancanti. Per scoprire come risolvere questo errore, vedi Errore 400/403: autorizzazioni di modifica mancanti nell'account.
Passaggi successivi
Se non riesci a trovare una soluzione al tuo problema nella documentazione, consulta Richiedere assistenza per ulteriore aiuto, inclusi consigli sui seguenti argomenti:
- Aprire una richiesta di assistenza contattando l'assistenza clienti Google Cloud.
- Ricevere assistenza dalla community ponendo domande su Stack Overflow e utilizzando il tag
google-kubernetes-engineper cercare problemi simili. Puoi anche unirti al#kubernetes-enginecanale Slack per ulteriore assistenza dalla community. - Aprire richieste di funzionalità o problemi utilizzando lo strumento di monitoraggio dei problemi pubblico.