En este instructivo, se muestra cómo optimizar los recursos disponibles programando trabajos en Google Kubernetes Engine (GKE) con Kueue. En este instructivo, aprenderás a usar Kueue para administrar y programar de manera eficaz trabajos por lotes, mejorar el uso de recursos y simplificar la administración de cargas de trabajo. Configuras un clúster compartido para dos equipos de inquilinos en el que cada equipo tiene su propio espacio de nombres y cada equipo crea Jobs que comparten recursos globales. También puedes configurar Kueue para programar los trabajos según las cuotas de recursos que definas.
Este instructivo está dirigido a arquitectos de Cloud y a ingenieros de plataformas interesados en implementar un sistema de procesamiento por lotes con GKE. Para obtener más información sobre los roles comunes y las tareas de ejemplo a los que se hace referencia en el contenido de Google Cloud, consulta Roles y tareas comunes de los usuarios de GKE.
Antes de leer esta página, asegúrate de estar familiarizado con lo siguiente:
Fondo
Los Jobs son aplicaciones que se ejecutan hasta su finalización, como el aprendizaje automático, la renderización, la simulación, las estadísticas, la CI/CD y las cargas de trabajo similares.
Kueue es un programador de trabajos nativo de la nube que funciona con el programador predeterminado de Kubernetes, el controlador de trabajos y el escalador automático del clúster para proporcionar un sistema por lotes de extremo a extremo. Kueue implementa la cola de Jobs, decide cuándo deben esperar los Jobs y cuándo deben iniciarse según las cuotas y una jerarquía para compartir recursos de manera equitativa entre los equipos.
Kueue tiene las siguientes características:
- Está optimizado para arquitecturas en la nube, en las que los recursos son heterogéneos, intercambiables y escalables.
- Proporciona un conjunto de APIs para administrar cuotas elásticas y una cola de Jobs.
- No vuelve a implementar las funciones existentes, como el ajuste de escala automático, la programación de Pods o la administración del ciclo de vida de los trabajos.
- Kueue tiene compatibilidad integrada con la API de
batch/v1.Job
de Kubernetes. - Se puede integrar en otras API de trabajo.
Kueue hace referencia a los trabajos definidos con cualquier API como cargas de trabajo para evitar confusiones con la API de trabajo de Kubernetes específica.
Crea ResourceFlavor
Un ResourceFlavor es un objeto que representa las variaciones en los nodos disponibles en tu clúster mediante la asociación de etiquetas y taints de nodo. Por ejemplo, puedes usar los objetos ResourceFlavor para representar las VMs con diferentes garantías de aprovisionamiento (por ejemplo, puntual y a pedido), arquitecturas (por ejemplo, CPU x86 frente a CPU ARM), marcas y modelos (por ejemplo, GPU Nvidia A100 frente a GPU T4).
En este instructivo, el clúster kueue-autopilot
tiene recursos homogéneos.
Como resultado, crea un solo objeto ResourceFlavor por CPU, memoria, almacenamiento efímero y GPU, sin etiquetas ni taints.
kubectl apply -f flavors.yaml
Crea ClusterQueue
Un ClusterQueue es un objeto con permisos de clúster que administra un grupo de recursos, como CPU, memoria y GPU. Administra los objetos ResourceFlavor, limita el uso y determina el orden en que se admiten las cargas de trabajo.
Implementa ClusterQueue:
kubectl apply -f cluster-queue.yaml
El orden de consumo se determina mediante .spec.queueingStrategy
, en el que hay dos parámetros de configuración:
BestEffortFIFO
- La configuración predeterminada de la estrategia de cola.
- La admisión de carga de trabajo sigue la regla primero en entrar, primero en salir (FIFO), pero si no hay suficiente cuota para admitir la carga de trabajo en el encabezado de la cola, se prueba la siguiente en la línea.
StrictFIFO
- Garantiza la semántica de FIFO.
- La carga de trabajo que está en el encabezado de la cola puede bloquear la cola hasta que se pueda admitir la carga de trabajo.
En cluster-queue.yaml
, debes crear un objeto ClusterQueue nuevo llamado cluster-queue
. Este objeto ClusterQueue administra cuatro recursos, cpu
, memory
, nvidia.com/gpu
y ephemeral-storage
con la variante creada en flavors.yaml
.
Las solicitudes en las especificaciones del Pod de la carga de trabajo consumen la cuota.
Cada variante incluye límites de uso representados como .spec.resourceGroups[].flavors[].resources[].nominalQuota
. En este caso, ClusterQueue admite cargas de trabajo solo si se cumplen las siguientes condiciones:
- La suma de las solicitudes de CPU es menor o igual que 10
- La suma de las solicitudes de memoria es menor o igual que 10Gi
- La suma de solicitudes de GPU es menor o igual que 10
- La suma del almacenamiento usado es menor o igual que 10Gi
Crea LocalQueue
Un LocalQueue es un objeto con espacio de nombres que acepta cargas de trabajo de los usuarios en el espacio de nombres.
Los objetos LocalQueue de diferentes espacios de nombres pueden apuntar al mismo ClusterQueue en el que pueden compartir la cuota de los recursos. En este caso, el objeto LocalQueue del espacio de nombres team-a
y team-b
apunta al mismo ClusterQueue cluster-queue
en .spec.clusterQueue
.
Cada equipo envía sus cargas de trabajo al objeto LocalQueue en su propio espacio de nombres. Luego, ClusterQueue asigna recursos.
Implementa los objetos LocalQueue:
kubectl apply -f local-queue.yaml
Crea Jobs y observa las cargas de trabajo admitidas
En esta sección, crearás Jobs de Kubernetes en el espacio de nombres team-a
. Un controlador de Job en Kubernetes crea uno o más Pods y garantiza que ejecuten correctamente una tarea específica.
El trabajo en el espacio de nombres team-a
tiene los siguientes atributos:
- Apunta al objeto LocalQueue
lq-team-a
. - Solicita recursos de GPU configurando el campo
nodeSelector
ennvidia-tesla-t4
. - Se compone de tres Pods que se suspenden durante 10 segundos en paralelo. Los trabajos se limpian después de 60 segundos según el valor definido en el campo
ttlSecondsAfterFinished
. - Requiere 1,500 millicores de CPU, 1,536 Mi de memoria, 1,536 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
, en el que su espacio de nombres pertenece a team-b
, con solicitudes para representar diferentes equipos con diferentes necesidades.
Para obtener más información, consulta Implementa cargas de trabajo de GPU 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 una terminal nueva, crea Jobs 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 cómo se ponen en cola los Jobs, cómo se admiten en ClusterQueue y cómo se activan los nodos con Autopilot de GKE.
Obtén un Job 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 Job del paso anterior y observa el estado de admisión y los eventos para un Job a través de la API de cargas de trabajo:
kubectl -n team-a describe workload JOB_NAME
Cuando los Jobs pendientes comiencen a aumentar desde el objeto ClusterQueue, presiona
CTRL + C
en la secuencia de comandos en ejecución para finalizarla.Una vez que se hayan completado todos los Jobs, observa que los nodos se reducen.