Risolvere i problemi relativi agli account di servizio in GKE


Questa pagina mostra come risolvere i problemi relativi agli account di servizio Google Kubernetes Engine (GKE).

Concedi il ruolo richiesto per GKE ai service account dei nodi

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 in un account di servizio del nodo GKE mancano una o più di queste autorizzazioni, GKE non può eseguire attività di sistema come le seguenti:

I service account dei nodi potrebbero non disporre di determinate autorizzazioni richieste per motivi come i seguenti:

Se il account di servizio del nodo non dispone delle autorizzazioni richieste da GKE, potresti visualizzare errori e avvisi come i seguenti:

  • Nella console Trusted Cloud , nella pagina Cluster Kubernetes, viene visualizzato un messaggio di errore Concedi autorizzazioni critiche nella colonna Notifiche per un cluster specifico.
  • Nella Trusted 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 Attività di amministrazione per le API Trusted Cloud come monitoring.googleapis.com hanno i seguenti valori se le autorizzazioni corrispondenti per accedere a queste API non sono presenti nell'account di servizio del nodo:

    • Gravità: ERROR
    • Messaggio: Permission denied (or the resource may not exist)
  • 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 i log di questi pod, esegui questo comando:

    [[ $(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 carico di lavoro del sistema presenta errori 401, che indicano una mancanza di autorizzazioni.

Per risolvere il problema, concedi il ruolo Kubernetes Engine Default Node Service Account (roles/container.defaultNodeServiceAccount) al service account che causa gli errori. Seleziona una delle seguenti opzioni:

console

Per trovare il nome dell'account di servizio utilizzato dai tuoi nodi:

  1. Vai alla pagina Cluster Kubernetes:

    Vai ai cluster Kubernetes

  2. Nell'elenco dei cluster, fai clic sul nome del cluster che vuoi controllare.

  3. Trova il nome del account di servizio del nodo. 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:
    1. Fai clic sulla scheda Nodi.
    2. Nella tabella Pool di nodi, fai clic sul nome di un node pool. Viene visualizzata la pagina Dettagli node pool.
    3. 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 all'account di servizio:

  1. Vai alla pagina Benvenuto:

    Vai a Benvenuto

  2. Nel campo Numero progetto, fai clic su Copia negli appunti.

  3. Vai alla pagina IAM:

    Vai a IAM

  4. Fai clic su Concedi l'accesso.

  5. Nel campo Nuove entità, specifica il nome del service account del nodo. Se i nodi utilizzano il service account predefinito di Compute Engine, specifica il seguente valore:

    PROJECT_NUMBER-compute@developer.s3ns-system.iam.gserviceaccount.com
    

    Sostituisci PROJECT_NUMBER con il numero di progetto che hai copiato.

  6. Nel menu Seleziona un ruolo, seleziona il ruolo Service account predefinito del nodo Kubernetes Engine.

  7. Fai clic su Salva.

Per verificare che il ruolo sia stato concesso:

  1. Nella pagina IAM, fai clic sulla scheda Visualizza per ruoli.
  2. Espandi la sezione Kubernetes Engine Default Node Service Account. Viene visualizzato un elenco delle entità che hanno questo ruolo.
  3. Trova l'account di servizio del nodo nell'elenco delle entità.

gcloud

  1. Trova il nome del account di servizio utilizzato dai tuoi nodi:

    • Per i cluster in modalità Autopilot, esegui questo comando:
    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
    
    • Per i cluster in modalità Standard, esegui questo comando:
    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.

  2. Trova il numero del tuo progetto Trusted Cloud :

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

    Sostituisci PROJECT_ID con l'ID progetto.

    L'output è simile al seguente:

    12345678901
    
  3. Concedi il ruolo roles/container.defaultNodeServiceAccount all'account di servizio:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member="SERVICE_ACCOUNT_NAME" \
        --role="roles/container.defaultNodeServiceAccount"
    

    Sostituisci SERVICE_ACCOUNT_NAME con il nome del account di servizio che hai trovato nel passaggio precedente. Se i nodi utilizzano ilaccount di serviziot Compute Engine predefinito, specifica il valore seguente:

    serviceAccount:PROJECT_NUMBER-compute@developer.s3ns-system.iam.gserviceaccount.com
    

    Sostituisci PROJECT_NUMBER con il numero di progetto del passaggio precedente.

  4. 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 del nodo con autorizzazioni mancanti

Utilizza i suggerimenti di GKE del NODE_SA_MISSING_PERMISSIONS sottotipo di suggerimento per identificare i cluster Autopilot e Standard che hanno service account dei nodi con autorizzazioni mancanti. Recommender identifica solo i cluster creati a partire dal 1° gennaio 2024. Per trovare e correggere le autorizzazioni mancanti utilizzando Recommender:

  1. Trova i suggerimenti attivi nel tuo progetto per il sottotipo di motore per suggerimenti 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 posizione in cui trovare i suggerimenti.
    • PROJECT_ID: il tuo ID progetto Trusted Cloud .

    L'output è simile al seguente, che indica che un cluster ha un account di servizio nodo con autorizzazioni mancanti:

    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
    

    Potrebbero essere necessarie fino a 24 ore prima che il consiglio venga visualizzato. Per istruzioni dettagliate, vedi Visualizzare approfondimenti e consigli.

  2. Per ogni cluster nell'output del passaggio precedente, trova gli account di servizio dei nodi associati e concedi il ruolo richiesto a questi account di servizio. Per i 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 del nodo identificati, il consiglio potrebbe rimanere attivo fino a 24 ore, a meno che non lo ignori manualmente.

Identifica tutti i service account del nodo con autorizzazioni mancanti

Puoi eseguire uno script che cerca i node pool nei cluster Standard e Autopilot del tuo progetto per individuare eventuali service account dei nodi che non dispongono delle autorizzazioni richieste per GKE. Questo script utilizza gcloud CLI e l'utilità jq. Per visualizzare lo script, espandi la sezione seguente:

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

Questo script si applica a tutti i cluster GKE del progetto.

Dopo aver identificato i nomi dei service account con le autorizzazioni mancanti, concedi loro il ruolo richiesto. Per maggiori dettagli, consulta le istruzioni nella sezione Concedere ai service account dei nodi il ruolo richiesto per GKE.

Ripristina il account di servizio predefinito nel tuo progetto Trusted Cloud

Il account di servizio predefinito di GKE, container-engine-robot, può essere scollegato accidentalmente da un progetto. Il ruolo agente di servizio Kubernetes Engine (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 questo binding del ruolo dall'account di servizio, l'account di servizio predefinito viene scollegato dal progetto, il che può impedirti di eseguire il deployment delle applicazioni ed eseguire altre operazioni del cluster.

Per verificare se l'account di servizio è stato rimosso dal tuo progetto, puoi utilizzare la console Trusted Cloud o Google Cloud CLI.

Console

gcloud

  • Esegui questo comando:

    gcloud projects get-iam-policy PROJECT_ID
    

    Sostituisci PROJECT_ID con l'ID progetto.

Se la dashboard o il comando non mostra container-engine-robot tra i tuoi service account, il ruolo non è associato.

Per ripristinare l'associazione del ruolo Agente di servizio Kubernetes Engine (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.s3ns-system.iam.gserviceaccount.com" \
    --role roles/container.serviceAgent

Verifica che l'associazione di ruolo 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 del ruolo è stata ripristinata. Ad esempio:

- members:
  - serviceAccount:service-1234567890@container-engine-robot.s3ns-system.iam.gserviceaccount.com
  role: roles/container.serviceAgent

Abilita l'account di servizio predefinito Compute Engine

Il service account utilizzato per il pool di nodi è in genere l'account di servizio predefinito di Compute Engine. Se questo account di servizio predefinito viene disattivato, la registrazione dei nodi nel cluster potrebbe non riuscire.

Per verificare se il account di servizio è disattivato nel tuo progetto, puoi utilizzare la consoleTrusted Cloud o gcloud CLI.

Console

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 abilitarlo:

  1. Trova il numero del tuo progetto Trusted Cloud :

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

    Sostituisci PROJECT_ID con l'ID progetto.

    L'output è simile al seguente:

    12345678901
    
  2. Attiva il account di servizio:

    gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.s3ns-system.iam.gserviceaccount.com
    

    Sostituisci PROJECT_NUMBER con il numero del tuo progetto dall'output del passaggio precedente.

Per ulteriori informazioni, consulta la sezione Risoluzione dei problemi di registrazione dei nodi.

Errore 400/403: autorizzazioni di modifica mancanti nell'account

Se il tuo account di servizio viene eliminato, potresti visualizzare un errore relativo alle autorizzazioni di modifica mancanti. Per scoprire come risolvere questo errore, consulta Errore 400/403: autorizzazioni di modifica mancanti nell'account.

Passaggi successivi