Risolvere i problemi di bilanciamento del carico in GKE


Questa pagina mostra come risolvere i problemi relativi al bilanciamento del carico nei cluster Google Kubernetes Engine (GKE) utilizzando le risorse Service, Ingress o Gateway.

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

BackendConfig non trovato

Questo errore si verifica quando nell'annotazione di servizio è specificato un BackendConfig per una porta di servizio, ma non è stato possibile trovare la risorsa BackendConfig effettiva.

Per valutare un evento Kubernetes, esegui il seguente comando:

kubectl get event

L'esempio di output seguente indica che BackendConfig non è stato trovato:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

Per risolvere il problema, assicurati di non aver creato la risorsa BackendConfig nello spazio dei nomi errato o di non aver scritto male il relativo riferimento nell'annotazione di servizio.

Criterio di sicurezza in entrata non trovato

Dopo aver creato l'oggetto Ingress, se il criterio di sicurezza non è associato correttamente al servizio LoadBalancer, valuta l'evento Kubernetes per verificare se è presente un errore di configurazione. Se BackendConfig specifica un criterio di sicurezza inesistente, viene emesso periodicamente un evento di avviso.

Per valutare un evento Kubernetes, esegui il seguente comando:

kubectl get event

L'esempio di output seguente indica che il criterio di sicurezza non è stato trovato:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

Per risolvere il problema, specifica il nome corretto del criterio di sicurezza in BackendConfig.

Risolvere gli errori della serie 500 con i NEG durante la scalabilità del carico di lavoro in GKE

Sintomo:

Quando utilizzi NEG di GKE di cui è stato eseguito il provisioning per il bilanciamento del carico, potresti riscontrare errori 502 o 503 per i servizi durante il fare lo scale down del carico di lavoro. Gli errori 502 si verificano quando i pod vengono terminati prima della chiusura delle connessioni esistenti, mentre gli errori 503 si verificano quando il traffico viene indirizzato ai pod eliminati.

Questo problema può interessare i cluster se utilizzi i prodotti di bilanciamento del carico gestiti da GKE che utilizzano gli NEG, inclusi Gateway, Ingress e NEG autonomi. Se esegui spesso il ridimensionamento dei carichi di lavoro, il tuo cluster è più a rischio di essere interessato.

Diagnosi:

La rimozione di un pod in Kubernetes senza svuotare il relativo endpoint e rimuoverlo prima dal NEG genera errori della serie 500. Per evitare problemi durante l'interruzione del pod, devi considerare l'ordine delle operazioni. Le seguenti immagini rappresentano scenari in cui BackendService Drain Timeout non è impostato e BackendService Drain Timeout è impostato con BackendConfig.

Scenario 1: BackendService Drain Timeout non è impostato.

L'immagine seguente mostra uno scenario in cui BackendService Drain Timeout è impostato su OFF.

Il valore Timeout svuotamento servizio di backend non è impostato.

Scenario 2: è impostato BackendService Drain Timeout.

L'immagine seguente mostra uno scenario in cui è impostato BackendService Drain Timeout.

È impostato il valore Timeout svuotamento servizio di backend.

Il momento esatto in cui si verificano gli errori della serie 500 dipende dai seguenti fattori:

  • Latenza di scollegamento dell'API NEG: la latenza di scollegamento dell'API NEG rappresenta il tempo corrente necessario per completare l'operazione di scollegamento in Google Cloud. Questo valore è influenzato da una serie di fattori esterni a Kubernetes, tra cui il tipo di bilanciatore del carico e la zona specifica.

  • Latenza di scarico: la latenza di scarico è il tempo necessario al bilanciatore del carico per iniziare a indirizzare il traffico lontano da una parte specifica del sistema. Dopo che è stato avviato il ritiro, il bilanciatore del carico smette di inviare nuove richieste all'endpoint, ma esiste ancora una latenza nell'attivazione del ritiro (latenza del ritiro) che può causare errori 503 temporanei se il pod non esiste più.

  • Configurazione dei controlli di integrità: soglie di controllo di integrità più sensibili mitigano la durata degli errori 503, in quanto possono indicare al bilanciatore del carico di interrompere l'invio di richieste agli endpoint anche se l'operazione di scollegamento non è stata completata.

  • Periodo di tolleranza per l'interruzione: il periodo di tolleranza per l'interruzione determina il tempo massimo concesso a un pod per uscire. Tuttavia, un pod può uscire prima del completamento del periodo di tolleranza prima della chiusura. Se un pod impiega più tempo di questo periodo, viene costretto a uscire alla fine di questo periodo. Si tratta di un'impostazione del pod e deve essere configurata nella definizione del carico di lavoro.

Possibile risoluzione:

Per evitare questi errori 5XX, applica le seguenti impostazioni. I valori di timeout sono indicativi e potrebbe essere necessario modificarli per la tua applicazione specifica. La sezione seguente illustra la procedura di personalizzazione.

La seguente immagine mostra come mantenere attivo il pod con preStopHook:

È impostato il valore Timeout svuotamento servizio di backend.

Per evitare errori della serie 500, svolgi i seguenti passaggi:

  1. Imposta BackendService Drain Timeout per il tuo servizio su 1 minuto.

  2. Espandi terminationGracePeriod nel pod.

    Imposta terminationGracePeriodSeconds sul pod su 3,5 minuti. Se abbinato alle impostazioni consigliate, questo consente ai pod di avere un intervallo di 30-45 secondi per un arresto graduale dopo la rimozione dell'endpoint del pod dal NEG. Se hai bisogno di più tempo per l'arresto graduale, puoi estendere il periodo di tolleranza o seguire le istruzioni riportate nella sezione Personalizzare i timeout.

    Il seguente manifest del pod specifica un timeout per lo svuotamento della connessione di 210 secondi (3,5 minuti):

    spec:
      terminationGracePeriodSeconds: 210
      containers:
      - name: my-app
        ...
      ...
    
  3. Applica un preStopHook a tutti i contenitori.

    Applica un preStopHook che garantisca che il pod rimanga attivo per altri 120 secondi mentre l'endpoint del pod viene svuotato nel bilanciatore del carico e l'endpoint viene rimosso dal NEG.

    spec:
      containers:
      - name: my-app
        ...
        lifecycle:
          preStopHook:
            exec:
              command: ["/bin/sh", "-c", "sleep 120s"]
      ...
    

Personalizzare i timeout

Per garantire la continuità del pod ed evitare errori della serie 500, il pod deve essere attivo fino a quando l'endpoint non viene rimosso dal NEG. In particolare, per evitare errori 502 e 503, prendi in considerazione l'implementazione di una combinazione di timeout e un preStopHook.

Per mantenere attivo il pod più a lungo durante il processo di arresto, aggiungi un preStopHook al pod. Esegui preStopHook prima che a un pod venga inviato il segnale di uscita, in modo che preStopHook possa essere utilizzato per mantenere il pod finché il relativo endpoint non viene rimosso dal NEG.

Per estendere la durata del tempo in cui un pod rimane attivo durante il processo di arresto, inserisci un preStopHook nella configurazione del pod come segue:

spec:
  containers:
  - name: my-app
    ...
    lifecycle:
      preStopHook:
        exec:
          command: ["/bin/sh", "-c", "sleep <latency time>"]
.

Puoi configurare i timeout e le impostazioni correlate per gestire l'arresto graduale dei pod durante i cali di scalabilità del carico di lavoro. Puoi modificare i timeout in base a casi d'uso specifici. Ti consigliamo di iniziare con timeout più lunghi e di ridurre la durata se necessario. Puoi personalizzare i timeout configurando i parametri relativi ai timeout e preStopHook nei seguenti modi:

Timeout di scarico del servizio di backend

Il parametro Backend Service Drain Timeout non è impostato per impostazione predefinita e non ha alcun effetto. Se imposti e attivi il parametro Backend Service Drain Timeout, il bilanciatore del carico smette di inoltrare le nuove richieste all'endpoint e attende il timeout prima di terminare le connessioni esistenti.

Puoi impostare il parametro Backend Service Drain Timeout utilizzando BackendConfig con Ingress, GCPBackendPolicy con Gateway o manualmente su BackendService con NEG autonomi. Il timeout deve essere 1,5-2 volte più lungo del tempo necessario per elaborare una richiesta. In questo modo, se una richiesta viene inviata poco prima dell'avvio dello scarico, verrà completata prima del timeout. L'impostazione del parametro Backend Service Drain Timeout su un valore superiore a 0 contribuisce ad attenuare gli errori 503 perché non vengono inviate nuove richieste agli endpoint pianificati per la rimozione. Affinché questo timeout sia efficace, devi usarlo in combinazione con preStopHook per assicurarti che il pod rimanga attivo durante lo svuotamento. Senza questa combinazione, le richieste esistenti che non sono state completate riceveranno un errore 502.

preStopHook volta

preStopHook deve ritardare l'arresto del pod in modo sufficiente per completare sia la latenza di scarico sia il timeout dello scarico del servizio di backend, garantendo un corretto svuotamento delle connessioni e la rimozione degli endpoint dal NEG prima dell'arresto del pod.

Per risultati ottimali, assicurati che il tempo di esecuzione di preStopHook sia maggiore o uguale alla somma della latenza di Backend Service Drain Timeout e del drenaggio.

Calcola il momento ideale per l'esecuzione di preStopHook con la seguente formula:

preStopHook execution time >= BACKEND_SERVICE_DRAIN_TIMEOUT + DRAIN_LATENCY

Sostituisci quanto segue:

  • BACKEND_SERVICE_DRAIN_TIMEOUT: l'ora configurata per il Backend Service Drain Timeout.
  • DRAIN_LATENCY: un tempo stimato per la latenza di scarico. Ti consigliamo di utilizzare un minuto come stima.

Se gli errori 500 persistono, stima la durata totale delle occorrenze e aggiungi il doppio di questo tempo alla latenza di scarico stimata. In questo modo, il pod avrà tempo sufficiente per eseguire lo svuotamento in modo corretto prima di essere rimosso dal servizio. Puoi modificare questo valore se è troppo lungo per il tuo caso d'uso specifico.

In alternativa, puoi stimare la tempistica esaminando il timestamp dell'eliminazione dal pod e il timestamp in cui l'endpoint è stato rimosso dal NEG in Cloud Audit Logs.

Parametro Periodo di tolleranza per il recesso

Devi configurare il parametro terminationGracePeriod in modo da concedere tempo sufficiente per il completamento di preStopHook e per l'arresto graduale del pod.

Per impostazione predefinita, se non impostato esplicitamente, terminationGracePeriod è pari a 30 secondi. Puoi calcolare il valore ottimale di terminationGracePeriod utilizzando la formula:

terminationGracePeriod >= preStopHook Time + Pod shutdown time

Per definire terminationGracePeriod all'interno della configurazione del pod come segue:

  spec:
    terminationGracePeriodSeconds: <terminationGracePeriod>
    containers:
    - name: my-app
      ...
    ...

NEG non trovato durante la creazione di una risorsa Ingress interna

Quando crei un Ingress interno in GKE, potrebbe verificarsi il seguente errore:

Error syncing: error running backend syncing routine: googleapi: Error 404: The resource 'projects/PROJECT_ID/zones/ZONE/networkEndpointGroups/NEG' was not found, notFound

Questo errore si verifica perché Ingress per i bilanciatori del carico delle applicazioni interni richiede Gruppi di endpoint di rete (NEG) come backend.

Negli ambienti VPC condivisi o nei cluster con i criteri di rete abilitati, aggiungi l'annotazione cloud.google.com/neg: '{"ingress": true}' al manifest del servizio.

504 Gateway Timeout: upstream request timeout

Quando accedi a un servizio da un Ingress interno in GKE, potrebbe verificarsi il seguente errore:

HTTP/1.1 504 Gateway Timeout
content-length: 24
content-type: text/plain

upsteam request timeout

Questo errore si verifica perché il traffico inviato agli Application Load Balancer interni viene eseguito tramite proxy da proxy Envoy nell'intervallo di subnet solo proxy.

Per consentire il traffico dall'intervallo della subnet solo proxy, crea una regola del firewall sul targetPort del servizio.

Errore 400: valore non valido per il campo "resource.target"

Quando accedi a un servizio da un Ingress interno in GKE, potrebbe verificarsi il seguente errore:

Error syncing:LB_NAME does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION_NAME/targetHttpProxies/LB_NAME. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

Per risolvere il problema, crea una subnet solo proxy.

Errore durante la sincronizzazione: errore durante l'esecuzione della routine di sincronizzazione del bilanciatore del carico: il bilanciatore del carico non esiste

Quando esegui l'upgrade del piano di controllo GKE o modifichi un oggetto Ingress, potrebbe verificarsi uno dei seguenti errori:

"Error during sync: error running load balancer syncing routine: loadbalancer
INGRESS_NAME does not exist: invalid ingress frontend configuration, please
check your usage of the 'kubernetes.io/ingress.allow-http' annotation."

In alternativa:

Error during sync: error running load balancer syncing routine: loadbalancer LOAD_BALANCER_NAME does not exist:
googleapi: Error 400: Invalid value for field 'resource.IPAddress':'INGRESS_VIP'. Specified IP address is in-use and would result in a conflict., invalid

Per risolvere questi problemi, prova i seguenti passaggi:

  • Aggiungi il campo hosts nella sezione tls del manifest di Ingress, quindi elimina Ingress. Attendi cinque minuti per consentire a GKE di eliminare le risorse Ingress non utilizzate. Quindi, ricrea l'Ingress. Per ulteriori informazioni, consulta il campo hosts di un oggetto Ingress.
  • Ripristina le modifiche apportate all'Ingress. Aggiungi un certificato utilizzando un'annotazione o un secret Kubernetes.

Ingress esterno genera errori HTTP 502

Segui le indicazioni riportate di seguito per risolvere i problemi relativi agli errori HTTP 502 con le risorse Ingress esterne:

  1. Attiva i log per ogni servizio di backend associato a ogni servizio GKE a cui fa riferimento l'Ingress.
  2. Utilizza i dettagli dello stato per identificare le cause delle risposte HTTP 502. I dettagli dello stato che indicano che la risposta HTTP 502 ha avuto origine dal backend richiedono la risoluzione dei problemi all'interno dei pod di servizio, non nel bilanciatore del carico.

Gruppi di istanze non gestite

Potresti riscontrare errori HTTP 502 con le risorse Ingress esterne se il tuo Ingress esterno utilizza backend di gruppi di istanze non gestiti. Questo problema si verifica quando sono soddisfatte tutte le seguenti condizioni:

  • Il cluster ha un numero totale elevato di nodi tra tutti i pool di nodi.
  • I pod di pubblicazione per uno o più servizi a cui fa riferimento l'Ingress si trovano solo su alcuni nodi.
  • I servizi a cui fa riferimento l'Ingress utilizzano externalTrafficPolicy: Local.

Per determinare se il tuo Ingress esterno utilizza backend di gruppi di istanze non gestiti, segui questi passaggi:

  1. Vai alla pagina Ingress nella console Google Cloud.

    Vai a Ingress

  2. Fai clic sul nome dell'Ingress esterno.

  3. Fai clic sul nome del bilanciatore del carico. Viene visualizzata la pagina Dettagli bilanciamento del carico.

  4. Controlla la tabella nella sezione Servizi di backend per determinare se il tuo ingress esterno utilizza NEG o gruppi di istanze.

Per risolvere il problema, utilizza una delle seguenti soluzioni:

  • Utilizza un cluster nativo di VPC.
  • Utilizza externalTrafficPolicy: Cluster per ogni servizio a cui fa riferimento l'Ingress esterno. Questa soluzione comporta la perdita dell'indirizzo IP del cliente originale nelle origini del pacchetto.
  • Utilizza l'annotazione node.kubernetes.io/exclude-from-external-load-balancers=true. Aggiungi l'annotazione ai nodi o ai pool di nodi che non eseguono alcun pod di servizio per qualsiasi servizio a cui fa riferimento un Ingress o un servizio LoadBalancer esterno nel tuo cluster.

Utilizzare i log del bilanciatore del carico per la risoluzione dei problemi

Puoi utilizzare i log dei bilanciatori del carico di rete passthrough interni e i log dei bilanciatori del carico di rete passthrough esterni per risolvere i problemi relativi ai bilanciatori del carico e correlare il traffico dai bilanciatori del carico alle risorse GKE.

I log vengono aggregati per connessione ed esportati in tempo quasi reale. I log vengono generati per ogni nodo GKE coinvolto nel percorso dati di un servizio LoadBalancer, sia per il traffico in entrata che in uscita. Le voci di log includono campi aggiuntivi per le risorse GKE, ad esempio:

  • Nome del cluster
  • Località del cluster
  • Nome servizio
  • Spazio dei nomi del servizio
  • Nome pod
  • Spazio dei nomi pod

Prezzi

Non vengono addebitati costi aggiuntivi per l'utilizzo dei log. In base alla modalità di importazione dei log, si applicano i prezzi standard per Cloud Logging, BigQuery o Pub/Sub. L'attivazione dei log non influisce sul rendimento del bilanciatore del carico.

Utilizzare gli strumenti di diagnostica per risolvere i problemi

Lo strumento di diagnostica check-gke-ingress controlla le risorse Ingress per rilevare le configurazioni errate comuni. Puoi utilizzare lo strumento check-gke-ingress nei seguenti modi:

  • Esegui lo gcpdiagstrumento a riga di comando sul tuo cluster. I risultati di importazione vengono visualizzati nella sezione della regola di controllo gke/ERR/2023_004.
  • Utilizza lo strumento check-gke-ingress da solo o come plug-in kubectl seguendo le istruzioni riportate in check-gke-ingress.

Passaggi successivi

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