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 workload. Configurerai un cluster condiviso per due team di tenant in cui ogni team ha il proprio spazio dei nomi e ogni team crea job che condividono risorse globali. Configurerai anche Kueue per pianificare i job in base alle quote delle risorse che hai definito.

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 si fa riferimento nei Google Cloud contenuti, consulta Ruoli e attività comuni degli utenti di GKE.

Prima di leggere questa pagina, assicurati di conoscere i seguenti argomenti:

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 Job e la scalabilità automatica dei cluster per fornire un sistema batch end-to-end. Kueue implementa l'accodamento dei job, decidendo quando i job devono attendere e quando devono iniziare, in base alle quote e a una gerarchia per la condivisione equa delle risorse 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 l'accodamento dei job.
  • Non implementa nuovamente le funzionalità esistenti, come la scalabilità automatica, la pianificazione dei pod o la gestione del ciclo di vita dei job.
  • Kueue supporta in modo integrato l'API Kubernetes batch/v1.Job.
  • Può integrarsi con altre API di job.

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

Obiettivi

  1. Crea un cluster GKE
  2. Crea il ResourceFlavor
  3. Crea la ClusterQueue
  4. Crea la 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, consulta Liberare spazio.

Prima di iniziare

Configura il progetto

  1. Accedi al tuo Google Cloud account. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the GKE API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    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.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the GKE API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

Imposta i valori predefiniti per Google Cloud CLI

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

  2. Scarica il codice sorgente per 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 CONTROL_PLANE_LOCATION
    

    Sostituisci i seguenti valori:

    • PROJECT_ID: l'ID progetto Google Cloud .
    • CONTROL_PLANE_LOCATION: la regione Compute Engine del piano di controllo del cluster.

Crea un cluster GKE

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

    gcloud container clusters create-auto kueue-autopilot \
      --release-channel "rapid" --location CONTROL_PLANE_LOCATION
    

    I cluster Autopilot sono completamente gestiti e hanno la 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 regolare.

    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 Release 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 nei nodi disponibili nel cluster associandoli a etichette e taint dei nodi. Ad esempio, puoi utilizzare ResourceFlavor per rappresentare le VM con garanzie di provisioning diverse (ad esempio, spot rispetto a on demand), architetture (ad esempio, CPU x86 rispetto a ARM), brand 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, storage temporaneo 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

Un ClusterQueue è un oggetto con ambito cluster che gestisce un pool di risorse come CPU, memoria, GPU. Gestisce i ResourceFlavor, 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 della strategia di accodamento predefinita.
    • L'ammissione del workload segue la regola FIFO (first in first out), ma se non è disponibile una quota sufficiente per ammettere il workload all'inizio della coda, viene provato il successivo in coda.
  • StrictFIFO

    • Garantisce la semantica FIFO.
    • Il workload all'inizio della coda può bloccare l'accodamento finché non può essere ammesso.

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

Ogni flavor include limiti di utilizzo rappresentati come .spec.resourceGroups[].flavors[].resources[].nominalQuota. In questo caso, ClusterQueue ammette i workload 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 GiB
  • La somma delle richieste di GPU è inferiore o uguale a 10
  • La somma dello spazio di archiviazione utilizzato è inferiore o uguale a 10 GiB

Crea LocalQueue

Un LocalQueue è un oggetto con spazio dei nomi che accetta i workload degli utenti nello spazio dei nomi. I LocalQueue di spazi dei nomi diversi possono puntare allo stesso ClusterQueue in cui possono condividere la quota delle risorse. In questo caso, LocalQueue dagli spazi dei nomi team-a e team-b punta allo stesso 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 workload a LocalQueue nel proprio spazio dei nomi. A cui vengono poi allocate le risorse da ClusterQueue.

Esegui il deployment di LocalQueue:

kubectl apply -f local-queue.yaml

Crea job e osserva i workload ammessi

In questa sezione, creerai job Kubernetes nello spazio dei nomi team-a. Un controller Job in Kubernetes crea uno o più pod e contribuisce a garantire 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 puliti dopo 60 secondi in base al valore definito nel campo ttlSecondsAfterFinished.
  • Richiede 1500 milliCPU, 1536 Mi di memoria, 1536 Mi di storage temporaneo e tre GPU, poiché sono presenti tre pod.
apiVersion: batch/v1
kind: Job
metadata:
  namespace: team-a # Job under team-a namespace
  generateName: sample-job-team-a-
  labels:
    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 il cui spazio dei nomi appartiene a team-b, con richieste che rappresentano team diversi con esigenze diverse.

Per scoprire di più, consulta la sezione Eseguire il deployment dei workload 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 job per 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 da ClusterQueue, termina lo script premendo CTRL + C sullo script in esecuzione.

  8. Una volta completati tutti i job, nota che i nodi vengono sottoposti a scale down.

Libera spazio

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. Nella Google Cloud console, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID progetto, quindi fai clic su Chiudi per eliminare il progetto.

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 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 --location=CONTROL_PLANE_LOCATION
    

Passaggi successivi