PerfectScalePerfectScale

PerfectScale

Kubernetes v1.35: novedades y mejoras

Kubernetes v1.35: 'Timbernetes' zarpa con 60 mejoras en escalado, seguridad, gestión de dispositivos, scheduling y más.

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Tania Duggal
By Tania Duggal
Jan 5, 202622 min read

Kubernetes v1.35, también conocida como "Timbernetes (The World Tree Release)", incorpora muchas funciones nuevas que hacen a Kubernetes más sólido y capaz de manejar workloads modernos a gran escala. Esta versión trae 60 funciones nuevas: 17 pasan a estables (GA), 19 a Beta y 22 a Alpha. El tema del "Árbol del Mundo" refleja cómo esta versión fortalece a Kubernetes en todos los niveles, desde sus cimientos hasta sus sistemas centrales y puntos de extensión. Esto le permite manejar una amplia gama de workloads, desde AI/ML hasta workloads con estado y en el edge.

Estas son algunas de las funciones que más nos entusiasman de Kubernetes v1.35: soporte para gang scheduling, actualizaciones in-place de recursos de Pods, batching oportunista en el scheduler y más. Con estas mejoras, Kubernetes optimiza mucho mejor el rendimiento, escala bien y administra los recursos con mayor eficiencia.

Repasemos las principales mejoras de Kubernetes v1.35:

Funciones estables de Kubernetes v1.35

1. Actualización in-place de recursos de Pods****

Grupo responsable: SIG Node | KEP: #1287

En Kubernetes v1.35, las actualizaciones in-place de los recursos de CPU y memoria de los Pods alcanzaron la disponibilidad general (GA).

Antes de esta función, había que recrear el Pod cada vez que se cambiaba .spec.resources.requests o .spec.resources.limits. Kubernetes trataba los cambios de recursos como campos inmutables, por lo que incluso un pequeño ajuste de CPU o memoria provocaba un reinicio completo. Esto era disruptivo para servicios con estado, trabajos batch de larga duración y aplicaciones sensibles a la latencia. Además, generaba tiempo de inactividad.

Con la v1.35, Kubernetes te permite cambiar las requests o limits de CPU y memoria de un Pod en ejecución sin tener que reiniciar el Pod ni sus contenedores. Ahora se pueden aplicar los cambios de recursos directamente al contenedor en ejecución cuando el runtime y la configuración del nodo lo permiten. El kubelet actualiza la configuración de cgroups in-place y el Pod sigue ejecutándose. Si un cambio de recursos no se puede aplicar de forma segura, Kubernetes recurre igualmente a recrear el Pod, preservando la retrocompatibilidad. Esto hace que el escalado vertical sea más fácil, seguro y efectivo.

2. Distribución de tráfico PreferSameNode

Grupo responsable: SIG Network | KEP:#3015

En Kubernetes v1.35, la distribución de tráfico PreferSameNode alcanza la disponibilidad general (GA).

Antes de este cambio, Kubernetes ofrecía la opción PreferClose dentro del campo trafficDistribution. Era útil, pero poco clara. PreferClose significaba implícitamente "preferir endpoints cercanos", lo que en la práctica se traducía en proximidad a nivel de zona, no de nodo. No había una forma clara de indicar que se quería una preferencia estricta por el nodo local, y la API no comunicaba con claridad la diferencia entre el comportamiento de enrutamiento a nivel de nodo y a nivel de zona.

Con la v1.35, Kubernetes te permite elegir hacia dónde va el tráfico de un Service. Puede dar una fuerte preferencia a los endpoints que están en el mismo nodo que el Pod cliente y recurrir a endpoints remotos solo cuando no haya locales disponibles. Se introduce una nueva opción, PreferSameNode, para priorizar los endpoints del mismo nodo. Al mismo tiempo, PreferClose pasa a llamarse PreferSameZone, lo que hace que la API sea autodescriptiva y más clara. PreferClose sigue siendo compatible por retrocompatibilidad, pero PreferSameZone es ahora la opción preferida y explícita para el enrutamiento zonal. En conjunto, estos cambios separan con claridad las preferencias de tráfico a nivel de nodo y a nivel de zona. Esto resulta útil para workloads que priorizan el rendimiento y buscan reducir la latencia y el tráfico entre nodos.

apiVersion: v1
kind: Service
metadata:
name: node-local-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
trafficDistribution: PreferSameNode

Con esta configuración, si un Pod cliente y un Pod backend correspondiente se ejecutan en el mismo nodo, Kubernetes enrutará el tráfico localmente. Solo cuando no existan endpoints locales, el tráfico se enviará a Pods en otros nodos.

3. Límite configurable de nodos NUMA para el Topology Manager

Grupo responsable: SIG Node | KEP:#4622

En Kubernetes v1.35, el límite configurable de nodos NUMA del Topology Manager alcanzó la disponibilidad general (GA).

NUMA (Non-Uniform Memory Access) es una arquitectura de hardware en la que un servidor se divide en varias regiones de memoria (nodos NUMA), cada una conectada directamente a un conjunto específico de CPU. El Topology Manager es un componente del kubelet que alinea las asignaciones de CPU, memoria y dispositivos para que los workloads se ejecuten en hardware físicamente cercano.

Antes de esta función, Kubernetes imponía un límite fijo de 8 nodos NUMA siempre que el Topology Manager estaba habilitado. Esta medida de seguridad existía para evitar la explosión de estados durante los cálculos de afinidad NUMA. Como resultado, el kubelet deshabilitaba por completo el Topology Manager en nodos con más de 8 nodos NUMA. Esta limitación implicaba que Kubernetes no podía aprovechar servidores grandes de múltiples sockets, donde la localidad precisa de CPU, memoria y dispositivos es crítica para el rendimiento.

Con la v1.35, la opción de política max-allowable-numa-nodes ya es estable. Kubernetes permite a los administradores de clústeres ejecutar el Topology Manager en máquinas con más de 8 nodos NUMA. Esto elimina el techo artificial y permite que Kubernetes coordine la ubicación de CPU, memoria y dispositivos incluso en máquinas muy grandes. Si bien todavía existen desafíos de rendimiento en sistemas NUMA extremadamente grandes, Kubernetes ahora da a los operadores el control para habilitarlo según su hardware y sus workloads.

Así, esta función permite que Kubernetes aproveche mejor los servidores modernos de gama alta, comunes en workloads de HPC, AI/ML, telecomunicaciones y baja latencia.

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
topologyManagerPolicy: restricted
topologyManagerScope: pod
topologyManagerPolicyOptions:
max-allowable-numa-nodes: "true"

4. Nueva opción de política del CPUManager para restringir reservedSystemCPUs

Grupo responsable: SIG Node | KEP: #4540

Antes de esta función, Kubernetes permitía a los administradores reservar CPU específicas para el sistema mediante reservedSystemCPUs. Sin embargo, esta reserva solo se aplicaba a los Pods Guaranteed con solicitudes de CPU enteras. Los Pods Burstable y BestEffort, así como los Guaranteed con solicitudes fraccionarias de CPU, aún podían consumir tiempo de CPU de esos núcleos reservados. En clústeres reales, esto generaba problemas de "vecinos ruidosos", donde los workloads de aplicaciones interferían con los procesos del sistema, causando inestabilidad en los nodos, demoras en el scheduling o degradación del rendimiento bajo carga.

Con Kubernetes v1.35, la opción strict-cpu-reservation de la política estática del CPUManager alcanza la disponibilidad general (GA). Cuando está habilitada, Kubernetes impide estrictamente que todos los Pods, sin importar su clase de QoS, se ejecuten en las CPU listadas en reservedSystemCPUs. Esto hace que el aislamiento de CPU sea predecible y confiable, garantizando que los daemons del sistema siempre tengan capacidad de CPU dedicada. El resultado son nodos más estables y un mejor rendimiento para los workloads sensibles a la latencia y de alto throughput que conviven con componentes críticos del sistema.

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
cpuManagerPolicy: static
reservedSystemCPUs: "0-1"
cpuManagerPolicyOptions:
strict-cpu-reservation: "true"

Con esta configuración, las CPU 0-1 quedan reservadas exclusivamente para el sistema operativo y los daemons de sistema de Kubernetes. Ningún Pod de aplicación, ya sea BestEffort, Burstable o Guaranteed, puede ejecutarse en estas CPU.

5. Límite del kubelet para pulls de imágenes en paralelo

Grupo responsable: SIG Node | KEP: #3673

El límite de pulls de imágenes en paralelo del kubelet controla cuántas imágenes de contenedor puede descargar un nodo al mismo tiempo. El pull de imágenes es una operación que consume mucha red y disco.

Antes de esta función, el comportamiento del kubelet era prácticamente binario. Cuando serializeImagePulls estaba en true, las imágenes se descargaban de a una, lo que evitaba la contención de recursos pero ralentizaba considerablemente el arranque de los pods durante escalados o reinicios de nodos. Cuando serializeImagePulls estaba en false, no había límite superior para los pulls de imágenes en paralelo. En nodos con mucha actividad, esto podía inundar la red, saturar los discos y retrasar otras operaciones críticas del nodo.

Con Kubernetes v1.35, la configuración maxParallelImagePulls alcanza la disponibilidad general (GA). Esto permite a los administradores definir un límite superior explícito para los pulls de imágenes concurrentes. Kubernetes ahora puede descargar varias imágenes en paralelo, pero solo hasta un límite seguro definido por el operador. Los pulls adicionales se encolan hasta que finaliza uno en curso, lo que ofrece concurrencia controlada en lugar de un comportamiento de todo o nada.

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
serializeImagePulls: false
maxParallelImagePulls: 3

Con esta configuración, el kubelet permite descargar hasta tres imágenes simultáneamente en un nodo.

6. Recolección de basura de imágenes en el kubelet tras una antigüedad máxima

Grupo responsable: SIG Node | KEP:#4210

Antes de esta función, la recolección de basura de imágenes del kubelet se guiaba principalmente por umbrales de uso de disco. Las imágenes se eliminaban solo cuando el uso de disco superaba HighThresholdPercent, y la limpieza continuaba hasta que el uso bajaba de LowThresholdPercent. Aunque era eficaz para prevenir el agotamiento del disco, esto significaba que las imágenes poco usadas u obsoletas podían permanecer en el disco indefinidamente mientras el nodo no estuviera bajo presión de disco. Con el tiempo, esto generaba cachés de imágenes infladas y un uso ineficiente del disco.

Con Kubernetes v1.35, la configuración imageMaximumGCAge ya es estable, lo que permite al kubelet recolectar imágenes que no se han usado durante un período determinado, independientemente del uso de disco. Los administradores pueden definir una antigüedad máxima para las imágenes sin uso, expresada como duración. Una vez que una imagen supera esa antigüedad sin usarse, pasa a ser candidata a eliminación. Esto complementa la GC basada en disco existente y hace que la limpieza de imágenes sea proactiva en lugar de reactiva.

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
imageMaximumGCAge: 24h
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 70

Con esta configuración, el kubelet puede eliminar cualquier imagen de contenedor que no se haya usado durante 24 horas, incluso si el uso de disco está por debajo del umbral alto.

7. Mecanismo managedBy en la API de Job

Grupo responsable: SIG Apps | KEP:#4368

Antes de esta función, cada objeto Job era siempre reconciliado por el controlador de Job integrado. Incluso si un sistema externo (como un controlador personalizado o un scheduler multiclúster) quería gestionar la ejecución o el estado, Kubernetes seguía creando Pods, actualizando las condiciones del Job, reintentando fallos y aplicando la semántica de finalización. Esto complicaba casos de uso avanzados, como replicar Jobs entre clústeres, y obligaba a recurrir a anotaciones, workarounds en los controladores o lógica de supresión para evitar conflictos.

Con Kubernetes v1.35, el campo managedBy alcanza la disponibilidad general (GA). Cuando está definido, Kubernetes trata el Job como gestionado externamente y no reconcilia sus Pods ni su estado. Esto habilita sistemas como MultiKueue, donde un Job se crea en un clúster de gestión, se ejecuta en un clúster worker y el estado se sincroniza de vuelta sin interferencia del controlador de Job nativo. La función es limitada a propósito: permite delegar la gestión del Job, pero no cambia la semántica del Job ni el comportamiento de CronJob, ni pasa configuración al controlador externo.

apiVersion: batch/v1
kind: Job
metadata:
name: delegated-job
spec:
managedBy: kueue.x-k8s.io/multikueue
........

8. Pod Generation (seguimiento confiable de actualizaciones de Pods)

Grupo responsable: SIG Node | KEP: #5067

Antes de esta función, los Pods no tenían un campo metadata.generation como los objetos de nivel superior, tales como Deployments o StatefulSets. Aunque los controladores podían actualizar la spec de un Pod, no existía una forma integrada y monotónica de saber si el kubelet ya había procesado un cambio determinado. Esto dificultaba detectar de forma confiable si una actualización de Pod seguía pendiente, se había aplicado parcialmente o ya estaba reflejada por completo en el estado, especialmente con actualizaciones in-place y cambios rápidos y sucesivos.

Con Kubernetes v1.35, el seguimiento de la generación del Pod alcanza la disponibilidad general (GA). Cada Pod comienza con metadata.generation: 1, y cada actualización de un campo mutable en la spec del Pod incrementa este valor. El kubelet registra la generación sobre la que ya actuó en status.observedGeneration. Así queda explícito si el estado actual del Pod refleja la última spec deseada o una versión anterior. Los controladores externos pueden comparar con seguridad estos dos campos para determinar si la reconciliación está completa, sin depender de tiempos ni suposiciones.

Funciones Beta de Kubernetes v1.35

9. Tolerancia configurable para HorizontalPodAutoscalers

Grupo responsable: SIG Autoscaling | KEP: #4951

El Horizontal Pod Autoscaler (HPA) ajusta automáticamente el número de réplicas de Pods de un workload según métricas observadas, como el uso de CPU o memoria.

Antes de esta función, el HPA usaba una tolerancia fija del 10% a nivel de clúster al decidir si escalar. Este valor no era configurable por workload. Como resultado, las aplicaciones muy sensibles podían no escalar cuando necesitaban reaccionar a pequeños aumentos de carga, mientras que otros workloads podían sufrir escalados innecesarios u oscilaciones. Ajustar este comportamiento requería cambiar un flag global del controlador, lo que afectaba a todos los HPA del clúster.

Con Kubernetes v1.35, la tolerancia configurable pasa a Beta y está habilitada por defecto. Ahora puedes definir valores de tolerancia por HPA y por dirección de escalado usando el campo behavior. Esto brinda un control granular sobre la sensibilidad del autoescalado sin afectar a otros workloads. Los operadores pueden ajustar los servicios críticos para que escalen de forma agresiva, mientras mantienen estables los workloads menos sensibles.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
behavior:
scaleUp:
tolerance: 0.05

Con esta configuración, el HPA solo aumenta las réplicas cuando la utilización de CPU supera el 65% (5% por encima del objetivo).

10. Límites mutables de attach de volúmenes

Grupo responsable: SIG Storage | KEP:#4876

Los límites de attach de volúmenes definen cuántos volúmenes de almacenamiento pueden adjuntarse a un nodo en un momento dado. Kubernetes usa esta información para decidir dónde programar los Pods que utilizan volúmenes persistentes. Los drivers CSI reportan estos límites a través del objeto CSINode.

Antes de esta función, la capacidad de attach de volúmenes reportada en CSINode.spec.drivers[*].allocatable.count era estática. Una vez que un driver CSI registraba su límite de attach al arrancar, Kubernetes asumía que ese valor era siempre correcto. Si luego se consumían slots de volúmenes —por operaciones externas, reinicios de nodos o fallos transitorios—, el scheduler aún podía ubicar Pods en nodos que ya no tenían capacidad. Esto provocaba Pods atascados en ContainerCreating porque el volumen no podía adjuntarse realmente.

Con Kubernetes v1.35, el límite de attach de volúmenes allocatable ahora es mutable y la función está en Beta, habilitada por defecto. Los drivers CSI pueden actualizar dinámicamente la capacidad de attach disponible de un nodo en tiempo de ejecución. Kubernetes también introduce un intervalo de actualización configurable mediante el objeto CSIDriver, lo que permite a los drivers controlar con qué frecuencia se recalculan los conteos allocatable. Además, Kubernetes actualiza automáticamente el conteo allocatable cuando detecta fallos de attach causados por capacidad insuficiente. Esto hace que las decisiones de scheduling sean más precisas y reduce significativamente los arranques de Pods fallidos o atascados.

apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: example.csi.storage
spec:
attachRequired: true
nodeAllocatableUpdatePeriodSeconds: 30 # Note: minimum is 10 seconds

Esto configura llamadas periódicas del kubelet al endpoint NodeGetInfo del driver CSI cada 30 segundos para actualizar CSINode.spec.drivers[].allocatable.count

11. Batching oportunista

Grupo responsable: SIG Scheduling | KEP: #5598

El batching oportunista es una optimización del scheduler que mejora el rendimiento cuando Kubernetes programa muchos Pods con requisitos de scheduling idénticos o equivalentes.

Antes de esta función, el kube-scheduler procesaba los Pods uno por uno, con una complejidad de scheduling proporcional al número de Pods multiplicado por el número de nodos. Incluso cuando varios Pods eran idénticos desde el punto de vista del scheduling —mismas solicitudes de recursos, afinidades y restricciones—, el scheduler repetía los mismos cálculos de filtrado y puntuación para cada Pod. Esto generaba trabajo redundante y un scheduling lento, especialmente en trabajos batch, workloads de ML y creación de réplicas a gran escala.

Con Kubernetes v1.35, se introduce el batching oportunista como función Beta, habilitada por defecto. El scheduler ahora calcula una firma de scheduling del pod, que captura todos los aspectos de un Pod relevantes para el scheduling, incluidas las specs del pod, los atributos de los nodos y el estado del clúster. Cuando llegan a la cola de scheduling Pods consecutivos con la misma firma, el scheduler los agrupa en lotes. Guarda en caché los resultados del scheduling del primer Pod y los reutiliza para los siguientes Pods con la misma firma, evitando cálculos repetidos. La caché es de corta duración y se actualiza automáticamente para garantizar la corrección a medida que cambia el estado del clúster.

Esta optimización funciona de forma transparente: no requiere configuración por parte del usuario y beneficia principalmente a los workloads con muchos Pods idénticos, como Jobs, workers paralelos de ML y despliegues a gran escala. Al reducir el trabajo redundante de scheduling, Kubernetes puede ubicar los Pods más rápido y escalar los workloads con mayor eficiencia bajo cargas altas.

12. maxUnavailable para StatefulSets

Grupo responsable: SIG Apps | KEP: #961

Un StatefulSet gestiona un conjunto de Pods que requieren identidades estables, arranque y terminación ordenados, y almacenamiento persistente.

Antes de esta función, los StatefulSets con la estrategia RollingUpdate actualizaban los Pods estrictamente de a uno, comenzando por el ordinal más alto. No había forma de controlar cuántos Pods podían estar no disponibles durante una actualización. Incluso si una aplicación con estado toleraba tener varios Pods caídos temporalmente, Kubernetes seguía imponiendo actualizaciones en serie, lo que alargaba los tiempos de despliegue en StatefulSets grandes.

Con Kubernetes v1.35, el campo maxUnavailable para las actualizaciones continuas de StatefulSets pasa a Beta y está habilitado por defecto. Esto permite a los operadores especificar cuántos Pods pueden estar no disponibles durante una actualización, ya sea como número absoluto o como porcentaje de las réplicas. Combinado con podManagementPolicy: Parallel, Kubernetes puede actualizar varios Pods a la vez respetando las restricciones de disponibilidad. Si no se define, el valor por defecto sigue siendo 1, preservando el comportamiento anterior.

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
replicas: 10
podManagementPolicy: Parallel
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 20%
........

13. Estado del Deployment: conteo de réplicas en terminación

Grupo responsable: SIG Apps | KEP: #3973

Un Deployment gestiona las actualizaciones continuas y el escalado de los Pods, y su estado es utilizado por operadores y automatizaciones para entender el progreso de los despliegues.

Antes de esta función, el estado del Deployment solo reportaba campos como replicas, updatedReplicas, readyReplicas y availableReplicas. Los Pods en terminación no eran visibles de forma explícita en el estado del Deployment. Esto dificultaba saber si un Deployment estaba realmente estable o si aún tenía Pods finalizando en segundo plano. Los operadores y controladores debían listar los Pods manualmente y filtrar por deletionTimestamp, algo propenso a errores e ineficiente.

Con Kubernetes v1.35, el campo status.terminatingReplicas se promueve a Beta y está habilitado por defecto (con el feature gate DeploymentReplicaSetTerminatingReplicas habilitado en el API server y el controller manager). Este campo reporta el número de Pods que están en terminación pero aún no se han eliminado por completo. Mejora la observabilidad durante los despliegues y los eventos de reducción de escala, y sienta las bases para futuras mejoras en el comportamiento de los Deployments, como políticas de reemplazo de Pods más inteligentes que consideren el progreso del apagado.

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
status:
replicas: 5
updatedReplicas: 5
readyReplicas: 4
availableReplicas: 4
terminatingReplicas: 1
........

14. Exposición de las etiquetas de topología del nodo mediante la Downward API

Grupo responsable: SIG Node | KEP:#4742

Las etiquetas de topología del nodo describen dónde se ejecuta un Pod dentro de la infraestructura, como la región o la zona de disponibilidad del nodo.

Antes de esta función, los Pods no podían acceder directamente a la información de topología del nodo. Los workloads que necesitaban datos de zona o región debían consultar el API server de Kubernetes, depender de sidecars o recibir permisos RBAC adicionales. Esto aumentaba la complejidad operativa e introducía riesgos de seguridad al ampliar los permisos de los Pods de aplicación más allá de lo que realmente necesitaban.

Con Kubernetes v1.35, las etiquetas de topología del nodo ahora se inyectan en los Pods y se exponen a través de la Downward API, con la función en Beta y habilitada por defecto. El kubelet propaga etiquetas estándar como topology.kubernetes.io/zone y topology.kubernetes.io/region desde el nodo hacia el Pod, dejándolas disponibles como variables de entorno o archivos proyectados. Esto permite que los workloads sean conscientes de la topología sin acceso a la API, simplificando la configuración y respetando el principio de mínimo privilegio.

apiVersion: v1
kind: Pod
metadata:
name: topology-aware-pod
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "env"]
env:
- name: ZONE
valueFrom:
fieldRef:
fieldPath: metadata.labels['topology.kubernetes.io/zone']
- name: REGION
valueFrom:
fieldRef:
fieldPath: metadata.labels['topology.kubernetes.io/region']

Con esta configuración, el Pod recibe automáticamente la zona y la región del nodo en el que se está ejecutando.

Funciones Alpha de Kubernetes v1.35

15. Soporte de gang scheduling en Kubernetes

Grupo responsable: SIG Scheduling | KEP: #4671

Antes de esta función, Kubernetes programaba los Pods de forma individual. Para workloads fuertemente acoplados, esto resultaba en un scheduling parcial: algunos Pods comenzaban a ejecutarse mientras otros quedaban pendientes por falta de recursos. Estos trabajos parcialmente programados podían generar deadlocks, desperdiciar recursos del clúster y bloquear otros workloads, lo que obligaba a los usuarios a recurrir a schedulers externos o controladores personalizados para aplicar la semántica de gang.

Con Kubernetes v1.35, se introduce el gang scheduling nativo como función Alpha, usando la nueva Workload API y las políticas de grupos de pods. Los usuarios definen un Workload que agrupa Pods y especifica un requisito de minCount. El scheduler retiene los Pods hasta que el grupo está completo y luego intenta ubicarlos juntos. Si no puede programar al menos el número requerido de Pods dentro de un tiempo límite, no se vincula ninguno, y los Pods esperan hasta que haya recursos suficientes. Así, la semántica de gang pasa a tener soporte nativo directamente en el scheduler de Kubernetes.

Ejemplo:

Workload que define un gang de Pods

apiVersion: scheduling.k8s.io/v1alpha1
kind: Workload
metadata:
name: ml-training
spec:
podGroups:
- name: workers
policy:
gang:
minCount: 4

Pod vinculado al Workload:

apiVersion: v1
kind: Pod
metadata:
name: worker-0
spec:
workloadRef:
name: ml-training
podGroup: workers
containers:
- name: trainer
image: <your-image>

Con esta configuración, Kubernetes programa los Pods solo cuando al menos cuatro workers pueden ejecutarse juntos. Si el clúster no puede satisfacer ese requisito, no se inicia ninguno de los Pods.

16. Operadores de toleration extendidos para colocación basada en umbrales

Grupo responsable: SIG Scheduling | KEP: #5471

En Kubernetes, los taints y las tolerations se usan para controlar dónde pueden ejecutarse los Pods. Los nodos usan taints para decir "no coloques Pods aquí", y los Pods usan tolerations para decir "tengo permitido ejecutarme en este nodo".

Antes de esta función, las tolerations solo admitían operadores básicos como Exists y Equal. Esto significaba que los Pods podían tolerar un taint o no, pero no podían expresar grados de tolerancia. Por ejemplo, un workload no podía decir "ejecútate solo en nodos con SLA ≥ 99.9" o "evita nodos con confiabilidad por debajo de cierto umbral". Como resultado, los clústeres que buscaban una colocación consciente del SLA debían recurrir a schedulers personalizados, múltiples pools de nodos o lógica de admisión compleja.

Con Kubernetes v1.35, las tolerations incorporan operadores de comparación numérica (como semánticas de mayor-que o menor-que) y avanzan como parte del scheduling extendido. Los nodos pueden exponer taints orientados a SLA (por ejemplo, puntuaciones de confiabilidad o calidad del dominio de fallos), y los Pods pueden especificar tolerations que solo coinciden si el valor del taint del nodo cumple una condición numérica. Esto permite que los workloads críticos apunten a nodos de alto SLA, mientras que los workloads best-effort pueden ejecutarse intencionalmente en infraestructura de menor costo y menor SLA, lo que mejora la utilización sin sacrificar la confiabilidad.

Taint de nodo que expresa un nivel de SLA:

kubectl taint nodes node-a
servicelevel.org.example/agreed-service-level=800:NoSchedule

Pod que tolera solo nodos con SLA suficiente:

apiVersion: v1
kind: Pod
metadata:
name: sla-tolerant-pod
spec:
tolerations:
- key: servicelevel.org.example/agreed-service-level
operator: LessThan
value: "900"
effect: NoSchedule
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo running on lower-SLA node"]

Con esta configuración, el Pod solo se programará en nodos cuyo valor de taint de SLA sea inferior a 900.

17. Recursos de contenedor mutables cuando un Job está suspendido

Grupo responsable: SIG Apps | KEP: #5440

Un Job de Kubernetes ejecuta una tarea hasta que finaliza con éxito y se asegura de que se complete.

Antes de esta función, la plantilla de Pod dentro de un Job era prácticamente inmutable. Si un Job fallaba por falta de CPU o memoria (por ejemplo, OOM kills repetidos), los usuarios no tenían forma de ajustar los valores de recursos en el Job existente. La única opción era eliminar el Job y crear uno nuevo con los recursos actualizados, lo que implicaba perder el historial del Job, su estado y cualquier herramienta que rastreara el progreso o los reintentos.

Con Kubernetes v1.35, en los Jobs en estado suspendido se pueden modificar las requests y limits de recursos de sus contenedores, cuando el feature gate MutableJobPodResourcesForSuspendedJobs está habilitado. Los usuarios pueden suspender un Job que falla, actualizar la plantilla de Pod con valores de recursos adecuados y luego reanudar el Job. Kubernetes continúa la ejecución con la configuración actualizada preservando la identidad y el estado del ciclo de vida del Job, lo que hace mucho más fluida la recuperación ante recursos mal configurados.

apiVersion: batch/v1
kind: Job
metadata:
name: data-processor
spec:
suspend: true
template:
spec:
restartPolicy: OnFailure
containers:
- name: worker
image: busybox
command: ["sh", "-c", "echo processing && sleep 30"]
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"

Después de actualizar los recursos, el Job se puede reanudar estableciendo spec.suspend en false. El Job continúa con los nuevos valores de CPU y memoria, sin necesidad de eliminarlo ni recrearlo.

18. Funciones declaradas por el nodo antes del scheduling

Grupo responsable: SIG Node | KEP: #5328

Antes de esta función, Kubernetes asumía que los nodos eran ampliamente compatibles con el plano de control, dentro del desfase de versiones soportado. Cuando se habilitaban nuevas funciones a nivel del plano de control, el scheduler aún podía ubicar Pods que usaban esas funciones en nodos más antiguos que todavía no las soportaban. Esto provocaba fallos en tiempo de ejecución, comportamientos sutilmente incorrectos o Pods atascados después del scheduling, aunque la decisión de ubicación en sí pareciera válida.

Con Kubernetes v1.35, una función Alpha introduce un mecanismo formal para que los nodos declaren las funciones que soportan, mediante un nuevo campo status.declaredFeatures en el objeto Node. Cuando está habilitado, los nodos publican el conjunto de funciones de Kubernetes que comprenden. El scheduler, los controladores de admisión y los componentes externos pueden entonces usar esta información para validar los Pods y restringir el scheduling a nodos compatibles, evitando problemas de desfase de funciones antes de que los Pods se vinculen.

Dynamic Resource Allocation (DRA): trabajo en curso

Grupo responsable: SIG Node / SIG Scheduling

Dynamic Resource Allocation (DRA) es el framework nativo de Kubernetes para gestionar recursos de hardware especializados (como GPU, aceleradores y dispositivos) de forma integrada con el scheduler y segura para el ciclo de vida. Reemplaza muchas de las limitaciones de los plugins de dispositivos tradicionales al integrar la asignación de dispositivos directamente en el proceso de scheduling y binding de Kubernetes.

Antes de Kubernetes v1.35, la funcionalidad central de DRA ya había alcanzado la estabilidad en la v1.34.

Con Kubernetes v1.35, DRA está siempre habilitado y varias funciones alpha importantes maduraron significativamente. El foco de la v1.35 no son las nuevas API, sino hacer que los conceptos existentes de DRA sean más completos, confiables y observables.

Veamos:

Solicitudes de recursos extendidos vía DRA

Las solicitudes de recursos extendidos permiten a los Pods solicitar dispositivos con una semántica más rica, incluyendo la reutilización entre init containers y una mejor puntuación durante el scheduling.****

****Antes de Kubernetes v1.35, DRA iba a la zaga de los plugins de dispositivos en algunos escenarios. Por ejemplo, los dispositivos no podían reutilizarse de forma limpia entre init containers y contenedores de aplicación, y las decisiones de scheduling carecían de señales de puntuación adecuadas para ciertos tipos de dispositivos.

Ahora, con Kubernetes v1.35, estas brechas se han resuelto. La reutilización de dispositivos entre init containers funciona correctamente, y la lógica de scheduling evalúa mejor la ubicación de los dispositivos. Esto hace que DRA sea viable para ciclos de vida de Pods más complejos y workloads de múltiples etapas.

Taints y tolerations de dispositivos

Los taints de dispositivos permiten que dispositivos individuales —no nodos completos— expresen condiciones que afectan el scheduling y el desalojo, de forma similar a los taints de nodos.

Antes de Kubernetes v1.35, los taints de dispositivos eran limitados y no ofrecían formas seguras de evaluar su impacto antes de aplicar los desalojos. Cualquier taint con NoExecute desalojaba de inmediato los Pods que usaban el dispositivo.

Ahora, con Kubernetes v1.35, se introduce un nuevo efecto: None. Esto permite a los operadores hacer un dry run. Puedes inspeccionar cuántos pods se verían afectados y cambiar a NoExecute solo cuando estés listo.

Además, DeviceTaintRule ahora reporta información de estado, lo que hace que los desalojos sean observables y más seguros de operar.

Dispositivos particionables

Los dispositivos particionables son dispositivos físicos que pueden dividirse en unidades lógicas más pequeñas (por ejemplo, slices de GPU).

Antes**,** todas las particiones de un dispositivo debían definirse dentro de un único ResourceSlice, lo que limitaba la flexibilidad para modelar y publicar los dispositivos.

Ahora, con Kubernetes v1.35, los dispositivos que pertenecen al mismo dispositivo particionable pueden definirse en múltiples ResourceSlices. Esto mejora la flexibilidad del modelado y se alinea mejor con la forma en que el hardware moderno expone los recursos particionados.

Capacidad consumible

La capacidad consumible rastrea los recursos de dispositivos que se agotan gradualmente en lugar de asignarse de forma exclusiva (por ejemplo, ancho de banda de memoria o aceleradores de uso limitado).

Las primeras implementaciones tenían problemas de corrección y una cobertura de pruebas incompleta, lo que limitaba la confianza en el comportamiento de scheduling y contabilización.

Ahora (v1.35), se corrigieron múltiples errores y se amplió la cobertura de pruebas. El comportamiento de consumo y liberación de capacidad es ahora más confiable, lo que hace que esta función sea más segura para experimentar.

Condiciones de binding de dispositivos

Las condiciones de binding definen cuándo y cómo la asignación de un dispositivo se vuelve definitiva durante el scheduling y la admisión de un Pod.

Antes, existían casos límite en los que el comportamiento del binding podía ser ambiguo o manejarse incorrectamente en escenarios de fallo.

Ahora (v1.35), varias correcciones y validaciones mejoran la corrección. Las decisiones de binding son más predecibles y resilientes, especialmente durante reintentos y fallos parciales.

Semántica de versiones de recursos comparables

Las versiones de recursos permiten a los clientes y controladores rastrear los cambios en los objetos de Kubernetes a lo largo del tiempo.

Antes de Kubernetes v1.35, las versiones de recursos solo podían compararse por igualdad, no por orden. Los clientes no podían determinar de forma confiable si una versión era más reciente que otra sin ayuda del lado del servidor.

Ahora, con Kubernetes v1.35, todas las versiones de recursos in-tree siguen un formato numérico estricto y comparable. Los clientes pueden comparar versiones por sí mismos con seguridad. Esto permite un mejor rendimiento de los informers y controladores más confiables. Este cambio sienta las bases y permite múltiples mejoras de nivel superior en todo Kubernetes.

Deprecaciones / Eliminaciones

Eliminación del soporte de cgroup v1

Kubernetes usa cgroups para gestionar la CPU y la memoria de los contenedores. Las versiones anteriores soportaban tanto cgroup v1 como v2, principalmente por retrocompatibilidad.

En la v1.35, el soporte de cgroup v1 se elimina por completo y cgroup v2 pasa a ser obligatorio.

Deprecación del modo IPVS en kube-proxy

kube-proxy enruta el tráfico de los Services hacia los Pods usando distintos modos de backend. El modo IPVS queda deprecado en la v1.35 debido a su complejidad operativa y su solapamiento con los dataplanes modernos.

Kubernetes ahora recomienda el modo iptables o los CNI basados en eBPF para un networking escalable.

Esto reduce la carga de mantenimiento y mejora la confiabilidad del networking a largo plazo.

Último llamado para containerd v1.x

Containerd es el runtime de contenedores predeterminado que usa Kubernetes.
Las versiones antiguas de containerd v1.x están cerca del fin de su soporte.
Kubernetes v1.35 marca el último llamado para actualizar a versiones más recientes de containerd.

Kubernetes 1.35 trae un total de 60 Kubernetes Enhancement Proposals (KEPs). Estas mejoras abarcan funcionalidades de Kubernetes, flexibilidad, gestión de recursos, observabilidad y más.

Más allá de los cambios principales que repasamos, el equipo de k8s agregó otras funciones. Te recomendamos echar un vistazo a las notas de la versión de Kubernetes v1.35 y revisar este enlace para más detalles.