Risolvi i problemi relativi ai node pool GKE Standard

Quando gestisci i cluster Standard di Google Kubernetes Engine (GKE), i problemi con i node pool possono interrompere le operazioni critiche. Questi problemi possono impedirti di fare lo scale out dei workload per soddisfare la domanda o di eseguire upgrade essenziali dell'infrastruttura, il che potrebbe influire sull'affidabilità della tua applicazione.

Utilizza questa pagina per risolvere i problemi comuni dei pool di nodi. Trova indicazioni su come verificare se le risorse sono insufficienti, utilizzare funzionalità come il provisioning best-effort per creare nodi ed eseguire la migrazione dei workload in sicurezza senza causare interruzioni.

Queste informazioni sono importanti per gli amministratori e gli operatori della piattaforma responsabili della gestione dell'infrastruttura del cluster. Può essere utile anche per gli sviluppatori di applicazioni che devono capire in che modo le limitazioni dei pool di nodi potrebbero influire sui deployment delle loro applicazioni. Per ulteriori informazioni sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei contenuti di Google Cloud , consulta Ruoli e attività comuni degli utenti GKE.

Problemi di creazione del node pool

Questa sezione elenca i problemi che potrebbero verificarsi durante la creazione di nuovi node pool nei cluster Standard e fornisce suggerimenti su come risolverli.

Problema: la creazione del node pool non riesce a causa di risorse insufficienti

Il seguente problema si verifica quando crei un pool di nodi con hardware specifico in una zona Google Cloud che non dispone di hardware sufficiente per soddisfare i tuoi requisiti.

Per verificare che la creazione pool di nodi non sia riuscita perché una zona non disponeva di risorse sufficienti, controlla i log per individuare eventuali messaggi di errore pertinenti.

  1. Vai a Esplora log nella console Google Cloud :

    Vai a Esplora log

  2. Nel campo Query, specifica la seguente query:

    log_id(cloudaudit.googleapis.com/activity)
    resource.labels.cluster_name="CLUSTER_NAME"
    protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")
    

    Sostituisci CLUSTER_NAME con il nome del tuo cluster GKE.

  3. Fai clic su Esegui query.

Potresti visualizzare uno dei seguenti messaggi di errore:

  • resource pool exhausted
  • The zone does not have enough resources available to fulfill the request. Try a different zone, or try again later.
  • ZONE_RESOURCE_POOL_EXHAUSTED
  • ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS
  • Machine type with name 'MACHINE_NAME' does not exist in zone 'ZONE_NAME'

Per risolvere il problema, prova i seguenti suggerimenti:

  • Assicurati che la regione o la zona Google Cloud selezionata disponga dell'hardware specifico di cui hai bisogno. Utilizza la tabella di disponibilità di Compute Engine per verificare se zone specifiche supportano hardware specifico. Scegli unaGoogle Cloud regione o una zona diversa per i nodi che potrebbe avere una migliore disponibilità dell'hardware di cui hai bisogno.
  • Crea il pool di nodi con tipi di macchine più piccoli. Aumenta il numero di nodi nel pool di nodi in modo che la capacità di computing totale rimanga invariata.
  • Utilizza la prenotazione della capacità di Compute Engine per prenotare le risorse in anticipo.
  • Definisci una ComputeClass personalizzata con un elenco con priorità di serie di macchine di riserva e attiva la migrazione attiva (optimizeRulePriority: true). Questa configurazione consente a GKE di eseguire automaticamente il provisioning di hardware alternativo quando la serie di macchine preferita non è disponibile in una zona ed esegue la migrazione dei workload quando la capacità preferita viene ripristinata.
  • Utilizza il provisioning best-effort, descritto nella sezione seguente, per creare correttamente il pool di nodi se può eseguire il provisioning di almeno un numero minimo specificato di nodi rispetto al numero richiesto.

Provisioning best-effort

Per alcuni hardware, puoi utilizzare il provisioning best-effort, che indica a GKE di creare correttamente il pool di nodi se può eseguire il provisioning di almeno un numero minimo specificato di nodi. GKE continua a tentare di eseguire il provisioning dei nodi rimanenti per soddisfare la richiesta originale nel tempo. Per indicare a GKE di utilizzare il provisioning best-effort, utilizza il seguente comando:

gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --node-locations=ZONE1,ZONE2,... \
    --machine-type=MACHINE_TYPE
    --best-effort-provision \
    --min-provision-nodes=MINIMUM_NODES

Sostituisci quanto segue:

  • NODE_POOL_NAME: il nome del nuovo pool di nodi.
  • CONTROL_PLANE_LOCATION: la località di Compute Engine del control plane del tuo cluster. Specifica una regione per i cluster a livello di regione o una zona per i cluster a livello di zona.
  • ZONE1,ZONE2,...: le zone di Compute Engine per i nodi. Queste zone devono supportare l'hardware selezionato.
  • MACHINE_TYPE: il tipo di macchina Compute Engine per i nodi. Ad esempio, a2-highgpu-1g.
  • MINIMUM_NODES: il numero minimo di nodi di cui GKE deve eseguire il provisioning e creare correttamente il pool di nodi. Se omesso, il valore predefinito è 1.

Ad esempio, considera uno scenario in cui hai bisogno di 10 nodi con GPU NVIDIA A100 da 40 GB collegate in us-central1-c. In base alle località delle GPU, questa zona supporta le GPU A100. Per evitare errori di creazione del pool di nodi se non sono disponibili 10 macchine GPU, utilizza il provisioning best-effort.

gcloud container node-pools create a100-nodes \
    --cluster=ml-cluster \
    --location=us-central1 \
    --node-locations=us-central1-c \
    --num-nodes=10 \
    --machine-type=a2-highgpu-1g \
    --accelerator=type=nvidia-tesla-a100,count=1 \
    --best-effort-provision \
    --min-provision-nodes=5

GKE crea il pool di nodi anche se in us-central1-c sono disponibili solo cinque GPU. Nel tempo, GKE tenta di eseguire il provisioning di altri nodi fino a quando non sono presenti 10 nodi nel pool di nodi.

Errore: l'istanza non contiene i metadati "instance-template"

Potresti visualizzare il seguente errore come stato di un pool di nodi per cui non è possibile eseguire l'upgrade, la scalabilità o la riparazione automatica dei nodi:

Instance INSTANCE_NAME does not contain 'instance-template' metadata

Questo errore indica che i metadati delle istanze VM, allocate da GKE, sono stati danneggiati. In genere, questo accade quando l'automazione o gli script personalizzati tentano di aggiungere nuovi metadati delle istanze (come block-project-ssh-keys) ed eliminano anche i metadati esistenti, anziché limitarsi ad aggiungere o aggiornare i valori. Puoi leggere i metadati delle istanze VM in Impostazione dei metadati personalizzati.

Se uno dei valori dei metadati critici (tra gli altri: instance-template, kube-labels, kubelet-config, kubeconfig, cluster-name, configure-sh, cluster-uid) è stato eliminato, il nodo o l'intero pool di nodi potrebbe entrare in uno stato instabile, poiché questi valori sono fondamentali per le operazioni di GKE.

Se i metadati dell'istanza sono stati danneggiati, ti consigliamo di recuperarli ricreando il pool di nodi che contiene le istanze VM danneggiate. Dovrai aggiungere un node pool al cluster e aumentare il numero di nodi nel nuovo pool di nodi, isolando e rimuovendo i nodi in un altro. Consulta le istruzioni per eseguire la migrazione dei workload tra i pool di nodi.

Per scoprire chi ha modificato i metadati dell'istanza e quando, puoi esaminare le informazioni di audit logging di Compute Engine o trovare i log utilizzando Esplora log con una query di ricerca simile alla seguente:

resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"

Nei log puoi trovare l'indirizzo IP e lo user agent dell'autore della richiesta. Ad esempio:

requestMetadata: {
  callerIp: "REDACTED"
  callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}

Esegui la migrazione dei workload tra i node pool

Segui queste istruzioni per eseguire la migrazione dei workload da un pool di nodi a un altro. Se vuoi modificare gli attributi della macchina dei nodi nel tuo pool di nodi, consulta Scala verticalmente modificando gli attributi della macchina dei nodi.

Scopri come eseguire la migrazione dei pod a un nuovo pool di nodi

Per eseguire la migrazione dei pod in un nuovo pool di nodi, devi:

  1. Isola i nodi nel pool di nodi esistente: questa operazione contrassegna i nodi nel pool di nodi esistente come non pianificabili. Quando li contrassegni come non pianificabili, Kubernetes smette di pianificare nuovi pod in questi nodi.

  2. Svuota i nodi nel pool di nodi esistente: questa operazione rimuove in modo controllato i workload in esecuzione sui nodi del pool di nodi esistente.

Questi passaggi, eseguiti singolarmente per ogni nodo, causano l'arresto controllato dei pod in esecuzione nel pool di nodi esistente. Kubernetes li ripianifica su altri nodi disponibili.

Per assicurarti che Kubernetes termini le tue applicazioni in modo corretto, i container devono gestire l'indicatore SIGTERM. Utilizza questo approccio per chiudere le connessioni attive ai client ed eseguire il commit o il rollback delle transazioni del database in modo pulito. Nel manifest del pod, puoi utilizzare il campo spec.terminationGracePeriodSeconds per specificare il tempo di attesa di Kubernetes prima di arrestare i container nel pod. Il valore predefinito è 30 secondi. Puoi scoprire di più sulla terminazione dei pod nella documentazione di Kubernetes.

Puoi isolare e svuotare i nodi utilizzando i comandi kubectl cordon e kubectl drain.

Crea pool di nodi ed esegui la migrazione dei workload

Per eseguire la migrazione dei workload in un nuovo pool di nodi, crea il nuovo pool di nodi, quindi isola e svuota i nodi nel pool di nodi esistente:

  1. Aggiungi un node pool al tuo cluster.

    Verifica che il nuovo pool di nodi sia stato creato eseguendo questo comando:

    gcloud container node-pools list --cluster CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    Sostituisci quanto segue:

    • CLUSTER_NAME: il nome del cluster.
    • CONTROL_PLANE_LOCATION: la località di Compute Engine del control plane del tuo cluster. Specifica una regione per i cluster a livello di regione o una zona per i cluster a livello di zona.
  2. Per disattivare la scalabilità automatica sul pool di nodi esistente, se è attivata, esegui questo comando:

    gcloud container clusters update CLUSTER_NAME
        --location=CONTROL_PLANE_LOCATION \
        --no-enable-autoscaling \
        --node-pool=EXISTING_NODE_POOL_NAME
    
  3. Esegui questo comando per vedere su quale nodo sono in esecuzione i pod (vedi la colonna NODE):

    kubectl get pods -o=wide
    
  4. Recupera un elenco di nodi nel pool di nodi esistente, sostituendo EXISTING_NODE_POOL_NAME con il nome:

    kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
    
  5. Esegui il comando kubectl cordon NODE (sostituisci NODE con i nomi del comando precedente). Il seguente comando shell esegue l'iterazione di ogni nodo nel pool di nodi esistente e lo contrassegna come non pianificabile:

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl cordon "$node";
    done
    
  6. Facoltativamente, aggiorna i workload in esecuzione nel pool di nodi esistente per aggiungere un nodeSelector per l'etichetta cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME, dove NEW_NODE_POOL_NAME è il nome del nuovo node pool. In questo modo, GKE posiziona i workload sui nodi nel nuovo pool di nodi.

  7. Svuota ogni nodo espellendo tutti i pod con un periodo di arresto controllato assegnato di 10 secondi:

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=GRACEFUL_TERMINATION_SECONDS  "$node";
    done
    

    Sostituisci GRACEFUL_TERMINATION_PERIOD_SECONDS con il tempo necessario per l'arresto normale.

  8. Verifica che i nodi nel pool di nodi esistente abbiano lo stato SchedulingDisabled nell'elenco dei nodi eseguendo questo comando:

    kubectl get nodes
    

    Inoltre, dovresti vedere che i pod ora vengono eseguiti sui nodi nel nuovo pool di nodi:

    kubectl get pods -o=wide
    
  9. Elimina il pool di nodi esistente se non ti serve:

    gcloud container node-pools delete default-pool --cluster CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

Passaggi successivi