Risolvere i problemi di autenticazione di GKE


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

RBAC e IAM

Gli account IAM autenticati non riescono a eseguire azioni nel 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. In caso di errore, viene visualizzato un messaggio 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 per gli oggetti roles nello spazio dei nomi kube-system. Per istruzioni, vedi Autorizzare le azioni nei cluster utilizzando il controllo dell'accesso basato sui ruoli.

Federazione delle identità per i workload per GKE

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

Se la tua applicazione non può autenticarsi su 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.

    Attiva l'API IAM Credentials

  2. Verifica che la federazione delle identità per i carichi di lavoro per GKE sia abilitata sul cluster controllando 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 tuo cluster GKE.

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

  3. Assicurati che il server metadati GKE sia configurato sul 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. 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 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 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 binding simile al 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 a 169.254.169.254/32 sulla porta 80.

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

    Sostituisci NETWORK_POLICY_NAME con il nome della tua policy di rete GKE.

Accesso negato all'account di servizio IAM

I pod potrebbero non riuscire ad accedere a una risorsa con la federazione delle identità per i carichi di lavoro per GKE immediatamente dopo l'aggiunta dei binding dei ruoli IAM. È più probabile che si verifichi un errore di accesso nelle pipeline di deployment o nelle configurazioni dichiarative Google Cloud in cui vengono create insieme risorse come policy di autorizzazione IAM, associazioni di ruoli e pod Kubernetes. Nel 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 all'accesso, come le concessioni di ruoli, richiedono tempo per propagarsi 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, vedi Propagazione della modifica di accesso.

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

Problemi di risoluzione DNS

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

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

Il modo in cui rilevi questo problema dipende dai dettagli dell'applicazione di cui è stato eseguito il deployment, inclusa la configurazione del logging. Cerca messaggi di errore che ti chiedono di configurare GOOGLE_APPLICATION_CREDENTIALS, che ti comunicano che le tue richieste a un servizioGoogle Cloud sono state rifiutate perché la richiesta non aveva credenziali o che il server dei 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, alcune librerie client Google Cloud possono essere istruite a 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'indirizzo IP hardcoded in cui il servizio di metadati è sempre disponibile sulle piattaforme di calcolo Google Cloud .

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 dei metadati GKE ha bisogno di alcuni secondi prima di poter iniziare ad accettare richieste su un nuovo pod. I tentativi di autenticazione utilizzando Workload Identity Federation per GKE nei primi secondi di vita di un pod potrebbero non riuscire per applicazioni e Google Cloud librerie client configurate con un timeout breve.

Se riscontri errori di timeout, prova quanto segue:

  • Aggiorna le librerie client Google Cloud utilizzate dai tuoi carichi di lavoro.
  • Modifica il codice dell'applicazione in modo che attenda qualche secondo e riprovi.
  • Esegui il deployment di un initContainer che attende che il server di 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 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.

Una voce di log potrebbe essere simile alla seguente in Esplora log:

dial tcp 35.232.136.58:443: connect: connection refused

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

Il control plane potrebbe non essere disponibile sui cluster di zona durante la manutenzione del cluster, ad esempio la rotazione degli indirizzi IP, l'upgrade delle VM del control plane o il ridimensionamento dei cluster o dei node pool. Consulta Scelta di un control plane regionale o zonale per scoprire di più sulla disponibilità del control plane. Il passaggio a un cluster a livello di regione elimina questo problema.

L'autenticazione di Workload Identity Federation for GKE non riesce nei cluster che utilizzano Istio

All'avvio dell'applicazione e quando 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 demesh di servizish 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 riesce. Se non configuri le tue applicazioni in modo da riprovare a inviare le richieste, i tuoi carichi di lavoro potrebbero non riuscire.

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

  1. Nella console Google Cloud , 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 messaggio Envoy proxy is ready indica quando il contenitore istio-proxy è 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 il problema ed evitare che si ripresenti, prova una delle seguenti opzioni di configurazione per workload:

  • Impedisci alle tue 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 mitigare facoltativamente questo problema per tutti i pod impostando una delle seguenti opzioni di configurazione globali:

  • 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 finché il proxy non viene avviato: 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 facilita la federazione delle identità per i carichi di lavoro per 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 esaurimento della memoria. Potresti riscontrare questo problema se il tuo cluster ha più di 3000 service account Kubernetes.

Per identificare il problema:

  1. Trova i pod gke-metadata-server che vanno in arresto 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 in arresto anomalo 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 service account nel cluster a meno di 3000.

L'attivazione di Workload Identity Federation for GKE non riesce e viene visualizzato il messaggio di errore DeployPatch failed

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

Se tenti di abilitare 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 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 procedere nel seguente modo:

  1. Verifica che l'agente di servizio esista nel tuo 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 l'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. Recupera 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 di nuovo ad abilitare la federazione delle identità per i carichi di lavoro per GKE.

Passaggi successivi