Introducción

Ejecutar un job de entrenamiento distribuido en Kubernetes siempre implicó un trade-off incómodo: o reservás recursos de forma estática (desperdiciando capacidad cuando el job no corre) o confiás en que el scheduler coloque todos los pods simultáneamente, algo que el modelo pod-por-pod nunca garantizó. Los equipos que migraron de YARN o Slurm a Kubernetes terminaron parcheando esta brecha con Volcano, Kueue o schedulers out-of-tree que agregan complejidad operativa y fricción en upgrades. Kubernetes v1.37, publicada el 8 de septiembre de 2026, ataca ese problema de raíz: las APIs Workload y PodGroup —el esqueleto del gang scheduling nativo— gradúan a Beta (v1beta1), se introduce CompositePodGroup para jerarquías multinivel, y la preemption consciente de workloads se integra al feature gate GenericWorkload como parte del núcleo. El mensaje es claro: el scheduling «all-or-nothing» deja de ser una extensión y pasa a ser capacidad de plataforma.

Qué ocurrió

El release v1.37 consolida la trayectoria del Workload-Aware Scheduling (WAS) en tres frentes. Primero, la promoción a Beta: las APIs Workload y PodGroup ahora exponeen v1beta1, un paso antes de General Availability. Los equipos que venían probando v1alpha2 deben migrar a v1alpha3 porque el alpha anterior fue eliminado por completo, con breaking changes en la estructura de disruptionMode. Segundo, la incorporación de CompositePodGroup, una API nueva que permite modelar grupos heterogéneos en una jerarquía árbol: un padre CompositePodGroup gobierna políticas de scheduling que aplican a hijos PodGroup u otros CompositePodGroups. Esto desbloquea soporte nativo para estructuras que hoy gestionan JobSet y LeaderWorkerSet (LWS) vía controladores externos. Tercero, se publican las controller integration APIs y la librería Go workloadbuilder, que estandarizan cómo los controladores out-of-tree consumen WAS sin reimplementar lógica de queueing o preemption.

El controlador Job nativo ya consume estas APIs expandidas, habilitando políticas de scheduling avanzadas, modos de disruption flexibles y scheduling topológico para batch estándar sin necesidad de schedulers adicionales.

Impacto para DevOps / Infraestructura / Cloud / Seguridad

Para equipos que corren pipelines de ML con 128+ GPUs por job, el cambio en la cola de scheduling es material: en v1.36, cada pod de un PodGroup se encolaba individualmente, generando interleaving con cargas de otros tenants y head-of-line blocking parcial. En v1.37, solo el objeto PodGroup de nivel superior entra a la cola. Esto elimina la ventana de race condition donde unos pods se colocan y otros quedan en Pending indefinidamente, y reduce la presión sobre kube-scheduler en clusters con cientos de grupos concurrentes.

La mutabilidad de minCount (antes inmutable) habilita workloads elásticos: un controller puede reducir el mínimo de un gang de 32 a 24 pods para degradar gracefully ante escasez de GPUs, sin reprogramar los 24 ya colocados. Para operadores de cloud multi-tenant, esto se traduce en mejor utilization de pools compartidos sin sacrificar la atomicidad del placement.

La unificación de WorkloadAwarePreemption dentro del feature gate GenericWorkload simplifica la gestión de feature flags: un solo toggle habilita gang scheduling y preemption consciente, reduciendo el riesgo de configuraciones inconsistentes entre environments.

Detalles técnicos

Promoción a Beta y breaking changes. Workload y PodGroup pasan a v1beta1. La versión v1alpha2 fue eliminada; reemplazala por v1alpha3. El campo disruptionMode se renombra para desacoplarlo del objeto PodGroup: el valor PodGroup pasa a llamarse all y Pod pasa a single, manteniendo consistencia con CompositePodGroup.

Preemption: optimización del algoritmo. En v1.36, al evaluar preemption, el scheduler simulaba la remoción de cada victim y re-ejecutaba el algoritmo de scheduling por cada reprieve. En v1.37, el algoritmo corre una sola vez, se asume la placement del preemptor sobre esa salida, y luego se verifica victim por victim si puede repatriarse. Esto reduce la complejidad computacional en clusters con decenas de candidatos a eviction.

Corrección de preemption por defecto. En v1.36, la preemption default de pods individuales ignoraba el campo disruptionMode del PodGroup padre, permitiendo evictar un pod aislado aunque el grupo tuviera disruptionMode: {all: {}}. v1.37 corrige esto: la preemption default respeta disruptionMode.

Nuevo campo preemptionPolicy en PodGroup. Con el feature gate PodGroupPreemptionPolicy habilitado, el PodGroup expone un campo preemptionPolicy propio que determina de forma autoritativa si el grupo puede ejecutar preemption, reemplazando la heurística de v1.36 que dependía de que ningún pod hijo tuviera preemptionPolicy: Never.

CompositePodGroup y templates jerárquicos. El API Workload se extiende con spec.compositePodGroupTemplates. Cada template define un padre y anida podGroupTemplates y/o compositePodGroupTemplates hijos. El scheduler evalúa el árbol completo como unidad de scheduling única.

apiVersion: scheduling.k8s.io/v1beta1
kind: Workload
metadata:
name: example-workload
spec:
compositePodGroupTemplates:
– name: workload-root
minGroupCount: 2
podGroupTemplates:
– name: example-workload-workers
minCount: 4
– name: example-workload-driver
minCount: 1

DRA ResourceClaims compartidos. Los PodGroups pueden compartir ResourceClaims del modelo Dynamic Resource Allocation, permitiendo que un gang de pods consuma un mismo recurso reservado (por ejemplo, un grupo de GPUs con topología NVLink) sin duplicar claims.

Qué deberían hacer los administradores y equipos técnicos

  • Auditar feature gates en kube-scheduler. Si ya tenías WorkloadAwarePreemption habilitado, migralo a GenericWorkload=true. Verificá que PodGroupPreemptionPolicy=true esté activo si necesitás control granular de preemption a nivel grupo. Reiniciá kube-scheduler tras el cambio.
  • Migrar manifests de v1alpha2 a v1alpha3. Buscá todos los YAML que referencien scheduling.k8s.io/v1alpha2 y actualizalos a v1alpha3. Revisá específicamente el campo disruptionMode: reemplazá el key PodGroup por all y Pod por single.
  • Evaluar CompositePodGroup para cargas jerárquicas. Si tu stack usa JobSet o LWS para jobs con roles (driver + workers + parameter servers), modelá la estructura como un Workload con compositePodGroupTemplates. Esto reduce la superficie de controladores externos y facilita upgrades del cluster sin revalidar integración con schedulers de terceros.
  • Ajustar políticas de preemption en multi-tenant. Con la corrección del disruptionMode en la preemption default, revisá las políticas de PriorityClass: un pod de alta prioridad ya no puede romper un gang configurado como disruptionMode: {all: {}} sin invocar la preemption a nivel grupo.
  • Integrar workloadbuilder en controladores propios. Si mantenés un controller out-of-tree, usá la librería Go workloadbuilder para generar objetos Workload/PodGroup/CompositePodGroup sin手写 la lógica de stamping. Esto reduce deuda técnica y garantiza compatibilidad con futuros cambios de API.
  • Planificar la migración a GA. v1beta1 implica que la API es estable pero puede recibir ajustes menores. Reservá un sprint de validación post-upgrade para confirmar que los controllers de Kueue o Volcano (si los usás) no colisionan con el scheduling nativo.
  • Conclusión

    Kubernetes v1.37 no introduce un feature experimental: consolida y jerarquiza capacidades que los equipos de ML y batch vienen construyendo por fuera del core. La promoción a Beta de Workload/PodGroup, la llegada de CompositePodGroup para topologías multinivel y la optimización del algoritmo de preemption posicionan al kube-scheduler como opción viable para cargas distribuidas complejas sin schedulers adicionales. El riesgo operativo es bajo para quien ya usa gang scheduling vía extensiones; el beneficio es la reducción de componentes, menos superficie de mantenimiento y un camino claro hacia GA en releases futuros.

    Fuentes

    • https://kubernetes.io/blog/2026/09/08/kubernetes-v1-37-advancing-workload-aware-scheduling/
    • https://www.redhat.com/en/blog
    • https://go.dev/blog/

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *