Risolvi 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 di servizio, Ingress o gateway.

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

BackendConfig non trovato

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

Per valutare un evento Kubernetes, esegui questo comando:

kubectl get event

L'output di esempio 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 in modo errato il relativo riferimento nell'annotazione del servizio.

Criterio di sicurezza in entrata non trovato

Dopo la creazione dell'oggetto Ingress, se il criterio di sicurezza non è associato correttamente al servizio LoadBalancer, valuta l'evento Kubernetes per vedere se si è verificato un errore di configurazione. Se il tuo BackendConfig specifica un criterio di sicurezza che non esiste, viene generato periodicamente un evento di avviso.

Per valutare un evento Kubernetes, esegui questo comando:

kubectl get event

L'output di esempio 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 del criterio di sicurezza corretto in BackendConfig.

Gestione degli errori della serie 500 con i NEG durante la scalabilità dei carichi di lavoro in GKE

Sintomo:

Quando utilizzi i NEG di cui è stato eseguito il provisioning di GKE per il bilanciamento del carico, potresti riscontrare errori 502 o 503 per i servizi durante lo 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 prodotti di bilanciamento del carico gestiti da GKE che utilizzano NEG, inclusi gateway, Ingress e NEG autonomi. Se scala frequentemente i carichi di lavoro, il rischio di impatto sul cluster è maggiore.

Diagnosi:

La rimozione di un pod in Kubernetes senza svuotare il relativo endpoint e rimuoverlo dal NEG prima causa errori di serie 500. Per evitare problemi durante la terminazione dei pod, devi considerare l'ordine delle operazioni. Le seguenti immagini mostrano scenari quando il criterio BackendService Drain Timeout non viene configurato e BackendService Drain Timeout è impostato su BackendConfig.

Scenario 1: il criterio BackendService Drain Timeout non è impostato.

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

Il timeout dello svuotamento di BackendService non è impostato

Scenario 2: BackendService Drain Timeout è impostato.

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

Il timeout dello svuotamento di BackendService è impostato

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 attuale necessario per finalizzare l'operazione di scollegamento in Google Cloud. Ciò è influenzato da una serie di fattori esterni a Kubernetes, tra cui il tipo di bilanciatore del carico e la zona specifica.

  • Latenza di svuotamento: rappresenta il tempo impiegato dal bilanciatore del carico per iniziare a indirizzare il traffico lontano da una determinata parte del sistema. Una volta avviata la procedura di svuotamento, il bilanciatore del carico interrompe l'invio di nuove richieste all'endpoint, ma l'attivazione dello svuotamento (latenza di svuotamento) presenta ancora una latenza che può causare errori 503 temporanei se il pod non esiste più.

  • Configurazione del controllo di integrità: soglie più sensibili per i controlli di integrità riducono la durata degli errori 503, in quanto possono segnalare al bilanciatore del carico di interrompere l'invio di richieste agli endpoint anche se l'operazione di scollegamento non è terminata.

  • Periodo di tolleranza per la chiusura: il periodo di tolleranza per la chiusura determina il periodo massimo di tempo concesso per l'uscita di un pod. Tuttavia, un pod può uscire prima del termine del periodo di tolleranza. Se un pod impiega più tempo di questo periodo, ne viene forzata l'uscita alla fine del periodo. Questa è un'impostazione sul pod e deve essere configurata nella definizione del carico di lavoro.

Potenziale risoluzione:

Per evitare questi errori 5XX, applica le seguenti impostazioni. I valori di timeout sono allusivi e potresti doverli modificare per la tua applicazione specifica. La sezione seguente illustra la procedura di personalizzazione.

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

Il timeout dello svuotamento di BackendService è impostato

Per evitare errori relativi alla serie 500:

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

  2. Estendi terminationGracePeriod sul pod.

    Imposta terminationGracePeriodSeconds sul pod su 3,5 minuti. Se combinato con le impostazioni consigliate, consente ai pod di usufruire di una finestra di 30-45 secondi per un arresto controllato dopo la rimozione dell'endpoint del pod dal NEG. Se hai bisogno di più tempo per la chiusura controllata, puoi estendere il periodo di tolleranza o seguire le istruzioni riportate nella sezione Personalizzare i timeout.

    Il seguente manifest dei 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'istruzione preStopHook a tutti i container.

    Applica un preStopHook che garantirà che il pod sia attivo per 120 secondi più a lungo 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"]
      ...
    

Personalizza timeout

Per garantire la continuità del pod ed evitare errori della serie 500, il pod deve essere attivo fino alla rimozione dell'endpoint dal NEG. Specialmente per evitare errori 502 e 503, valuta la possibilità di implementare una combinazione di timeout e di un valore preStopHook.

Per mantenere il pod più a lungo durante il processo di arresto, aggiungi un preStopHook al pod. Esegui preStopHook prima che venga segnalato l'uscita di un pod, in modo che preStopHook possa essere utilizzato per mantenere il pod a portata di mano fino a quando l'endpoint corrispondente non viene rimosso dal NEG.

Per estendere il periodo di 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 relative impostazioni per gestire l'arresto controllato dei pod durante lo scale down dei carichi di lavoro. Puoi regolare 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 al timeout e il preStopHook nei seguenti modi:

Timeout svuotamento servizio di backend

Il parametro Backend Service Drain Timeout non è impostato per impostazione predefinita e non ha alcun effetto. Se imposti il parametro Backend Service Drain Timeout e lo attivi, il bilanciatore del carico interrompe l'instradamento delle 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 il gateway o manualmente su BackendService con NEG autonomi. Il timeout dovrebbe essere da 1,5 a 2 volte superiore al tempo necessario per elaborare una richiesta. Ciò garantisce che, se una richiesta è stata inviata poco prima dell'inizio dello svuotamento, verrà completata prima del completamento del timeout. L'impostazione del parametro Backend Service Drain Timeout su un valore maggiore di 0 consente di mitigare gli errori 503 perché non vengono inviate nuove richieste agli endpoint pianificati per la rimozione. Affinché questo timeout venga applicato, devi utilizzarlo insieme a preStopHook per assicurarti che il pod resti attivo mentre si verifica 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 affinché la latenza di svuotamento e il timeout per lo svuotamento del servizio di backend siano completati, garantendo il corretto svuotamento della connessione e la rimozione dell'endpoint dal NEG prima dell'arresto del pod.

Per risultati ottimali, assicurati che il tempo di esecuzione di preStopHook sia inferiore o uguale alla somma di Backend Service Drain Timeout e Latenza di svuotamento.

Questo valore può essere calcolato utilizzando la formula:

preStopHook >= Backend Service Drain Timeout + Drain Latency

Ti consigliamo di impostare la Latenza di svuotamento su 1 minuto. Se rimangono 500 errori, stima la durata totale dell'occorrenza e aggiungi il doppio alla latenza. In questo modo il pod ha tempo a sufficienza per svuotarsi correttamente prima di essere rimosso dal servizio. Puoi regolare questo valore se è troppo lungo per il tuo caso d'uso specifico.

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

Parametro periodo di tolleranza per la chiusura

Devi configurare il parametro terminationGracePeriod in modo da concedere tempo sufficiente per il completamento di preStopHook e per il completamento di un arresto controllato dal pod.

Per impostazione predefinita, se non viene configurato in modo esplicito, il valore di terminationGracePeriod è di 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 una risorsa Ingress interna 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é il traffico in entrata per i bilanciatori del carico delle applicazioni interni richiede gruppi di endpoint di rete (NEG) come backend.

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

504 Timeout gateway: timeout della richiesta upstream

Potrebbe verificarsi il seguente errore quando accedi a un servizio da un server Ingress interno in GKE:

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

upsteam request timeout

Questo errore si verifica perché il traffico inviato ai bilanciatori del carico delle applicazioni interni viene inviato tramite proxy da proxy Envoy nell'intervallo di subnet solo proxy.

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

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

Potrebbe verificarsi il seguente errore quando accedi a un servizio da un server Ingress interno in GKE:

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

Potrebbe verificarsi uno dei seguenti errori quando viene eseguito l'upgrade del piano di controllo GKE o quando modifichi un oggetto Ingress:

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

Oppure:

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 a procedere nel seguente modo:

  • Aggiungi il campo hosts nella sezione tls del manifest Ingress, quindi elimina l'oggetto Ingress. Aspetta cinque minuti affinché GKE elimini le risorse Ingress inutilizzate. Quindi, ricrea la risorsa Ingress. Per maggiori informazioni, consulta il campo hosts di un oggetto Ingress.
  • Ripristina le modifiche apportate a Ingress. Quindi, aggiungi un certificato utilizzando un'annotazione o un secret di Kubernetes.

Una risorsa Ingress esterna produce errori HTTP 502

Utilizza le seguenti indicazioni per risolvere gli errori HTTP 502 con risorse Ingress esterne:

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

Gruppi di istanze non gestite

Potresti riscontrare errori HTTP 502 con risorse Ingress esterne se la tua risorsa Ingress esterna utilizza backend di gruppi di istanze non gestite. Questo problema si verifica quando sono soddisfatte tutte le seguenti condizioni:

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

Per determinare se la tua risorsa Ingress esterna utilizza backend di gruppi di istanze non gestite:

  1. Vai alla pagina Ingress nella console Google Cloud.

    Vai a Ingress

  2. Fai clic sul nome della risorsa Ingress esterna.

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

  4. Controlla la tabella nella sezione Servizi di backend per determinare se la tua risorsa Ingress esterna 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'oggetto Ingress esterno. Questa soluzione causa la perdita dell'indirizzo IP client originale nelle origini del pacchetto.
  • Usa 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 pubblicazione per alcun servizio a cui fa riferimento un qualsiasi servizio Ingress o LoadBalancer esterno nel tuo cluster.

Utilizzare i log del bilanciatore del carico per risolvere i problemi

Puoi utilizzare i log del bilanciatore del carico di rete passthrough interno e i log del bilanciatore del carico di rete passthrough esterno 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 quasi in tempo reale. I log vengono generati per ciascun nodo GKE coinvolto nel percorso dei 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 cluster - Località cluster - Nome servizio - Spazio dei nomi servizio - Nome pod - Spazio dei nomi pod

Prezzi

Non sono previsti costi aggiuntivi per l'utilizzo dei log. In base alle modalità di importazione dei log, si applicano i prezzi standard per Cloud Logging, BigQuery o Pub/Sub. L'abilitazione dei log non ha alcun effetto sulle prestazioni del bilanciatore del carico.

Utilizzare gli strumenti di diagnostica per risolvere i problemi

Lo strumento di diagnostica check-gke-ingress ispeziona le risorse Ingress alla ricerca di configurazioni comuni. Puoi utilizzare lo strumento check-gke-ingress nei seguenti modi:

  • Esegui lo strumento a riga di comando gcpdiag sul tuo cluster. I risultati in entrata 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 in check-gke-ingress.

Passaggi successivi

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