Configura buffer di capacità

I buffer di capacità migliorano la reattività e l'affidabilità dei workload critici gestendo in modo proattivo la capacità di riserva del cluster e gli stati sospesi della capacità preconfigurata e di cui è stato eseguito il pre-provisioning utilizzando una CustomResourceDefinition (CRD) CapacityBuffer di Kubernetes. L'utilizzo dei buffer di capacità ti consente di definire esplicitamente una quantità specifica di capacità dei nodi inutilizzata all'interno del cluster. Questa capacità prenotata contribuisce a ridurre il tempo di pianificazione dei pod.

Quando un workload ad alta priorità deve fare lo scale up rapidamente, il nuovo workload può utilizzare immediatamente la capacità vuota senza attendere il provisioning dei nodi. Questo approccio riduce al minimo la latenza ed evita la contesa delle risorse durante picchi improvvisi della domanda.

Questa pagina mostra come configurare i buffer di capacità con replica fissa, limite di risorse e basati su percentuale, dedicare un buffer a un workload specifico, personalizzare il comportamento del buffer in standby e precaricare le immagini container.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti attività:

  • Abilita l'API Google Kubernetes Engine.
  • Abilita l'API Google Kubernetes Engine
  • Per utilizzare Google Cloud CLI per questa attività, installala e poi inizializza gcloud CLI. Se hai già installato gcloud CLI, scarica l'ultima versione eseguendo il comando gcloud components update. Le versioni precedenti di gcloud CLI potrebbero non supportare l'esecuzione dei comandi in questo documento.
  • Crea o accedi a un cluster GKE che esegue la versione 1.37.1-gke.3020000 o successiva. I buffer di standby sui cluster Autopilot richiedono ComputeClass personalizzate.
  • Attiva la creazione automatica dei node pool sui cluster Standard. Nei cluster Autopilot, la creazione automatica dei pool di nodi è già abilitata. La creazione automatica dei pool di nodi è facoltativa, ma consigliata per i buffer attivi e obbligatoria per i buffer in standby.

Crea oggetti Kubernetes prerequisiti

Per configurare un CapacityBuffer, devi disporre di uno spazio dei nomi che contenga tutti gli oggetti richiesti (il CapacityBuffer stesso e risorse aggiuntive come un PodTemplate o un workload). PodTemplate e CapacityBuffer devono trovarsi nello stesso spazio dei nomi. Puoi creare uno spazio dei nomi o utilizzarne uno esistente, incluso lo spazio dei nomi default.

A seconda del tipo di CapacityBuffer che stai configurando, devi anche avere uno dei seguenti elementi:

  • PodTemplate: definisce i requisiti delle risorse per una singola unità di capacità del buffer. La configurazione specificata nell'oggetto CapacityBuffer fa riferimento al template del pod.
  • Workload: un workload esistente a cui fai riferimento nell'oggetto CapacityBuffer. Questa guida utilizza un oggetto Deployment come workload di esempio, ma i buffer di capacità supportano uno dei seguenti tipi di risorse:

    • Deployment
    • ReplicaSet
    • StatefulSet
    • ReplicationController
    • Job
    • CustomResourceDefinition (CRD) che implementano la risorsa secondaria scale.

Questa sezione fornisce esempi di questi oggetti. Se hai già un workload che vuoi configurare con un buffer di capacità, vai ad Applica un buffer di capacità.

Per creare un workload Kubernetes di esempio, completa i seguenti passaggi:

  1. Salva il seguente manifest come namespace.yaml:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: capacity-buffer-example
      labels:
        name: capacity-buffer-example
    

    Questo manifest crea uno spazio dei nomi denominato capacity-buffer-example.

  2. (Facoltativo) Per utilizzare i buffer di capacità con una ComputeClass personalizzata, salva il seguente manifest come custom-compute-class.yaml:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: ccc-example
    spec:
      # Buffers are also created according to these priorities
      priorities:
      - machineFamily: n4
      - machineFamily: n4d
      - machineFamily: c4
      - machineFamily: c4d
      nodePoolAutoCreation:
        enabled: true
    

    Questo manifest crea un ComputeClass personalizzato che definisce e controlla le priorità di computing per i nodi di cui GKE esegue il provisioning. Per saperne di più, consulta ComputeClass personalizzate.

  3. Salva il seguente manifest come buffer-pod-template.yaml:

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: buffer-unit-template
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    template:
      spec:
        terminationGracePeriodSeconds: 0
        containers:
        - name: buffer-container
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              cpu: "1"
              memory: "1Gi"
            limits:
              cpu: "1"
              memory: "1Gi"
        # Optional: Using buffers with a custom ComputeClass /
        # controls the properties of the provisioned nodes.
        nodeSelector:
          cloud.google.com/compute-class: ccc-example
    

    Questo manifest crea un PodTemplate che definisce i requisiti delle risorse per una singola unità di capacità del buffer (1 CPU e 1Gi memoria). Questa configurazione specifica le dimensioni delle unità di capacità di cui GKE esegue il provisioning per il buffer. Ad esempio, con questo PodTemplate, GKE non considererà i nodi con meno di 1 CPU e 1 Gi di risorse disponibili come parte del buffer, se il cluster fa lo scale up.

  4. Salva il seguente manifest come sample-workload-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: critical-workload-ref
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: critical-workload
      template:
        metadata:
          labels:
            app: critical-workload
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sleep", "3600"]
            resources:
              requests:
                cpu: 100m
          # Optional: Using buffers with a custom ComputeClass /
          # controls the properties of the provisioned nodes.
          nodeSelector:
            cloud.google.com/compute-class: ccc-example
    

    Questo manifest crea un deployment di esempio con 10 repliche, che è l'oggetto di riferimento per l'esempio di buffer basato su percentuale nella sezione successiva.

  5. Applica i manifest al tuo cluster:

    kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yaml
    
  6. Verifica che GKE abbia creato gli oggetti:

    kubectl get podtemplate -n capacity-buffer-example
    kubectl get deployment critical-workload-ref -n capacity-buffer-example
    

    L'output è simile al seguente:

    NAME                   AGE
    buffer-unit-template   1m
    
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    critical-workload-ref   10/10   10           10          1m
    

Applica un buffer di capacità

Questa sezione fornisce esempi dei diversi tipi di buffer di capacità che puoi applicare ai tuoi workload.

Configura un buffer di repliche fisse

La configurazione di un CapacityBuffer con repliche fisse specifica il numero esatto di unità buffer che vuoi in base a un PodTemplate.

Per creare un buffer con repliche fisse, completa i seguenti passaggi:

  1. Salva il seguente manifest come cb-fixed-replicas.yaml:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: fixed-replica-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      replicas: 3
      provisioningStrategy: "STRATEGY"
    

    Sostituisci quanto segue:

    • NAMESPACE: il nome del tuo spazio dei nomi, ad esempio capacity-buffer-example.
    • POD_TEMPLATE: il PodTemplate che definisce i requisiti delle risorse, ad esempio buffer-unit-template.
    • STRATEGY: la strategia di provisioning, "buffer.x-k8s.io/active-capacity" (predefinita) o "buffer.gke.io/standby-capacity".

    Questo manifest crea una risorsa CapacityBuffer che fa riferimento a un PodTemplate per richiedere un numero specifico di unità buffer.

  2. Applica il manifest:

    kubectl apply -f cb-fixed-replicas.yaml
    
  3. Verifica che GKE abbia applicato il buffer di capacità:

    kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACE
    

    Il campo replicas nello stato dovrebbe mostrare 3, che riflette il numero di repliche che hai definito nel manifest. Il campo STATUS dovrebbe mostrare ReadyForProvisioning.

Configura un buffer dei limiti delle risorse

Puoi utilizzare il campo limits per definire una quantità massima di risorse che il buffer deve consumare, calcolata in base alle dimensioni del PodTemplate.

Per creare un buffer dei limiti delle risorse, completa i seguenti passaggi:

  1. Salva il seguente manifest come cb-resource-limits.yaml:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: resource-limit-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      limits:
        cpu: "5"
        memory: "5Gi"
      provisioningStrategy: "STRATEGY"
    

    Sostituisci quanto segue:

    • NAMESPACE: il nome del tuo spazio dei nomi, ad esempio capacity-buffer-example.
    • POD_TEMPLATE: il PodTemplate che definisce i requisiti delle risorse, ad esempio buffer-unit-template.
    • STRATEGY: la strategia di provisioning, "buffer.x-k8s.io/active-capacity" (predefinita) o "buffer.gke.io/standby-capacity".

    Questo manifest crea una risorsa CapacityBuffer con un limite totale di 5 CPU e 5 GiB di memoria. Se utilizzi l'esempio di PodTemplate del passaggio precedente, definisci ogni unità come 1 CPU e 1Gi memoria, il che dovrebbe comportare 5 unità buffer.

  2. Applica il manifest:

    kubectl apply -f cb-resource-limits.yaml
    
  3. Verifica che GKE abbia applicato il buffer di capacità:

    kubectl get capacitybuffer resource-limit-buffer -n NAMESPACE
    

    Controlla lo stato di CapacityBuffer. Il campo replicas deve mostrare un valore derivato dai limiti che hai definito. Se utilizzi l'esempio di PodTemplate della sezione precedente, dovresti vedere 5 unità buffer, perché questo è il numero massimo di unità che rientrano nei limiti definiti.

Configura un buffer basato su percentuale

La configurazione di un buffer basato su percentuale dimensiona dinamicamente il buffer in base a una percentuale di un workload scalabile esistente. I buffer di capacità basati su percentuale sono supportati solo per gli oggetti scalabili di Kubernetes che implementano la risorsa secondaria di scalabilità, come Deployment, StatefulSet, ReplicaSet o Job. Non puoi definire un buffer basato su percentuale per i template di pod perché non hanno un campo replicas.

Nella maggior parte dei casi, inizia con strategie di replica fissa o di limite delle risorse anziché con buffer basati su percentuali. Quando decidi, tieni presente quanto segue:

  • I buffer basati su percentuali sono meno reattivi agli scale up improvvisi se il workload viene scalato a numeri bassi o a zero, perché il margine di sicurezza diminuisce in proporzione ai pod attivi.
  • I nodi in standby comportano costi di computing durante il periodo di inizializzazione prima della sospensione. La scalabilità dinamica dei buffer di standby insieme alle fluttuazioni del workload spreca risorse di computing, quindi utilizza repliche fisse o limiti delle risorse per i buffer di standby.
  • I buffer basati su percentuali sono utili principalmente per i buffer attivi su deployment di grandi dimensioni che non eseguono mai lo scale down a un numero ridotto di repliche.

Per mantenere una dimensione minima del buffer quando il workload di riferimento fa lo scale down, imposta il campo replicas insieme al campo percentage. GKE utilizza il campo che genera più unità buffer. Per limitare la dimensione del buffer, imposta anche il campo limits.

Ad esempio, considera un buffer con percentage: 20 e replicas: 3 che fa riferimento a un deployment con 10 repliche. Poiché il 20% di 10 repliche è 2, che è inferiore al valore replicas di 3, GKE esegue il provisioning di 3 unità buffer. Se il deployment scala fino a 20 repliche, il buffer aumenta fino a 4 unità. Per maggiori informazioni, consulta la documentazione di riferimento di CapacityBuffer.

Per creare un buffer basato su percentuale, completa i seguenti passaggi:

  1. Salva il seguente manifest come cb-percentage-based.yaml:

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: percentage-buffer
      namespace: NAMESPACE
    spec:
      scalableRef:
        apiGroup: apps
        kind: Deployment
        name: SCALABLE_RESOURCE_NAME
      percentage: 20
      provisioningStrategy: "STRATEGY"
    

    Sostituisci quanto segue:

    • NAMESPACE: il nome dello spazio dei nomi.
    • SCALABLE_RESOURCE_NAME: il nome della risorsa scalabile, ad esempio critical-workload-ref.
    • STRATEGY: la strategia di provisioning, "buffer.x-k8s.io/active-capacity" (predefinita) o "buffer.gke.io/standby-capacity".

    Questo manifest crea una risorsa CapacityBuffer che richiede una dimensione del buffer equivalente al 20% delle repliche della risorsa di riferimento. Se utilizzi l'esempio di deployment della sezione precedente, il valore della replica è impostato su 10.

  2. Applica il manifest:

    kubectl apply -f cb-percentage-based.yaml
    
  3. Verifica che GKE abbia applicato il buffer di capacità:

    kubectl get capacitybuffer percentage-buffer -n NAMESPACE
    

    Controlla lo stato di CapacityBuffer. Il campo replicas dovrebbe mostrare un valore dal calcolo della percentuale. Se utilizzi l'esempio di deployment della sezione precedente, dovresti vedere 2 unità buffer, ovvero il 20% delle 10 repliche definite nel deployment.

  4. Testa la scalabilità dinamica eseguendo manualmente lo scale up del deployment fino a 20 repliche:

    kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20
    

    Il controller CapacityBuffer reagisce e scala automaticamente il buffer a 4 repliche.

Assegna un buffer di capacità a un workload specifico

Per impostazione predefinita, qualsiasi pod in attesa che corrisponda ai vincoli di pianificazione di un nodo buffer può richiedere la capacità del buffer. Quando più workload condividono una ComputeClass personalizzata o pool di nodi, utilizza la separazione dei workload per prenotare un buffer di capacità per un workload specifico. Questo approccio richiede la creazione automatica dei pool di nodi o un pool di nodi dedicato per i buffer attivi sui cluster Standard.

Evita di dedicare buffer di capacità separati a molti singoli workload. Ogni buffer dedicato richiede un proprio pool di nodi, il che aumenta il tempo necessario per il provisioning e il riempimento dei buffer. Per i conteggi dei buffer consigliati, consulta Scalabilità.

Per dedicare un buffer di capacità a un workload specifico, completa i seguenti passaggi:

  1. Nel manifest del workload, ad esempio sample-workload-deployment.yaml di Crea oggetti Kubernetes prerequisiti, aggiungi una tolleranza personalizzata e un selettore di nodi alla specifica del pod:

    spec:
      tolerations:
      - key: KEY
        operator: Equal
        value: "VALUE"
        effect: NoSchedule
      nodeSelector:
        KEY: "VALUE"
        cloud.google.com/compute-class: ccc-example
    

    Sostituisci quanto segue:

    • KEY: una chiave personalizzata per l'etichetta del taint e del nodo, ad esempio group. Per i prefissi delle chiavi limitati, consulta Limitazioni della separazione dei workload.
    • VALUE: un valore personalizzato che identifica il workload, ad esempio critical-workload.

    Sui cluster Autopilot, mantieni una ComputeClass personalizzata o un selettore hardware nel campo nodeSelector in modo che il buffer utilizzi la fatturazione basata sui nodi anziché il modello di fatturazione basato sui pod non supportato.

  2. Configura CapacityBuffer in modo che utilizzi gli stessi vincoli di pianificazione:

    • Se il CapacityBuffer utilizza il campo scalableRef, fai riferimento al workload nel campo spec.scalableRef. Il buffer eredita automaticamente i campi tolerations e nodeSelector del workload.
    • Se il tuo CapacityBuffer utilizza il campo podTemplateRef, aggiungi gli stessi campi tolerations e nodeSelector al manifest PodTemplate, ad esempio buffer-pod-template.yaml.
  3. Applica i manifest e crea il CapacityBuffer. Per le istruzioni, consulta Applica un buffer di capacità. Se precarichi le immagini nei buffer di standby, aggiungi anche la tolleranza personalizzata al DaemonSet di precaricamento in modo che possa pianificare sui nodi buffer dedicati. Se il buffer utilizza una ComputeClass personalizzata, il DaemonSet deve avere anche una tolleranza per il taint della ComputeClass:

    tolerations:
    - key: "buffer.gke.io/standby-capacity-node-suspended"
      operator: "Exists"
    - key: KEY
      operator: Equal
      value: "VALUE"
      effect: NoSchedule
    - key: cloud.google.com/compute-class
      operator: Equal
      value: ccc-example
      effect: NoSchedule
    
  4. Dopo che il gestore della scalabilità automatica dei cluster ha eseguito il provisioning dei nodi buffer, verifica che i nodi abbiano l'etichetta e la contaminazione dei nodi dedicate:

    kubectl get nodes -l KEY=VALUE \
        -o custom-columns='NAME:.metadata.name,TAINTS:.spec.taints[*].key'
    

    Ogni nodo nell'output elenca la chiave taint KEY. Se il buffer utilizza una ComputeClass personalizzata, i nodi elencano anche la chiave taint cloud.google.com/compute-class. I nodi buffer di standby hanno anche taint gestiti da GKE, come buffer.gke.io/standby-capacity-node-suspended sui nodi sospesi. Quando il tuo workload fa lo scale up, esegui kubectl get pods -n NAMESPACE -o wide e verifica che la colonna NODE elenchi i nomi dei nodi dedicati di questo output.

Personalizza il comportamento del buffer di standby

Puoi utilizzare le annotazioni per personalizzare l'avvio e l'aggiornamento dei buffer di standby. Aggiungi queste annotazioni al campo metadata.annotations della risorsa CapacityBuffer:

  • buffer.gke.io/standby-capacity-init-time: il periodo di tempo in cui un nodo rimane attivo dopo la creazione prima che GKE lo sospenda. Specifica una stringa di durata come 5m o 1h. Il valore predefinito è 5m.
  • buffer.gke.io/standby-capacity-refresh-frequency: la frequenza con cui GKE aggiorna i nodi sospesi. Specifica una stringa di durata come 12h o 24h, fino a un massimo di 120h (5 giorni). Il valore predefinito è 24h.

L'esempio seguente mostra un manifest con questi campi facoltativi per personalizzare il comportamento dei buffer di standby:

apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: customized-standby-buffer
  namespace: my-namespace
  annotations:
    buffer.gke.io/standby-capacity-init-time: "15m"
    buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
  podTemplateRef:
    name: buffer-unit-template
  replicas: 3
  provisioningStrategy: "buffer.gke.io/standby-capacity"

Precarica le immagini nei buffer di standby

Per velocizzare i tempi di avvio del workload quando un nodo in standby riprende, puoi precaricare le immagini container utilizzando un DaemonSet. Il DaemonSet viene eseguito durante il periodo di avvio prima della sospensione del nodo.

Per precaricare le immagini utilizzando il DaemonSet, completa i seguenti passaggi:

  1. Salva il seguente manifest come image-puller-daemonset.yaml:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: image-prefetch-daemonset
      namespace: NAMESPACE
    spec:
      selector:
        matchLabels:
          name: image-prefetch
      template:
        metadata:
          labels:
            name: image-prefetch
        spec:
          tolerations:
          - key: "buffer.gke.io/standby-capacity-node-suspended"
            operator: "Exists"
          initContainers:
          - name: image-puller
            image: IMAGE_NAME
            command: ["sh", "-c", "true"]
          containers:
          - name: pause
            image: registry.k8s.io/pause:3.9
    

    Sostituisci quanto segue:

    • NAMESPACE: lo spazio dei nomi per il DaemonSet, ad esempio capacity-buffer-example.
    • IMAGE_NAME: il nome dell'immagine da precaricare, ad esempio your-app-image:latest.

    Questo manifest include la tolleranza buffer.gke.io/standby-capacity-node-suspended in modo che il DaemonSet rimanga pianificato sui nodi in standby dopo che GKE li ha sospesi.

  2. Applica il manifest DaemonSet al tuo cluster:

    kubectl apply -f image-puller-daemonset.yaml
    
  3. Verifica che il DaemonSet sia stato creato:

    kubectl get daemonset image-prefetch-daemonset -n NAMESPACE
    
  4. Verifica che il buffer di capacità sia stato creato e sia pronto per il provisioning:

    kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

    Controlla lo stato. Il campo STATUS dovrebbe mostrare ReadyForProvisioning.

Monitora lo stato e le prestazioni del buffer di capacità

Puoi monitorare lo stato e l'integrità dei buffer di capacità utilizzando i comandi kubectl e le metriche di Cloud Monitoring.

Verifica lo stato della risorsa CapacityBuffer

Per controllare l'integrità dei buffer di capacità e verificare che siano pronti per ricevere i workload, completa i seguenti passaggi:

  1. Ottieni lo stato di tutti i buffer di capacità nel cluster:

    kubectl get capacitybuffer -A
    
  2. Esamina lo stato dettagliato, le condizioni e i log eventi di un buffer specifico:

    kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

Identifica i nodi buffer di standby sospesi

Le VM di buffer in standby sono pre-provisionate, ma mantenute in uno stato sospeso per ridurre i costi. Puoi riconoscere questi nodi sospesi perché hanno una condizione personalizzata. Per controllare le istanze di nodi sospesi, esegui questo comando:

kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'

Lo stato True indica che una VM di standby è sospesa. Lo stato False o <none> indica un nodo attivo in esecuzione.

Monitora le prestazioni con Cloud Monitoring

Per monitorare l'impatto end-to-end dei buffer di capacità sui tempi di scale up, utilizza le dashboard Latenza di avvio nella console Google Cloud . Utilizza i grafici Distribuzione latenza avvio pod e Latenza prima disponibilità pod per monitorare la metrica kubernetes.io/pod/latencies/pod_first_ready dalla creazione del pod all'idoneità. Puoi anche eseguire query sugli eventi Scheduled in Cloud Logging per misurare la latenza di pianificazione dei pod. Per istruzioni, consulta Monitora le metriche di latenza di avvio.

Rimuovi i buffer di capacità

Se non hai più bisogno di un buffer di capacità per i tuoi workload, elimina l'oggetto CapacityBuffer. In questo modo, i pod segnaposto vengono rimossi e il gestore della scalabilità automatica dei cluster può fare lo scale down dei nodi.

kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE

Sostituisci CAPACITY_BUFFER_NAME con il nome del CapacityBuffer che vuoi eliminare.

Risoluzione dei problemi

La sezione seguente contiene informazioni sulla risoluzione dei problemi comuni relativi ai buffer di capacità.

Buffer di capacità non pronto a causa del modello di fatturazione

Se crei un CapacityBuffer per un workload che utilizza il modello di fatturazione basato su pod (pagamento per pod), il buffer di capacità non sarà pronto per il provisioning.

Per identificare questo problema, controlla lo stato di CapacityBuffer:

kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE

Cerca una condizione di tipo ReadyForProvisioning con stato False.

Per risolvere il problema, assicurati che CapacityBuffer faccia riferimento a un workload o a un PodTemplate compatibile con la fatturazione basata sui nodi.

I pod buffer non sono pianificati sui nodi di cui è stato eseguito il provisioning da ComputeClass personalizzate

Se la dipendenza della configurazione di CapacityBuffer (ad esempio un PodTemplate) seleziona una ComputeClass personalizzata, potresti riscontrare un problema per cui i pod buffer non vengono pianificati sui nodi di cui è stato appena eseguito il provisioning. Questo problema fa sì che il gestore della scalabilità automatica dei cluster crei ripetutamente pool di nodi e nodi ridondanti, mentre i nodi inattivi vengono eliminati.

Questo problema si verifica se la ComputeClass personalizzata esegue il provisioning dei nodi con taint o requisiti di runtime specifici e i pod buffer (o il PodTemplate su cui si basano) non hanno tolleranze o impostazioni corrispondenti.

Per risolvere il problema, aggiorna la configurazione di CapacityBuffer in modo da specificare le tolleranze, i selettori di nodi o le classi di runtime richieste. Ad esempio, se la tua dipendenza seleziona una ComputeClass personalizzata configurata con GKE Sandbox, aggiorna la dipendenza per eseguire una delle seguenti operazioni:

  • Specifica il campo spec.runtimeClassName: gvisor.
  • Includi una tolleranza esplicita per l'effetto nocivo sandbox.gke.io/runtime=gvisor:NoSchedule.

Per saperne di più, consulta la documentazione relativa alla ComputeClass personalizzata.

I nodi buffer in standby non vengono ripristinati

I nodi buffer di standby sospesi potrebbero non riprendere l'esecuzione per uno dei seguenti motivi:

  • Per riprendere un nodo di standby sospeso, è necessaria la capacità di Compute Engine disponibile nella zona per il tipo di macchina del nodo e la generazione specifica della piattaforma CPU, ad esempio all'interno della serie di macchine E2 o N2. Se la zona non ha capacità di computing sufficiente per quella configurazione esatta, il nodo non riesce a riprendere. Per saperne di più, consulta Limitazioni di sospensione e ripristino di Compute Engine.
  • Se la tua ComputeClass personalizzata attiva la migrazione attiva ai nodi con priorità più alta (activeMigration.optimizeRulePriority: true) e posiziona le VM spot con una priorità più alta rispetto alle VM on demand, GKE esegue la migrazione dei nodi on demand in standby alle VM spot nel tempo. Poiché le VM spot sono più soggette a vincoli di capacità e le VM spot sospese non possono essere convertite in VM on demand al momento della ripresa, questi vincoli possono impedire la ripresa dei nodi in standby.
  • Il ripristino del nodo supera le quote di Compute Engine del tuo progetto. Per maggiori informazioni, consulta Il provisioning del buffer di capacità non riesce a causa dei limiti di quota.

Per identificare il motivo per cui un nodo di standby non è riuscito a riprendere, esegui una query sugli audit log di Compute Engine in Esplora log per individuare gli errori ZONE_RESOURCE_POOL_EXHAUSTED o QUOTA_EXCEEDED nelle operazioni compute.instances.resume.

Per risolvere o mitigare questo problema, procedi in uno o più dei seguenti modi:

  • Utilizza i cluster regionali in modo che il gestore della scalabilità automatica dei cluster possa eseguire il provisioning o riprendere i nodi in più zone.
  • Configura più famiglie di macchine nell'elenco spec.priorities della tua ComputeClass personalizzata. Se i nodi sospesi non possono riprendere, il gestore della scalabilità automatica dei cluster può tornare alla creazione di nuovi nodi in base a una regola di priorità diversa. Questi nuovi nodi richiedono più tempo per essere pronti rispetto ai nodi in standby ripristinati. Questa configurazione non aiuta i nodi sospesi a riprendere l'esecuzione, perché un nodo sospeso può riprendere l'esecuzione solo con il tipo di macchina originale.
  • Utilizza una ComputeClass personalizzata dedicata con VM on demand o imposta il campo activeMigration.optimizeRulePriority su false per la ComputeClass utilizzata dal buffer di standby.
  • Abbina il buffer di standby a un piccolo buffer attivo per assorbire i picchi di traffico immediati.

Il provisioning del buffer di capacità non riesce a causa dei limiti di quota

Un buffer di capacità potrebbe eseguire il provisioning di un numero di repliche inferiore a quello richiesto o non riuscire a fare lo scale up se supera i Kubernetes ResourceQuotas o le quote di Compute Engine.

Per identificare la quota che limita il buffer, controlla una o più delle seguenti quote:

  • Controlla se un ResourceQuota di Kubernetes nello spazio dei nomi limita il buffer:

    kubectl describe capacitybuffer \
        CAPACITY_BUFFER_NAME \
        -n NAMESPACE
    

    Nell'output status.conditions, cerca una condizione LimitedByQuotas con stato True. Sia le unità buffer attive che quelle di riserva, incluse le unità supportate da nodi di riserva sospesi, vengono conteggiate ai fini dei limiti di ResourceQuota dello spazio dei nomi come se i pod buffer fossero in esecuzione. Quando un buffer supera la quota dello spazio dei nomi, GKE limita il campo status.replicas per rientrare nella quota disponibile.

  • Controlla se le quote di progetto di Compute Engine bloccano il provisioning dei nodi. In Esplora log, cerca gli eventi no.scale.up.nap.quota.exceeded nel log container.googleapis.com/cluster-autoscaler-visibility o cerca gli errori QUOTA_EXCEEDED negli audit log di Compute Engine.

    Quando controlli le quote di Compute Engine per i buffer di standby, verifica entrambe le seguenti quote oltre a quelle per vCPU e memoria:

    • I nodi di standby sospesi conservano i propri indirizzi IP interni ed esterni, consumando la quota di indirizzi IP in uso.
    • Quando sospendi una VM di standby, Compute Engine scrive la memoria del nodo su disco, il che consuma una quota di disco di Persistent disk standard (GB) proporzionale alle dimensioni della memoria del nodo.

Per risolvere il problema del limite di quota, esegui una delle seguenti operazioni:

I pod DaemonSet smettono di ricevere dati dopo la ripresa di un nodo in standby

Dopo il ripristino di un nodo buffer in standby sospeso, i pod DaemonSet su quel nodo potrebbero smettere di ricevere dati tramite connessioni di lunga durata aperte prima della sospensione del nodo. I pod non registrano errori e non si riconnettono.

Questo problema si verifica quando un pod DaemonSet agisce come client di sola ricezione, ad esempio per una risposta HTTP in streaming, una connessione WebSocket, eventi inviati dal server o una chiamata di streaming del server gRPC. Mentre il nodo in standby è sospeso, il server o un dispositivo di rete intermedio va in timeout e chiude la connessione. Quando il nodo riprende, lo stack di rete del pod considera ancora la connessione aperta. Poiché il pod non invia dati, non rileva mai che la connessione è stata chiusa e attende i dati a tempo indeterminato.

Per risolvere questo problema, configura l'applicazione client nel pod DaemonSet in modo che rilevi le connessioni chiuse e si riconnetta eseguendo una delle seguenti operazioni:

  • Configura il keepalive TCP lato client nell'applicazione del pod (l'attivazione del keepalive solo sul server non invia notifiche al pod). Per saperne di più sui parametri TCP keepalive, consulta Connessioni inattive.
    1. Attiva l'opzione socket SO_KEEPALIVE nella libreria client o nel runtime del linguaggio, ad esempio socket.setKeepAlive(true, initialDelay) in Node.js o net.Dialer.KeepAlive in Go. Alcuni runtime disattivano il keepalive TCP per impostazione predefinita.
    2. Configura un tempo di inattività keepalive breve (TCP_KEEPIDLE), ad esempio alcuni secondi, anziché fare affidamento sul valore predefinito di sistema operativo.
    3. Aggiorna l'applicazione per rilevare l'errore di connessione (ad esempio una reimpostazione o un timeout della connessione) quando un probe keepalive non va a buon fine e apri una nuova connessione.
  • Configura heartbeat a livello di applicazione o timeout di lettura nel client, ad esempio frame ping e pong WebSocket o ping keepalive gRPC, e aggiorna l'applicazione in modo che si riconnetta quando si verifica un timeout.

Passaggi successivi