Bilanciamento del carico nativo del container tramite Ingress


Questa pagina spiega come utilizzare il bilanciamento del carico nativo dei container in Google Kubernetes Engine (GKE). Il bilanciamento del carico nativo del container consente ai bilanciatori del carico di scegliere come target direttamente i pod Kubernetes e di distribuire uniformemente il traffico tra i pod.

Per ulteriori informazioni sui vantaggi, sui requisiti e sulle limitazioni del bilanciamento del carico nativo del container, consulta Bilanciamento del carico nativo del container.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti operazioni:

  • Attiva l'API Google Kubernetes Engine.
  • Attiva l'API Google Kubernetes Engine
  • Se vuoi utilizzare Google Cloud CLI per questa attività, installa e poi inizializza gcloud CLI. Se hai già installato gcloud CLI, ottieni la versione più recente eseguendo gcloud components update.

Utilizzare il bilanciamento del carico nativo del container

Le sezioni seguenti illustrano la procedura di configurazione di un bilanciamento del carico nativo del container su GKE. Tieni presente che per i cluster GKE che eseguono la versione 1.17 o successive e in determinate condizioni, il bilanciamento del carico nativo dei container è predefinito e non richiede un'annotazione del servizio cloud.google.com/neg: '{"ingress": true}' esplicita.

Crea un cluster nativo di VPC

Per utilizzare il bilanciamento del carico nativo del container, nel cluster GKE devono essere attivati gli indirizzi IP alias.

Ad esempio, il seguente comando crea un cluster GKE,neg-demo-cluster, con una sottorete con provisioning automatico:

  • Per la modalità Autopilot, gli indirizzi IP alias sono abilitati per impostazione predefinita:

    gcloud container clusters create-auto neg-demo-cluster \
        --location=COMPUTE_LOCATION
    

    Sostituisci COMPUTE_LOCATION con la località Compute Engine del cluster.

  • Per la modalità standard, abilita gli indirizzi IP alias quando crei il cluster:

    gcloud container clusters create neg-demo-cluster \
        --enable-ip-alias \
        --create-subnetwork="" \
        --network=default \
        --zone=us-central1-a
    

Creazione di un deployment

Il seguente deployment di esempio,neg-demo-app, esegue una singola istanza di un server HTTP containerizzato. Ti consigliamo di utilizzare carichi di lavoro che utilizzano il feedback sulla preparazione dei pod.

Utilizzare il feedback relativo all'idoneità dei pod

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: registry.k8s.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
        ports:
        - containerPort: 9376
          protocol: TCP
  

Utilizzare un ritardo hardcoded

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  minReadySeconds: 60 # Number of seconds to wait after a Pod is created and its status is Ready
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: registry.k8s.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
      # Note: The following line is necessary only on clusters running GKE v1.11 and lower.
      # For details, see https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
        ports:
        - containerPort: 9376
          protocol: TCP
      terminationGracePeriodSeconds: 60 # Number of seconds to wait for connections to terminate before shutting down Pods
  

In questo deployment, ogni contenitore esegue un server HTTP. Il server HTTP restituisce il nome host del server dell'applicazione (il nome del pod su cui viene eseguito il server) come risposta.

Salva questo manifest come neg-demo-app.yaml, quindi crea il deployment:

kubectl apply -f neg-demo-app.yaml

Crea un servizio per un bilanciatore del carico nativo del container

Dopo aver creato un deployment, devi raggruppare i relativi pod in un servizio.

Il seguente servizio di esempio, neg-demo-svc, ha come target il deployment di esempio che hai creato nella sezione precedente:

apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc # Name of Service
  annotations:
    cloud.google.com/neg: '{"ingress": true}' # Creates a NEG after an Ingress is created
spec: # Service's specification
  type: ClusterIP
  selector:
    run: neg-demo-app # Selects Pods labelled run: neg-demo-app
  ports:
  - name: http
    port: 80 # Service's port
    protocol: TCP
    targetPort: 9376

L'annotazione del servizio, cloud.google.com/neg: '{"ingress": true}', attiva il bilanciamento del carico nativo del container. Tuttavia, il bilanciatore del carico non viene creato finché non crei un Ingress per il servizio.

Salva questo manifest come neg-demo-svc.yaml, quindi crea il servizio:

kubectl apply -f neg-demo-svc.yaml

Crea un Ingress per il servizio

Il seguente Ingresso di esempio, neg-demo-ing, ha come target il servizio che hai creato:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: neg-demo-ing
spec:
  defaultBackend:
    service:
      name: neg-demo-svc # Name of the Service targeted by the Ingress
      port:
        number: 80 # Should match the port used by the Service

Salva questo manifest come neg-demo-ing.yaml, quindi crea l'Ingress:

kubectl apply -f neg-demo-ing.yaml

Al momento della creazione di Ingress, nel progetto viene creato un bilanciatore del carico delle applicazioni e vengono creati gruppi di endpoint di rete(NEG) in ogni zona in cui viene eseguito il cluster. Gli endpoint nel NEG e gli endpoint del servizio vengono mantenuti sincronizzati.

Verifica l'ingresso

Dopo aver eseguito il deployment di un carico di lavoro, raggruppato i relativi pod in un servizio e creato un Ingress per il servizio, devi verificare che l'Ingress abbia eseguito il provisioning del bilanciatore del carico nativo del container.

Recupera lo stato dell'Ingress:

kubectl describe ingress neg-demo-ing

L'output include gli eventi ADD e CREATE:

Events:
Type     Reason   Age                From                     Message
----     ------   ----               ----                     -------
Normal   ADD      16m                loadbalancer-controller  default/neg-demo-ing
Normal   Service  4s                 loadbalancer-controller  default backend set to neg-demo-svc:32524
Normal   CREATE   2s                 loadbalancer-controller  ip: 192.0.2.0

Testa il bilanciatore del carico

Le sezioni seguenti spiegano come testare la funzionalità di un bilanciatore del carico nativo per i container.

Visita l'indirizzo IP di Ingress

Attendi alcuni minuti per la configurazione del bilanciatore del carico delle applicazioni.

Puoi verificare che il bilanciatore del carico nativo del container funzioni visitando l'indirizzo IP di Ingress.

Per ottenere l'indirizzo IP di Ingress, esegui il seguente comando:

kubectl get ingress neg-demo-ing

Nell'output del comando, l'indirizzo IP di Ingress viene visualizzato nella colonna ADDRESS. Visita l'indirizzo IP in un browser web.

Controllare lo stato di salute del servizio di backend

Puoi anche ottenere lo stato di integrità del servizio di backend del bilanciatore del carico.

  1. Visualizza un elenco dei servizi di backend in esecuzione nel tuo progetto:

    gcloud compute backend-services list
    

    Registra il nome del servizio di backend che include il nome del servizio, ad esempio neg-demo-svc.

  2. Visualizza lo stato di integrità del servizio di backend:

    gcloud compute backend-services get-health BACKEND_SERVICE_NAME --global
    

    Sostituisci BACKEND_SERVICE_NAME con il nome del servizio di backend.

Testa Ingress

Un altro modo per verificare che il bilanciatore del carico funzioni come previsto è eseguire il ridimensionamento del deployment di esempio, inviare richieste di test all'Ingress e verificare che risponda il numero corretto di repliche.

  1. Scala il deployment neg-demo-app da un'istanza a due istanze:

    kubectl scale deployment neg-demo-app --replicas 2
    

    Il completamento di questo comando potrebbe richiedere diversi minuti.

  2. Verifica che l'implementazione sia completa:

    kubectl get deployment neg-demo-app
    

    L'output deve includere due repliche disponibili:

    NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    neg-demo-app   2         2         2            2           26m
    
  3. Ottieni l'indirizzo IP di Ingress:

    kubectl describe ingress neg-demo-ing
    

    Se questo comando restituisce un errore 404, attendi qualche minuto per l'avvio del bilanciatore del carico, quindi riprova.

  4. Conta il numero di risposte distinte del bilanciatore del carico:

    for i in `seq 1 100`; do \
      curl --connect-timeout 1 -s IP_ADDRESS && echo; \
    done  | sort | uniq -c
    

    Sostituisci IP_ADDRESS con l'indirizzo IP di Ingress.

    L'output è simile al seguente:

    44 neg-demo-app-7f7dfd7bc6-dcn95
    56 neg-demo-app-7f7dfd7bc6-jrmzf
    

    In questa uscita, il numero di risposte distinte corrisponde al numero di repliche, il che indica che tutti i pod di backend stanno servendo il traffico.

Esegui la pulizia

Dopo aver completato le attività in questa pagina, segui questi passaggi per rimuovere le risorse ed evitare addebiti indesiderati sul tuo account:

Elimina il cluster

gcloud

gcloud container clusters delete neg-demo-cluster

Console

  1. Vai alla pagina Google Kubernetes Engine nella console Google Cloud.

    Vai a Google Kubernetes Engine

  2. Seleziona neg-demo-cluster e fai clic su Elimina.

  3. Quando ti viene richiesto di confermare, fai clic su Elimina.

Risoluzione dei problemi

Utilizza le tecniche riportate di seguito per verificare la configurazione di rete. Le seguenti sezioni spiegano come risolvere problemi specifici relativi al bilanciamento del carico nativo dei container.

  • Consulta la documentazione sul bilanciamento del carico per scoprire come elencare i gruppi di endpoint di rete.

  • Puoi trovare il nome e le zone del NEG che corrispondono a un servizio nell'annotazione neg-status del servizio. Recupera la specifica del servizio con:

    kubectl get svc SVC_NAME -o yaml
    

    L'annotazione metadata:annotations:cloud.google.com/neg-status elenca il nome del NEG corrispondente del servizio e le zone del NEG.

  • Puoi controllare lo stato del servizio di backend corrispondente a un NEG con il seguente comando:

    gcloud compute backend-services --project PROJECT_NAME \
        get-health BACKEND_SERVICE_NAME --global
    

    Il servizio di backend ha lo stesso nome del relativo NEG.

  • Per stampare i log eventi di un servizio:

    kubectl describe svc SERVICE_NAME
    

    La stringa del nome del servizio include il nome e lo spazio dei nomi del servizio GKE corrispondente.

Impossibile creare un cluster con IP alias

Sintomi

Quando provi a creare un cluster con IP alias, potresti riscontrare il seguente errore:

ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
Possibili cause

Questo errore si verifica se provi a creare un cluster con IP alias che utilizza anche una rete precedente.

Risoluzione

Assicurati di non creare un cluster con IP alias e una rete legacy attivati contemporaneamente. Per ulteriori informazioni sull'utilizzo degli IP alias, consulta Creare un cluster nativo di VPC.

Il traffico non raggiunge gli endpoint

Sintomi
Errori 502/503 o connessioni rifiutate.
Possibili cause

In genere, i nuovi endpoint diventano raggiungibili dopo l'attacco al bilanciatore del carico, a condizione che rispondano ai controlli di integrità. Potresti riscontrare errori 502 o connessioni rifiutate se il traffico non riesce a raggiungere gli endpoint.

Gli errori 502 e le connessioni rifiutate possono essere causati anche da un contenitore che non gestisce SIGTERM. Se un contenitore non gestisce esplicitamente SIGTERM, si chiude immediatamente e smette di gestire le richieste. Il bilanciatore del carico continua a inviare il traffico in entrata al contenitore terminato, causando errori.

Il bilanciatore del carico nativo del container ha un solo endpoint di backend. Durante un aggiornamento progressivo, l'endpoint precedente viene deprogrammato prima che venga programmato quello nuovo.

I pod di backend vengono dispiacchiati in una nuova zona per la prima volta dopo il provisioning di un bilanciatore del carico nativo del contenitore. L'infrastruttura del bilanciatore del carico viene programmata in una zona se è presente almeno un endpoint. Quando viene aggiunto un nuovo endpoint a una zona, l'infrastruttura del bilanciatore del carico viene programmata e causa interruzioni del servizio.

Risoluzione

Configura i contenitori per gestire SIGTERM e continuare a rispondere alle richieste durante il periodo di tolleranza per il recesso (30 secondi per impostazione predefinita). Configura i pod in modo che inizino a non superare i controlli di integrità quando ricevono SIGTERM. Questo indica al bilanciatore del carico di interrompere l'invio di traffico al pod mentre la deprogrammazione dell'endpoint è in corso.

Se l'applicazione non si arresta in modo corretto e smette di rispondere alle richieste quando riceve un SIGTERM, l'hook preStop può essere utilizzato per gestire SIGTERM e continuare a pubblicare traffico mentre è in corso la deprogrammazione dell'endpoint.

lifecycle:
  preStop:
    exec:
      # if SIGTERM triggers a quick exit; keep serving traffic instead
      command: ["sleep","60"]

Consulta la documentazione sull'interruzione dei pod.

Se il backend del bilanciatore del carico ha una sola istanza, configura la strategia di implementazione per evitare di smantellare l'unica istanza prima che la nuova istanza sia completamente programmata. Per i pod di applicazioni gestiti dal workload Deployment, questo può essere ottenuto configurando la strategia di implementazione con il parametro maxUnavailable uguale a 0.

strategy:
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

Per risolvere i problemi relativi al traffico che non raggiunge gli endpoint, verifica che le regole del firewall consentano il traffico TCP in entrata verso gli endpoint negli intervalli 130.211.0.0/22 e 35.191.0.0/16. Per saperne di più, consulta Aggiunta di controlli di integrità nella documentazione di Cloud Load Balancing.

Visualizza i servizi di backend nel tuo progetto. La stringa del nome del servizio di backend pertinente include il nome e lo spazio dei nomi del servizio GKE corrispondente:

gcloud compute backend-services list

Recupera lo stato di integrità del backend dal servizio di backend:

gcloud compute backend-services get-health BACKEND_SERVICE_NAME

Se tutti i backend non sono integri, il firewall, Ingress o il servizio potrebbe essere configurato in modo errato.

Se alcuni backend non sono operativi per un breve periodo di tempo, la causa potrebbe essere la latenza della programmazione della rete.

Se alcuni backend non vengono visualizzati nell'elenco dei servizi di backend, la causa potrebbe essere la latenza di programmazione. Puoi verificarlo eseguendo il comando seguente, dove NEG_NAME è il nome del servizio di backend. (NEG e servizi di backend condividono lo stesso nome):

gcloud compute network-endpoint-groups list-network-endpoints NEG_NAME

Controlla se tutti gli endpoint previsti sono nel NEG.

Se hai un numero ridotto di backend (ad esempio un pod) selezionati da un bilanciatore del carico nativo del contenitore, ti consigliamo di aumentare il numero di repliche e di distribuire i pod di backend in tutte le zone in cui si estende il cluster GKE. In questo modo, l'infrastruttura del bilanciatore del carico sottostante sarà completamente programmata. In caso contrario, valuta la possibilità di limitare i pod di backend a una singola zona.

Se configuri un criterio di rete per l'endpoint, assicurati che l'ingresso dalla subnet solo proxy sia consentito.

Implementazione in stallo

Sintomi
L'implementazione di un deployment aggiornato si blocca e il numero di repliche aggiornate non corrisponde al numero di repliche desiderato.
Possibili cause

I controlli di integrità del deployment non vanno a buon fine. L'immagine del contenitore potrebbe essere danneggiata o il controllo di integrità potrebbe essere configurato in modo errato. La sostituzione graduale dei pod attende che il pod appena avviato superi il controllo di idoneità dei pod. Ciò si verifica solo se il pod risponde ai controlli di integrità del bilanciatore del carico. Se il pod non risponde o se il controllo di integrità è configurato in modo errato, le condizioni del cancello di idoneità non possono essere soddisfatte e l'implementazione non può continuare.

Se utilizzi kubectl 1.13 o versioni successive, puoi controllare lo stato dei gate di idoneità di un pod con il seguente comando:

kubectl get pod POD_NAME -o wide

Controlla la colonna READINESS GATES.

Questa colonna non esiste in kubectl 1.12 e versioni precedenti. Un pod contrassegnato come in stato READY potrebbe avere un controllo di idoneità non superato. Per verificarlo, utilizza questo comando:

kubectl get pod POD_NAME -o yaml

I controlli di idoneità e il relativo stato sono elencati nell'output.

Risoluzione

Verifica che l'immagine del contenitore nella specifica del pod del deployment funzioni correttamente e sia in grado di rispondere ai controlli di integrità. Verifica che i controlli di salute siano configurati correttamente.

Errori relativi alla modalità degradata

Sintomi

A partire dalla versione GKE 1.29.2-gke.1643000, potresti ricevere i seguenti avvisi sul tuo servizio in Logs Explorer quando vengono aggiornati i NEG:

Entering degraded mode for NEG <service-namespace>/<service-name>-<neg-name>... due to sync err: endpoint has missing nodeName field
Possibili cause

Questi avvisi indicano che GKE ha rilevato configurazioni errate degli endpoint durante un aggiornamento dell'NEG in base agli oggetti EndpointSlice, attivando un processo di calcolo più approfondito chiamato modalità di degradamento. GKE continua ad aggiornare i NEG secondo il criterio del massimo impegno, correggendo la configurazione errata o escludendo gli endpoint non validi dagli aggiornamenti dei NEG.

Ecco alcuni errori comuni:

  • endpoint has missing pod/nodeName field
  • endpoint corresponds to an non-existing pod/node
  • endpoint information for attach/detach operation is incorrect
Risoluzione

In genere, questi eventi sono causati da stati transitori e vengono risolti autonomamente. Tuttavia, gli eventi causati da configurazioni errate negli oggetti EndpointSlice personalizzati rimangono irrisolti. Per comprendere la configurazione errata, esamina gli oggetti EndpointSlice corrispondenti al servizio:

kubectl get endpointslice -l kubernetes.io/service-name=<service-name>

Convalida ogni endpoint in base all'errore nell'evento.

Per risolvere il problema, devi modificare manualmente gli oggetti EndpointSlice. L'aggiornamento attiva l'aggiornamento di nuovo dei NEG. Una volta che la configurazione errata non esiste più, l'output è simile al seguente:

NEG <service-namespace>/<service-name>-<neg-name>... is no longer in degraded mode

Problemi noti

Il bilanciamento del carico nativo del container su GKE presenta i seguenti problemi noti:

Garbage collection incompleta

Il garbage collection di GKE raccoglie i bilanciatori del carico nativi del container ogni due minuti. Se un cluster viene eliminato prima che i bilanciatori del carico vengano completamente rimossi, devi eliminare manualmente i NEG del bilanciatore del carico.

Visualizza i NEG nel tuo progetto eseguendo il seguente comando:

gcloud compute network-endpoint-groups list

Nell'output del comando, cerca i NEG pertinenti.

Per eliminare un NEG, esegui il seguente comando, sostituendo NEG_NAME con il nome del NEG:

gcloud compute network-endpoint-groups delete NEG_NAME

Allinea i rollout dei carichi di lavoro alla propagazione degli endpoint

Quando esegui il deployment di un carico di lavoro nel cluster o aggiorni un carico di lavoro esistente, il bilanciatore del carico nativo del container può impiegare più tempo per propagare i nuovi endpoint rispetto al tempo necessario per completare l'implementazione del carico di lavoro. Il deployment di esempio implementato in questa guida utilizza due campi per allineare il suo implementamento alla propagazione degli endpoint: terminationGracePeriodSeconds e minReadySeconds.

terminationGracePeriodSeconds consente al pod di smettere di funzionare in modo corretto aspettando che le connessioni vengano chiuse dopo che è stata pianificata l'eliminazione di un pod.

minReadySeconds aggiunge un periodo di latenza dopo la creazione di un pod. Specifica un numero minimo di secondi per cui un nuovo pod deve essere in stato Ready, senza che si verifichi un arresto anomalo di nessuno dei suoi container, perché sia considerato disponibile.

Devi configurare i valori minReadySeconds e terminationGracePeriodSeconds dei tuoi carichi di lavoro in modo che siano pari o superiori a 60 secondi per assicurarti che il servizio non venga interrotto a causa degli implementamenti dei carichi di lavoro.

terminationGracePeriodSeconds è disponibile in tutte le specifiche dei pod e minReadySeconds è disponibile per i deployment e i DaemonSet.

Per scoprire di più sulla messa a punto delle implementazioni, consulta RollingUpdateStrategy.

initialDelaySeconds nel pod readinessProbe non rispettato

Potresti aspettarti che la configurazione initialDelaySeconds in readinessProbe del pod sia rispettata dal bilanciatore del carico nativo del contenitore. Tuttavia, readinessProbe è implementato da kubelet e la configurazione initialDelaySeconds controlla il controllo di integrità di kubelet, non il bilanciatore del carico nativo del contenitore. Il bilanciamento del carico nativo del container ha il proprio controllo di integrità del bilanciamento del carico.

Passaggi successivi