En este tutorial se muestra cómo optimizar los recursos disponibles programando trabajos en Google Kubernetes Engine (GKE) con Kueue. En este tutorial, aprenderás a usar Kueue para gestionar y programar de forma eficaz trabajos por lotes, mejorar el uso de los recursos y simplificar la gestión de las cargas de trabajo. Configuras un clúster compartido para dos equipos de clientes, donde cada equipo tiene su propio espacio de nombres y crea trabajos que comparten recursos globales. También puedes configurar Kueue para programar las tareas en función de las cuotas de recursos que definas.
Este tutorial está dirigido a arquitectos de Cloud e ingenieros de plataformas que quieran implementar un sistema de procesamiento por lotes con GKE. Para obtener más información sobre los roles habituales y las tareas de ejemplo que se mencionan en el contenido, consulta Roles y tareas de usuario habituales de GKE. Google Cloud
Antes de leer esta página, asegúrese de que conoce los siguientes conceptos:
Fondo
Los trabajos son aplicaciones que se ejecutan hasta completarse, como el aprendizaje automático, el renderizado, la simulación, las analíticas, la integración y la entrega continuas (CI/CD) y cargas de trabajo similares.
Kueue es un programador de tareas nativo de la nube que funciona con el programador predeterminado de Kubernetes, el controlador de tareas y el autoescalador de clústeres para proporcionar un sistema de procesamiento por lotes integral. Kueue implementa la puesta en cola de trabajos, decidiendo cuándo deben esperar los trabajos y cuándo deben iniciarse, en función de las cuotas y una jerarquía para compartir recursos de forma equitativa entre los equipos.
Kueue tiene las siguientes características:
- Está optimizado para arquitecturas de nube, donde los recursos son heterogéneos, intercambiables y escalables.
- Proporciona un conjunto de APIs para gestionar cuotas elásticas y colas de trabajos.
- No vuelve a implementar funciones ya disponibles, como el escalado automático, la programación de pods o la gestión del ciclo de vida de los trabajos.
- Kueue tiene compatibilidad integrada con la API de Kubernetes
batch/v1.Job
. - Se puede integrar con otras APIs de empleo.
Kueue se refiere a los trabajos definidos con cualquier API como cargas de trabajo para evitar la confusión con la API de trabajo específica de Kubernetes.
Crear el ResourceFlavor
Un ResourceFlavor es un objeto que representa las variaciones de los nodos disponibles en tu clúster asociándolos con etiquetas y taints de nodo. Por ejemplo, puedes usar ResourceFlavors para representar máquinas virtuales con diferentes garantías de aprovisionamiento (por ejemplo, de tipo spot o bajo demanda), arquitecturas (por ejemplo, CPUs x86 o ARM), marcas y modelos (por ejemplo, GPUs Nvidia A100 o T4).
En este tutorial, el clúster kueue-autopilot
tiene recursos homogéneos.
Por lo tanto, crea un único ResourceFlavor para CPU, memoria, almacenamiento efímero y GPUs, sin etiquetas ni taints.
kubectl apply -f flavors.yaml
Crear el ClusterQueue
Un ClusterQueue es un objeto con ámbito de clúster que gestiona un conjunto de recursos, como CPU, memoria y GPU. Gestiona los ResourceFlavors, limita el uso y determina el orden en el que se admiten las cargas de trabajo.
Despliega ClusterQueue:
kubectl apply -f cluster-queue.yaml
El orden de consumo se determina mediante .spec.queueingStrategy
, donde hay dos configuraciones:
BestEffortFIFO
- La configuración predeterminada de la estrategia de colas.
- La admisión de cargas de trabajo sigue la regla de FIFO (primero en entrar, primero en salir), pero si no hay suficiente cuota para admitir la carga de trabajo que está al principio de la cola, se intenta con la siguiente.
StrictFIFO
- Garantiza la semántica FIFO.
- La carga de trabajo al principio de la cola puede bloquear la puesta en cola hasta que se pueda admitir la carga de trabajo.
En cluster-queue.yaml
, crea un ClusterQueue llamado cluster-queue
. Este ClusterQueue gestiona cuatro recursos: cpu
, memory
, nvidia.com/gpu
y ephemeral-storage
, con el sabor creado en flavors.yaml
.
La cuota se consume con las solicitudes de las especificaciones de los pods de la carga de trabajo.
Cada variante incluye límites de uso representados como
.spec.resourceGroups[].flavors[].resources[].nominalQuota
. En este caso, ClusterQueue admite cargas de trabajo si y solo si:
- La suma de las solicitudes de CPU es inferior o igual a 10
- La suma de las solicitudes de memoria es inferior o igual a 10 Gi
- La suma de las solicitudes de GPU es inferior o igual a 10
- La suma del almacenamiento utilizado es inferior o igual a 10 Gi
Crea el LocalQueue
LocalQueue es un objeto con espacio de nombres que acepta cargas de trabajo de los usuarios del espacio de nombres.
Las LocalQueues de diferentes espacios de nombres pueden apuntar a la misma ClusterQueue, donde pueden compartir la cuota de recursos. En este caso, LocalQueue de los espacios de nombres team-a
y team-b
apunta al mismo ClusterQueue cluster-queue
en .spec.clusterQueue
.
Cada equipo envía sus cargas de trabajo a LocalQueue en su propio espacio de nombres. A continuación, ClusterQueue les asigna recursos.
Implementa LocalQueues:
kubectl apply -f local-queue.yaml
Crea trabajos y observa las cargas de trabajo admitidas
En esta sección, creará trabajos de Kubernetes en el espacio de nombres team-a
. Un controlador de trabajo de Kubernetes crea uno o varios pods y se asegura de que ejecuten correctamente una tarea específica.
El trabajo del espacio de nombres team-a
tiene los siguientes atributos:
- Apunta a
lq-team-a
LocalQueue. - Solicita recursos de GPU asignando el valor
nvidia-tesla-t4
al camponodeSelector
. - Se compone de tres pods que duermen durante 10 segundos en paralelo. Las tareas se eliminan después de 60 segundos, según el valor definido en el campo
ttlSecondsAfterFinished
. - Requiere 1500 miliCPU, 1536 Mi de memoria, 1536 Mi de almacenamiento efímero y tres GPUs, ya que hay tres pods.
Los trabajos también se crean en el archivo
job-team-b.yaml
cuyo espacio de nombres pertenece a team-b
, con solicitudes para
representar diferentes equipos con diferentes necesidades.
Para obtener más información, consulta el artículo sobre cómo desplegar cargas de trabajo de GPUs en Autopilot.
En una terminal nueva, observa el estado de ClusterQueue, que se actualiza cada dos segundos:
watch -n 2 kubectl get clusterqueue cluster-queue -o wide
En una terminal nueva, observa el estado de los nodos:
watch -n 2 kubectl get nodes -o wide
En un terminal nuevo, crea tareas en LocalQueue desde el espacio de nombres
team-a
yteam-b
cada 10 segundos:./create_jobs.sh job-team-a.yaml job-team-b.yaml 10
Observa las tareas que se ponen en cola, se admiten en ClusterQueue y los nodos que se activan con Autopilot de GKE.
Obtener un trabajo del espacio de nombres
team-a
:kubectl -n team-a get jobs
El resultado es similar al siguiente:
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
Copia el nombre de un trabajo del paso anterior y observa el estado de admisión y los eventos de un trabajo a través de la API Workloads:
kubectl -n team-a describe workload JOB_NAME
Cuando los trabajos pendientes empiecen a aumentar en ClusterQueue, finaliza la secuencia de comandos pulsando
CTRL + C
en la secuencia de comandos en ejecución.Una vez que se hayan completado todos los trabajos, verás que los nodos se reducen.