Risolvere i problemi di autenticazione di GKE


Questa pagina mostra come risolvere i problemi relativi alle configurazioni di sicurezza nei cluster Autopilot e Standard di Google Kubernetes Engine (GKE).

Se hai bisogno di ulteriore assistenza, contatta l'assistenza clienti Google Cloud.

RBAC e IAM

Gli account IAM autenticati non riescono a eseguire azioni all'interno del cluster

Il seguente problema si verifica quando provi a 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 granti la stessa autorizzazione. In caso di errore, 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 riesce ad autenticarsi su Google Cloud

Se la tua applicazione non riesce ad autenticarsi in Google Cloud, assicurati che le seguenti impostazioni siano configurate correttamente:

  1. Verifica di aver attivato l'API Credentials degli account di servizio IAM nel progetto contenente il cluster GKE.

    Attiva l'API IAM Credentials

  2. Verifica che la federazione delle identità per i carichi di lavoro per GKE sia abilitata nel cluster verificando che sia impostato un pool di identità per i carichi di lavoro:

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

    Sostituisci CLUSTER_NAME con il nome del cluster GKE.

    Se non hai già specificato una zona o una regione predefinita per gcloud, potrebbe essere necessario 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 cluster GKE.
  4. Verifica che l'account di servizio Kubernetes sia annotato correttamente:

    kubectl describe serviceaccount \
        --namespace NAMESPACE KSA_NAME
    

    Sostituisci quanto segue:

    • NAMESPACE con lo spazio dei nomi del tuo 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
    
  5. Verifica che l'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 una associazione simile alla seguente:

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    
  6. Se hai un criterio di rete del cluster, devi consentire l'uscita a 127.0.0.1/32 sulla porta 988 per i cluster che eseguono versioni di GKE precedenti alla 1.21.0-gke.1000 o a 169.254.169.252/32 sulla porta 988 per i cluster che eseguono GKE versione 1.21.0-gke.1000 e successive. Per i cluster che eseguono GKE Dataplane V2, devi consentire l'uscita su 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.

Accesso all'account di servizio IAM negato

I pod potrebbero non riuscire ad accedere a una risorsa con la federazione delle identità per i carichi di lavoro per GKE immediatamente dopo aver aggiunto le associazioni di ruoli IAM. È più probabile che si verifichi un errore di accesso nelle pipeline di deployment o nelle configurazioni declarative di Google Cloud, dove risorse come i criteri IAM, le associazioni di ruoli e i pod Kubernetes vengono create insieme. Nei log del 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 delle modifiche dell'accesso in IAM, il che significa che le modifiche dell'accesso come le concessioni dei ruoli richiedono del tempo per essere propagate nel sistema. Per le concessioni di ruoli, la propagazione richiede in genere circa due minuti, ma talvolta può richiedere sette o più minuti. Per maggiori dettagli, consulta Propagazione della modifica di accesso.

Per risolvere questo errore, ti consigliamo di aggiungere un ritardo prima che i pod provino ad accedere alle risorse Google Cloud dopo la creazione.

Problemi di risoluzione DNS

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

La modalità di rilevamento del problema dipende dai dettagli dell'applicazione di cui è stato eseguito il deployment, incluso il relativo logging. Cerca messaggi di errore che:

  • ti chiede di configurare GOOGLE_APPLICATION_CREDENTIALS oppure
  • ti comunica che le tue richieste a un servizio Google Cloud sono state rifiutate perché non contenevano credenziali.

Se riscontri problemi con la risoluzione DNS di metadata.google.internal, puoi chiedere ad alcune librerie client di Google Cloud di saltare 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"

Si tratta dell'indirizzo IP hardcoded a cui il servizio di metadati è sempre disponibile sulle piattaforme di calcolo di Google Cloud.

Librerie Google Cloud supportate:

  • Python
  • Java
  • Node.js
  • Golang (tieni presente, tuttavia, che la libreria client Golang preferisce già connettersi tramite IP anziché tramite nome DNS).

Errori di timeout all'avvio del pod

Il server dei metadati GKE ha bisogno di alcuni secondi prima di poter iniziare accettare le richieste su un nuovo pod. I tentativi di autenticazione tramite la federazione Workload Identity per GKE nei primi secondi di vita di un pod potrebbero non riuscire per le applicazioni e le librerie client di Google Cloud configurate con un timeout breve.

Se riscontri errori di timeout, prova quanto segue:

  • Aggiorna le librerie client di Google Cloud utilizzate dai tuoi carichi di lavoro.
  • Modifica il codice dell'applicazione in modo che attenda qualche secondo e riprova.
  • Esegui il deployment di un initContainer che attende che il server di metadati GKE sia pronto prima di eseguire il contenitore 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 della mancata disponibilità del control plane

Il server metadati non può restituire la federazione delle identità per i carichi di lavoro per GKE quando il piano di controllo del cluster non è disponibile. Le chiamate al server dei metadati restituiscono il codice di stato 500.

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

dial tcp 35.232.136.58:443: connect: connection refused

Questo comportamento comporta la mancata disponibilità di Workload Identity Federation per GKE.

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

L'autenticazione di Workload Identity Federation for GKE non va a buon fine nei cluster che utilizzano Istio

Quando l'applicazione si avvia 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 contenitore 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 il carico di lavoro del proxy del mesh di servizi che intercetta e reindirizza il traffico sia in esecuzione. Per i pod che utilizzano la federazione delle identità per i carichi di lavoro per GKE, queste richieste iniziali che si verificano prima dell'avvio del proxy potrebbero non raggiungere il server metadati GKE. Di conseguenza, l'autenticazione alle API Google Cloud non va a buon fine. Se non configuri le applicazioni in modo che riprovino a inviare le richieste, i carichi di lavoro potrebbero non riuscire.

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

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

    Vai a Esplora log

  2. Nel riquadro delle 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 contenitore istio-proxy è diventato attivo.

    Nell'esempio seguente, l'applicazione ha provato a effettuare una chiamata gRPC. Tuttavia, poiché il contenitore istio-proxy era ancora in fase di inizializzazione, l'applicazione ha ricevuto un errore Connection refused. Il timestamp accanto al messaggio Envoy proxy is ready indica quando il contenitore istio-proxy è diventato disponibile 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 il problema ed evitare che si ripresenti, prova una delle seguenti opzioni di configurazione per workload:

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

    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  • Configura Istio o Cloud Service Mesh per escludere l'indirizzo IP del server di metadati GKE dal reindirizzamento. Aggiungi la seguente annotazione al campo metadata.annotations della specifica del pod:

    traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32
    

In Istio open source, puoi eventualmente attenuare questo problema per tutti i pod impostando una delle seguenti opzioni di configurazione globale:

  • Escludi l'indirizzo IP del server metadati GKE dal reindirizzamento: aggiorna 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 fino all'avvio del proxy: aggiungi l'opzione di configurazione globale global.proxy.holdApplicationUntilProxyStarts con un valore di true alla configurazione di Istio.

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

Il pod DaemonSet di sistema gke-metadata-server semplifica la federazione delle identità per i carichi di lavoro per GKE sui tuoi nodi. Il pod utilizza risorse di memoria proporzionali al numero di account di servizio Kubernetes nel cluster.

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

Per identificare il problema:

  1. Trova i pod gke-metadata-server in crash 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 in crash per confermare che la causa è stata un'espulsione per esaurimento della memoria:

    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 account di servizio nel cluster a meno di 3000.

La federazione delle identità per i carichi di lavoro per GKE non riesce ad attivarsi con il messaggio di errore DeployPatch failed

GKE utilizza l'agente di servizio Kubernetes Engine gestito da Google Cloud per semplificare la federazione delle identità per i carichi di lavoro per GKE nei tuoi cluster. Google Cloud assegna automaticamente a questo agente di servizio il ruolo Agente di servizio Kubernetes Engine (roles/container.serviceAgent) nel tuo progetto quando attivi l'API Google Kubernetes Engine.

Se provi ad attivare la federazione delle identità per i carichi di lavoro per GKE sui cluster di un progetto in cui l'agente di servizio non dispone del ruolo Agente di servizio Kubernetes Engine, l'operazione non va a buon fine con un messaggio di errore simile al seguente:

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

Per risolvere il problema, prova a procedere nel seguente modo:

  1. Verifica che l'agente di servizio esista nel progetto e sia 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 ID progetto Google Cloud.

    Se l'agente di servizio è configurato correttamente, l'output mostra l'identità completa dell'agente di servizio:

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

    Se l'output non mostra l'agente di servizio, devi concedergli il ruolo Agente di servizio Kubernetes Engine. Per concedere questo ruolo, completa i seguenti passaggi.

  2. Ottieni il numero del tuo progetto Google Cloud:

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

    L'output è simile al seguente:

    123456789012
    
  3. Concedi all'agente di servizio il ruolo:

    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 numero del tuo progetto Google Cloud.

  4. Prova ad abilitare di nuovo la federazione delle identità per i carichi di lavoro per GKE.

Passaggi successivi

Se hai bisogno di ulteriore assistenza, contatta l'assistenza clienti Google Cloud.