Esegui il deployment di un sistema batch utilizzando Kueue


Questo tutorial mostra come ottimizzare le risorse disponibili pianificando i job su Google Kubernetes Engine (GKE) con Kueue. In questo tutorial, imparerai a utilizzare Kueue per gestire e pianificare in modo efficace i job batch, migliorare l'utilizzo delle risorse e semplificare la gestione dei carichi di lavoro. Configuri un cluster condiviso per due team tenant in cui ogni team ha il proprio spazio dei nomi e ogni team crea job che condividono risorse globali. Configuri anche Kueue per pianificare i job in base alle quote di risorse che definisci.

Questo tutorial è rivolto agli architetti cloud e agli ingegneri di piattaforma interessati a implementare un sistema batch utilizzando GKE. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui viene fatto riferimento nei contenuti di Google Cloud, consulta la pagina Ruoli utente e attività comuni di GKE Enterprise.

Prima di leggere questa pagina, assicurati di avere familiarità con quanto segue:

Sfondo

I job sono applicazioni che vengono eseguite fino al completamento, come machine learning, rendering, simulazione, analisi, CI/CD e workload simili.

Kueue è un programma di pianificazione dei job cloud-native che funziona con il programma di pianificazione Kubernetes predefinito, il controller dei job e il gestore della scalabilità automatica del cluster per fornire un sistema batch end-to-end. Kueue implementa la gestione delle code dei job, decidendo quando i job devono attendere e quando devono iniziare, in base alle quote e a una gerarchia per la condivisione delle risorse in modo equo tra i team.

Kueue ha le seguenti caratteristiche:

  • È ottimizzato per le architetture cloud, in cui le risorse sono eterogenee, intercambiabili e scalabili.
  • Fornisce un insieme di API per gestire le quote elastiche e la gestione della coda dei job.
  • Non implementa nuovamente funzionalità esistenti come lo scalabilità automatica, la pianificazione dei pod o la gestione del ciclo di vita dei job.
  • Kueue supporta l'API Kubernetesbatch/v1.Job.
  • Può essere integrato con altre API di lavoro.

Kueue si riferisce ai job definiti con qualsiasi API come carichi di lavoro, per evitare confusione con l'API Kubernetes Job specifica.

Obiettivi

  1. Crea un cluster GKE
  2. Crea ResourceFlavor
  3. Crea ClusterQueue
  4. Crea LocalQueue
  5. Crea job e osserva i workload ammessi

Costi

Questo tutorial utilizza i seguenti componenti fatturabili di Google Cloud:

Utilizza il Calcolatore prezzi per generare una stima dei costi in base all'utilizzo previsto.

Al termine di questo tutorial, evita l'addebito di ulteriori costi eliminando le risorse create. Per ulteriori informazioni, vedi Pulizia.

Prima di iniziare

Configura il progetto

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the GKE API.

    Enable the API

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE API.

    Enable the API

  8. Impostare i valori predefiniti per Google Cloud CLI

    1. Nella console Google Cloud , avvia un'istanza Cloud Shell:
      Apri Cloud Shell

    2. Scarica il codice sorgente di questa app di esempio:

      git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
      cd kubernetes-engine-samples/batch/kueue-intro
      
    3. Imposta le variabili di ambiente predefinite:

      gcloud config set project PROJECT_ID
      gcloud config set compute/region COMPUTE_REGION
      

      Sostituisci i seguenti valori:

    Crea un cluster GKE

    1. Crea un cluster GKE Autopilot denominato kueue-autopilot:

      gcloud container clusters create-auto kueue-autopilot \
        --release-channel "rapid" --region COMPUTE_REGION
      

      I cluster Autopilot sono completamente gestiti e dispongono di scalabilità automatica integrata. Scopri di più su GKE Autopilot.

      Kueue supporta anche GKE Standard con il provisioning automatico dei nodi e i pool di nodi con scalabilità automatica regolari.

      Una volta creato il cluster, il risultato è simile al seguente:

        NAME: kueue-autopilot
        LOCATION: us-central1
        MASTER_VERSION: 1.26.2-gke.1000
        MASTER_IP: 35.193.173.228
        MACHINE_TYPE: e2-medium
        NODE_VERSION: 1.26.2-gke.1000
        NUM_NODES: 3
        STATUS: RUNNING
      

      Dove STATUS è RUNNING per kueue-autopilot.

    2. Recupera le credenziali di autenticazione per il cluster:

      gcloud container clusters get-credentials kueue-autopilot
      
    3. Installa Kueue sul cluster:

      VERSION=VERSION
      kubectl apply --server-side -f \
        https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
      

      Sostituisci VERSION con l'ultima versione di Kueue. Per ulteriori informazioni sulle versioni di Kueue, consulta Versioni di Kueue.

    4. Attendi che i pod Kueue siano pronti:

      watch kubectl -n kueue-system get pods
      

      Prima di poter continuare, l'output dovrebbe essere simile al seguente:

      NAME                                        READY   STATUS    RESTARTS   AGE
      kueue-controller-manager-66d8bb946b-wr2l2   2/2     Running   0          3m36s
      
    5. Crea due nuovi spazi dei nomi denominati team-a e team-b:

      kubectl create namespace team-a
      kubectl create namespace team-b
      

    Crea ResourceFlavor

    Un ResourceFlavor è un oggetto che rappresenta le variazioni dei nodi disponibili nel cluster associandoli a etichette e taint dei nodi. Ad esempio, puoi utilizzare ResourceFlavors per rappresentare VM con diverse garanzie di provisioning (ad esempio spot rispetto a on demand), architetture (ad esempio CPU x86 rispetto a ARM), marche e modelli (ad esempio GPU Nvidia A100 rispetto a T4).

    In questo tutorial, il cluster kueue-autopilot ha risorse omogenee. Di conseguenza, crea un singolo ResourceFlavor per CPU, memoria, ephemeral-storage e GPU, senza etichette o taint.

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ResourceFlavor
    metadata:
      name: default-flavor # This ResourceFlavor will be used for all the resources
    Esegui il deployment di ResourceFlavor:

    kubectl apply -f flavors.yaml
    

    Crea ClusterQueue

    Una ClusterQueue è un oggetto con ambito a livello di cluster che gestisce un pool di risorse come CPU, memoria e GPU. Gestisce ResourceFlavors, limita l'utilizzo e determina l'ordine in cui vengono ammessi i workload.

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
      name: cluster-queue
    spec:
      namespaceSelector: {} # Available to all namespaces
      queueingStrategy: BestEffortFIFO # Default queueing strategy
      resourceGroups:
      - coveredResources: ["cpu", "memory", "nvidia.com/gpu", "ephemeral-storage"]
        flavors:
        - name: "default-flavor"
          resources:
          - name: "cpu"
            nominalQuota: 10
          - name: "memory"
            nominalQuota: 10Gi
          - name: "nvidia.com/gpu"
            nominalQuota: 10
          - name: "ephemeral-storage"
            nominalQuota: 10Gi

    Esegui il deployment di ClusterQueue:

    kubectl apply -f cluster-queue.yaml
    

    L'ordine di consumo è determinato da .spec.queueingStrategy, dove sono presenti due configurazioni:

    • BestEffortFIFO

      • La configurazione predefinita della strategia di accodamento.
      • L'ammissione del carico di lavoro segue la regola FIFO (first in first out), ma se non è disponibile una quota sufficiente per ammettere il carico di lavoro in testa alla coda, viene provato il successivo in coda.
    • StrictFIFO

      • Garantisce la semantica FIFO.
      • Il carico di lavoro in testa alla coda può bloccare l'accodamento finché non può essere ammesso.

    In cluster-queue.yaml, crea una nuova ClusterQueue denominata cluster-queue. Questo ClusterQueue gestisce quattro risorse, cpu, memory, nvidia.com/gpu e ephemeral-storage con il tipo creato in flavors.yaml. La quota viene consumata dalle richieste nelle specifiche dei pod del workload.

    Ogni sapore include limiti di utilizzo rappresentati come .spec.resourceGroups[].flavors[].resources[].nominalQuota. In questo caso, ClusterQueue ammette i carichi di lavoro se e solo se:

    • La somma delle richieste di CPU è inferiore o uguale a 10
    • La somma delle richieste di memoria è inferiore o uguale a 10 Gi
    • La somma delle richieste di GPU è inferiore o uguale a 10
    • La somma dello spazio di archiviazione utilizzato è minore o uguale a 10 Gi

    Crea LocalQueue

    Una LocalQueue è un oggetto con spazio dei nomi che accetta i workload degli utenti nello spazio dei nomi. LocalQueues di spazi dei nomi diversi possono puntare alla stessa ClusterQueue, dove possono condividere la quota delle risorse. In questo caso, LocalQueue dallo spazio dei nomi team-a e team-b punta alla stessa ClusterQueue cluster-queue in .spec.clusterQueue.

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      namespace: team-a # LocalQueue under team-a namespace
      name: lq-team-a
    spec:
      clusterQueue: cluster-queue # Point to the ClusterQueue
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      namespace: team-b # LocalQueue under team-b namespace
      name: lq-team-b
    spec:
      clusterQueue: cluster-queue # Point to the ClusterQueue

    Ogni team invia i propri carichi di lavoro a LocalQueue nel proprio spazio dei nomi. A cui vengono poi allocate le risorse da ClusterQueue.

    Esegui il deployment di LocalQueues:

    kubectl apply -f local-queue.yaml
    

    Crea job e osserva i workload ammessi

    In questa sezione, creerai i job Kubernetes nello spazio dei nomi team-a. Un controller Job in Kubernetes crea uno o più pod e assicura che eseguano correttamente un'attività specifica.

    Il job nello spazio dei nomi team-a ha i seguenti attributi:

    • Punta a LocalQueue lq-team-a.
    • Richiede risorse GPU impostando il campo nodeSelector su nvidia-tesla-t4.
    • È composto da tre pod che rimangono inattivi per 10 secondi in parallelo. I job vengono eliminati dopo 60 secondi in base al valore definito nel campo ttlSecondsAfterFinished.
    • Richiede 1500 millicpu, 1536 Mi di memoria, 1536 Mi di spazio di archiviazione temporanea e tre GPU, poiché ci sono tre pod.
    apiVersion: batch/v1
    kind: Job
    metadata:
      namespace: team-a # Job under team-a namespace
      generateName: sample-job-team-a-
      annotations:
        kueue.x-k8s.io/queue-name: lq-team-a # Point to the LocalQueue
    spec:
      ttlSecondsAfterFinished: 60 # Job will be deleted after 60 seconds
      parallelism: 3 # This Job will have 3 replicas running at the same time
      completions: 3 # This Job requires 3 completions
      suspend: true # Set to true to allow Kueue to control the Job when it starts
      template:
        spec:
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-tesla-t4" # Specify the GPU hardware
          containers:
          - name: dummy-job
            image: gcr.io/k8s-staging-perf-tests/sleep:latest
            args: ["10s"] # Sleep for 10 seconds
            resources:
              requests:
                cpu: "500m"
                memory: "512Mi"
                ephemeral-storage: "512Mi"
                nvidia.com/gpu: "1"
              limits:
                cpu: "500m"
                memory: "512Mi"
                ephemeral-storage: "512Mi"
                nvidia.com/gpu: "1"
          restartPolicy: Never

    I job vengono creati anche nel file job-team-b.yaml in cui il relativo spazio dei nomi appartiene a team-b, con richieste di rappresentare team diversi con esigenze diverse.

    Per saperne di più, consulta la sezione Deployment dei carichi di lavoro GPU in Autopilot.

    1. In un nuovo terminale, osserva lo stato di ClusterQueue che si aggiorna ogni due secondi:

      watch -n 2 kubectl get clusterqueue cluster-queue -o wide
      
    2. In un nuovo terminale, osserva lo stato dei nodi:

      watch -n 2 kubectl get nodes -o wide
      
    3. In un nuovo terminale, crea Jobs to LocalQueue dagli spazi dei nomi team-a e team-b ogni 10 secondi:

      ./create_jobs.sh job-team-a.yaml job-team-b.yaml 10
      
    4. Osserva i job accodati, ammessi in ClusterQueue e i nodi attivati con GKE Autopilot.

    5. Ottieni un job dallo spazio dei nomi team-a:

      kubectl -n team-a get jobs
      

      Il risultato è simile al seguente:

      NAME                      COMPLETIONS   DURATION   AGE
      sample-job-team-b-t6jnr   3/3           21s        3m27s
      sample-job-team-a-tm7kc   0/3                      2m27s
      sample-job-team-a-vjtnw   3/3           30s        3m50s
      sample-job-team-b-vn6rp   0/3                      40s
      sample-job-team-a-z86h2   0/3                      2m15s
      sample-job-team-b-zfwj8   0/3                      28s
      sample-job-team-a-zjkbj   0/3                      4s
      sample-job-team-a-zzvjg   3/3           83s        4m50s
      
    6. Copia il nome di un job dal passaggio precedente e osserva lo stato di ammissione e gli eventi di un job tramite l'API Workloads:

      kubectl -n team-a describe workload JOB_NAME
      
    7. Quando i job in attesa iniziano ad aumentare dalla coda ClusterQueue, termina lo script premendo CTRL + C sullo script in esecuzione.

    8. Una volta completati tutti i job, nota la riduzione del numero di nodi.

    Esegui la pulizia

    Per evitare che al tuo Account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

    Elimina il progetto

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Elimina la singola risorsa

    1. Elimina il sistema di quote Kueue:

      kubectl delete -n team-a localqueue lq-team-a
      kubectl delete -n team-b localqueue lq-team-b
      kubectl delete clusterqueue cluster-queue
      kubectl delete resourceflavor default-flavor
      
    2. Elimina il manifest di Kueue:

      VERSION=VERSION
      kubectl delete -f \
        https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
      
    3. Elimina il cluster:

      gcloud container clusters delete kueue-autopilot --region=COMPUTE_REGION
      

    Passaggi successivi