Risolvi i problemi di autenticazione di GKE

I problemi di autenticazione in Google Kubernetes Engine (GKE) possono impedire alle entità, come utenti e carichi di lavoro, di accedere al server API Kubernetes o ostacolare l'accesso tra le risorse GKE e altri Google Cloud servizi.

Utilizza questo documento per diagnosticare i problemi di autenticazione, correggere gli errori in Kubernetes RBAC e IAM e risolvere i problemi relativi a Workload Identity Federation for GKE.

Queste informazioni sono importanti per gli amministratori e gli operatori della piattaforma e per gli amministratori della sicurezza responsabili della protezione dei cluster GKE e della gestione del controllo dell'accesso. Per saperne di più sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei Google Cloud contenuti, consulta Ruoli e attività comuni degli utenti GKE.

RBAC e IAM

Gli account IAM autenticati non riescono a eseguire azioni in-cluster

Il seguente problema si verifica quando tenti di eseguire un'azione nel cluster, ma GKE non riesce a trovare un criterio RBAC che autorizzi l'azione. GKE tenta di trovare un criterio di autorizzazione IAM che conceda la stessa autorizzazione. Se l'operazione non riesce, viene visualizzato un messaggio di errore simile al seguente:

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

Per risolvere il problema, utilizza un criterio RBAC per concedere le autorizzazioni per l'azione tentata. Ad esempio, per risolvere il problema nell'esempio precedente, concedi un ruolo con l'autorizzazione list sugli oggetti roles nello spazio dei nomi kube-system. Per istruzioni, consulta Autorizzare le azioni nei cluster utilizzando il controllo dell'accesso basato sui ruoli.

Workload Identity Federation for GKE

Il pod non può eseguire l'autenticazione a Google Cloud

Se la tua applicazione non riesce a eseguire l'autenticazione a Google Cloud, assicurati che le seguenti impostazioni siano configurate correttamente:

  1. Verifica di aver abilitato l'API IAM Service Account Credentials nel progetto contenente il cluster GKE.

    Abilita l'API IAM Credentials

  2. Verifica che Workload Identity Federation for GKE sia abilitato sul cluster controllando che abbia un pool di identità del workload impostato:

    gcloud container clusters describe CLUSTER_NAME \
        --format="value(workloadIdentityConfig.workloadPool)"
    

    Sostituisci CLUSTER_NAME con il nome del tuo cluster GKE.

    Se non hai ancora specificato una zona o una regione predefinita per gcloud, potresti dover specificare anche un flag --region o --zone quando esegui questo comando.

  3. Assicurati che il server metadati GKE sia configurato nel pool di nodi in cui è in esecuzione l'applicazione:

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --format="value(config.workloadMetadataConfig.mode)"
    

    Sostituisci quanto segue:

    • NODEPOOL_NAME con il nome del tuo node pool.
    • CLUSTER_NAME con il nome del tuo cluster GKE.
  4. Se hai un criterio di rete del cluster, devi consentire il traffico in uscita verso 169.254.169.252/32 sulla porta 988. Per i cluster che eseguono GKE Dataplane V2, devi consentire il traffico in uscita verso 169.254.169.254/32 sulla porta 80.

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

    Sostituisci NETWORK_POLICY_NAME con il nome del tuo criterio di rete GKE.

Se la configurazione collega i service account Kubernetes ai service account IAM, verifica quanto segue:

  1. Verifica che il account di servizio Kubernetes sia annotato correttamente:

    kubectl describe serviceaccount \
        --namespace NAMESPACE KSA_NAME
    

    Sostituisci quanto segue:

    • NAMESPACE con lo spazio dei nomi del cluster GKE.
    • KSA con il nome del tuo account di servizio Kubernetes.

    L'output previsto contiene un'annotazione simile alla seguente:

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  2. Verifica che il account di servizio IAM sia configurato correttamente:

    gcloud iam service-accounts get-iam-policy \
        GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
    

    L'output previsto contiene un'associazione simile alla seguente:

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    

Errore: formato non valido dell'ID account

Il seguente errore si verifica quando tenti di eseguire un'operazione che richiede un indirizzo email del account di servizio IAM, ad esempio la creazione manuale di un URL firmato di Cloud Storage:

ERROR: Error: Invalid form of account ID test_account.svc.id.goog. Should be [Gaia ID |Email |Unique ID |] of the account
# Multiple lines are omitted here
command terminated with exit code 137

Questo errore si verifica quando utilizzi un'annotazione per collegare i service account Kubernetes ai service account IAM anziché utilizzare un identificatore dell'entità IAM per configurare Workload Identity Federation for GKE.

Per impostazione predefinita, il server metadati GKE restituisce un valore di SERVICEACCOUNT_NAME.svc.id.goog come identificatore del account di servizio per i service account collegati. Questo identificatore non utilizza la sintassi dell'identificatore dell'entità IAM.

Per risolvere questo errore, aggiungi l'iam.gke.io/return-principal-id-as-email="true" annotazione al service account Kubernetes del pod:

kubectl annotate serviceaccount KSA_NAME \
    --namespace=NAMESPACE \
    iam.gke.io/return-principal-id-as-email="true"

Sostituisci quanto segue:

  • KSA_NAME: il nome del service account Kubernetes.
  • NAMESPACE: lo spazio dei nomi del service account.

Accesso al account di servizio IAM negato

I pod potrebbero non riuscire ad accedere a una risorsa con Workload Identity Federation for GKE immediatamente dopo l'aggiunta delle associazioni di ruoli IAM. È più probabile che si verifichi un errore di accesso nelle pipeline di deployment o nelle configurazioni dichiarative in cui vengono create insieme risorse come i criteri di autorizzazione IAM, le associazioni di ruoli e i pod Kubernetes. Google Cloud Nei log dei pod viene visualizzato il seguente messaggio di errore:

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

Questo errore potrebbe essere causato dalla propagazione della modifica dell'accesso in IAM, il che significa che le modifiche dell'accesso, come le concessioni di ruoli, richiedono tempo per essere propagate nel sistema. Per le concessioni di ruoli, la propagazione richiede in genere circa due minuti, ma a volte può richiedere sette o più minuti. Per maggiori dettagli, consulta Propagazione della modifica dell'accesso.

Per risolvere questo errore, valuta la possibilità di aggiungere un ritardo prima che i pod tentino di accedere Google Cloud alle risorse dopo la creazione.

Problemi di risoluzione DNS

Questa sezione descrive come identificare e risolvere gli errori di connessione dai pod alle Google Cloud API causati da problemi di risoluzione DNS. Se i passaggi descritti in questa sezione non risolvono gli errori di connessione, consulta la sezione Errori di timeout all'avvio del pod.

Alcune Google Cloud librerie client sono configurate per connettersi ai server metadati GKE e Compute Engine risolvendo il nome DNS metadata.google.internal. Per queste librerie, una risoluzione DNS in-cluster integra è una dipendenza fondamentale per l'autenticazione dei carichi di lavoro ai Google Cloud servizi.

La modalità di rilevamento di questo problema dipende dai dettagli dell'applicazione di cui hai eseguito il deployment, inclusa la configurazione della registrazione. Cerca messaggi di errore che ti chiedono di configurare GOOGLE_APPLICATION_CREDENTIALS, che ti informano che le tue richieste a un Google Cloud servizio sono state rifiutate perché la richiesta non aveva credenziali, o che il server metadati non è stato trovato.

Ad esempio, il seguente messaggio di errore potrebbe indicare un problema di risoluzione DNS:

ComputeEngineCredentials cannot find the metadata server. This is likely because code is not running on Google Compute Engine

Se riscontri problemi con la risoluzione DNS di metadata.google.internal, puoi indicare ad alcune Google Cloud librerie client di ignorare la risoluzione DNS impostando la variabile di ambiente GCE_METADATA_HOST su 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"

Questo è l'indircoded IP address in cui il servizio metadati è sempre disponibile sulle Google Cloud piattaforme di calcolo.

Sono supportate le seguenti Google Cloud librerie:

  • Python
  • Java
  • Node.js
  • Golang

    Per impostazione predefinita, la libreria client Go si connette utilizzando l'indirizzo IP.

Errori di timeout all'avvio del pod

Il server metadati GKE richiede alcuni secondi prima di poter iniziare ad accettare richieste su un nuovo pod. I tentativi di autenticazione utilizzando Workload Identity Federation for GKE nei primi secondi di vita di un pod potrebbero non riuscire per le applicazioni e le Google Cloud librerie client configurate con un timeout breve.

Se riscontri errori di timeout, prova a eseguire le seguenti operazioni:

  • Aggiorna le Google Cloud librerie client utilizzate dai carichi di lavoro.
  • Modifica il codice dell'applicazione in modo che attenda alcuni secondi e riprovi.
  • Esegui il deployment di un initContainer che attende che il server metadati GKE sia pronto prima di eseguire il container principale del pod.

    Ad esempio, il seguente manifest è per un pod con un 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
    

Workload Identity Federation for GKE non riesce a causa dell'indisponibilità del piano di controllo

Il server metadati non può restituire Workload Identity Federation for GKE quando il piano di controllo del cluster non è disponibile. Le chiamate al server metadati restituiscono il codice di stato 500.

In Esplora log potrebbe essere visualizzata una voce di log simile alla seguente:

dial tcp 35.232.136.58:443: connect: connection refused

Questo comportamento comporta l'indisponibilità di Workload Identity Federation for GKE.

Il piano di controllo potrebbe non essere disponibile nei cluster zonali durante la manutenzione del cluster, ad esempio la rotazione degli indirizzi IP, l'upgrade delle VM del piano di controllo o il ridimensionamento dei cluster o dei node pool. Consulta la sezione Scegliere un piano di controllo regionale o zonale per scoprire di più sulla disponibilità del piano di controllo. Il passaggio a un cluster regionale elimina questo problema.

L'autenticazione di Workload Identity Federation for GKE non riesce nei cluster che utilizzano Cloud Service Mesh o Istio OSS

Quando l'applicazione viene avviata nei cluster che utilizzano i sidecar di Cloud Service Mesh o Istio e tenta di comunicare con un endpoint, potresti visualizzare errori simili ai seguenti:

Connection refused (169.254.169.254:80)
Connection timeout

Questi errori possono verificarsi quando l'applicazione tenta di stabilire una connessione di rete prima che il container istio-proxy sia pronto. Per impostazione predefinita, Istio e Cloud Service Mesh consentono ai carichi di lavoro di inviare richieste non appena vengono avviati, indipendentemente dal fatto che sia in esecuzione il carico di lavoro del proxy del mesh di servizi che intercetta e reindirizza il traffico. Per i pod che utilizzano Workload Identity Federation for GKE, queste richieste iniziali che si verificano prima dell'avvio del proxy potrebbero non raggiungere il server metadati GKE. Di conseguenza, l'autenticazione alle Google Cloud API non riesce. Se non configuri le applicazioni in modo che ritentino le richieste, i carichi di lavoro potrebbero non riuscire.

Per verificare se questo problema è la causa degli errori, visualizza i log e controlla se il container istio-proxy è stato avviato correttamente:

  1. Nella Google Cloud console, vai alla pagina Esplora log.

    Vai a Esplora log

  2. Nel riquadro della query, inserisci la seguente query:

    (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")
    

    Sostituisci quanto segue:

    • POD_NAME: il nome del pod con il carico di lavoro interessato.
    • ERROR_MESSAGE: l'errore ricevuto dall'applicazione (connection timeout o connection refused).
  3. Fai clic su Esegui query.

  4. Esamina l'output e controlla quando il container istio-proxy è diventato pronto.

    Nell'esempio seguente, l'applicazione ha tentato di effettuare una chiamata gRPC. Tuttavia, poiché il container istio-proxy era ancora in fase di inizializzazione, l'applicazione ha ricevuto un errore Connection refused. Il timestamp accanto al Envoy proxy is ready messaggio indica quando il istio-proxy container è diventato pronto per le richieste di connessione:

    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
    

Per risolvere questo problema ed evitare che si ripresenti, utilizza uno dei seguenti metodi:

  • Per Cloud Service Mesh e Istio open source:

    • Impedisci ai container delle applicazioni di inviare richieste finché il carico di lavoro del proxy non è pronto aggiungendo la seguente annotazione al campo metadata.annotations nella specifica del pod:

      proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
      
    • Escludi l'indirizzo IP del server metadati GKE dal reindirizzamento aggiungendo la seguente annotazione al campo metadata.annotations della specifica del pod per configurare Istio o Cloud Service Mesh in modo da escludere 169.254.169.254/32 dal reindirizzamento:

      traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32
      
  • Solo per Istio open source, puoi facoltativamente mitigare questo problema per tutti i pod nel cluster impostando una delle seguenti opzioni di configurazione globali:

    • Escludi l'indirizzo IP del server metadati GKE dal reindirizzamento aggiornando l'opzione di configurazione globale global.proxy.excludeIPRanges per aggiungere l'intervallo di indirizzi IP 169.254.169.254/32.

    • Impedisci alle applicazioni di inviare richieste finché il proxy non viene avviato aggiungendo l' global.proxy.holdApplicationUntilProxyStarts opzione di configurazione globale con il valore true alla configurazione di Istio. Questa opzione non si applica a initContainers. Se hai initContainers che devono eseguire l'autenticazione, utilizza invece l'opzione global.proxy.excludeIPRanges.

Il pod gke-metadata-server si arresta in modo anomalo

Il pod DaemonSet di sistema gke-metadata-server facilita Workload Identity Federation for GKE sui nodi. Il pod utilizza risorse di memoria proporzionali al numero di service account Kubernetes nel cluster.

Il seguente problema si verifica quando l'utilizzo delle risorse del pod gke-metadata-server supera i limiti. Kubelet elimina il pod con un errore di memoria insufficiente. Questo problema potrebbe verificarsi se il cluster ha più di 3000 service account Kubernetes.

Per identificare il problema:

  1. Trova i pod gke-metadata-server che si arrestano in modo anomalo nello spazio dei nomi kube-system:

    kubectl get pods -n=kube-system | grep CrashLoopBackOff
    

    L'output è simile al seguente:

    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
    
  2. Descrivi il pod che si arresta in modo anomalo per verificare che la causa sia stata un'eliminazione per memoria insufficiente:

    kubectl describe pod POD_NAME --namespace=kube-system | grep OOMKilled
    

    Sostituisci POD_NAME con il nome del pod da controllare.

Per ripristinare la funzionalità del server metadati GKE, riduci il numero di service account nel cluster a meno di 3000.

Workload Identity Federation for GKE non riesce a essere abilitato con il messaggio di errore DeployPatch failed

GKE utilizza il Google Cloud-managed Kubernetes Engine Service Agent per facilitare Workload Identity Federation for GKE nei cluster. Google Cloud concede automaticamente a questo service agent il ruolo Kubernetes Engine Service Agent (roles/container.serviceAgent) nel tuo progetto quando abiliti l'API Kubernetes Engine.

Se tenti di abilitare Workload Identity Federation for GKE sui cluster in un progetto in cui il service agent non ha il ruolo Kubernetes Engine Service Agent, l'operazione non riesce e viene visualizzato un messaggio di errore simile al seguente:

Error waiting for updating GKE cluster workload identity config: DeployPatch failed

Per risolvere il problema, prova a eseguire i seguenti passaggi:

  1. Verifica se il service agent esiste nel tuo progetto ed è configurato correttamente:

    gcloud projects get-iam-policy PROJECT_ID \
        --flatten=bindings \
        --filter=bindings.role=roles/container.serviceAgent \
        --format="value[delimiter='\\n'](bindings.members)"
    

    Sostituisci PROJECT_ID con il tuo Google Cloud ID progetto.

    Se il service agent è configurato correttamente, l'output mostra l'identità completa del service agent:

    serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
    

    Se l'output non mostra il service agent, devi concedergli il ruolo Service Agent Kubernetes Engine. Per concedere questo ruolo, completa i seguenti passaggi.

  2. Recupera il numero del tuo Google Cloud progetto:

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

    L'output è simile al seguente:

    123456789012
    
  3. Concedi il ruolo al service agent:

    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
    

    Sostituisci PROJECT_NUMBER con il Google Cloud numero del tuo progetto.

  4. Prova di nuovo ad abilitare Workload Identity Federation for GKE.

Passaggi successivi