Durante años, la observabilidad de Kubernetes vivió pegada al plano de control: el API server, el scheduler, el etcd. El nodo — donde realmente arrancan tus contenedores — era una caja bastante opaca. La versión 1.34 "Of Wind & Will" cambió eso al graduar a estable el tracing distribuido del kubelet, y de paso llevó a GA VolumeAttributesClass, la API para modificar volúmenes en caliente. No son features de vidriera: son dos piezas que, si operás clusters en serio, cambian cómo depurás latencia y cómo escalás almacenamiento sin migrar datos.

Kubernetes 1.34 es la versión del proyecto lanzada el 27 de agosto de 2025 bajo el nombre "Of Wind & Will". Trajo 58 mejoras: 23 estables, 22 en beta y 13 en alpha, según el anuncio oficial del release. Sus dos cambios de mayor impacto operativo son el tracing distribuido del kubelet con OpenTelemetry (KEP-2831), que ahora es producción-grade, y VolumeAttributesClass en GA, que permite modificar parámetros de volúmenes en línea.

¿Por qué la observabilidad de Kubernetes se corrió hacia el nodo?

Kubernetes 1.34: tracing en el kubelet y VolumeAttributesClass GA

Porque la mayoría de los problemas raros — pods que tardan en arrancar, montajes lentos, timeouts contra el runtime — ocurren en el nodo, no en el plano de control. Hasta la 1.34 el kubelet exponía métricas y logs, pero no trazas correlacionadas: no podías seguir una operación end-to-end desde que el API server la ordena hasta que containerd crea el contenedor. Con el tracing estable del kubelet, esa cadena por fin se ve completa.

Esto sigue la misma línea que ya cubrimos en el blog en la nota sobre observar Kubernetes con OpenTelemetry Collector y métricas de pods: las señales de nodo dejan de ser un punto ciego y se integran al mismo backend de trazas que el resto de tu stack.

¿Qué es el tracing distribuido del kubelet (KEP-2831)?

Es la capacidad del kubelet de emitir trazas OpenTelemetry de sus operaciones clave y propagar el contexto de traza hacia el runtime de contenedores. En Kubernetes 1.34 esta funcionalidad (KEP-2831) graduó a estable, instrumentando las llamadas gRPC del kubelet contra la Container Runtime Interface (CRI). Según la cobertura de InfoQ, el objetivo es que los operadores puedan "descubrir latencia y errores más rápido".

La pieza clave es la propagación de contexto: el kubelet pasa el trace ID en cada request gRPC, de modo que runtimes instrumentados como containerd y CRI-O asocian sus propios spans a la misma traza. Resultado: una sola traza que arranca en el API server, baja al kubelet y termina en el runtime creando el contenedor.

  • Instrumenta las operaciones internas del kubelet. Sincronización de pods, recolección de basura y cada método gRPC quedan trazados con timing preciso y relaciones padre-hijo entre spans.
  • Correlaciona nodo y runtime. Al propagar el contexto por CRI, los spans de containerd/CRI-O se enganchan a la traza del kubelet en lugar de quedar sueltos.
  • Comparte backend con el API server. El plano de control también tiene tracing OpenTelemetry, así que exportás todo al mismo colector y ves el flujo completo en una herramienta.
  • Es producción-grade, no experimental. Al ser estable, el feature gate viene activado por defecto y no depende de flags que puedan desaparecer.

¿Cómo activás el tracing del kubelet?

Se configura en el KubeletConfiguration de cada nodo, con una sección tracing que define el endpoint del colector OpenTelemetry (por defecto localhost:4317) y la tasa de muestreo. El samplingRatePerMillion indica cuántos spans se envían por cada millón: si lo ponés en 1000000 se exporta absolutamente todo, algo que en producción rara vez querés por el volumen.

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
tracing:
  endpoint: otel-collector.observability.svc:4317
  samplingRatePerMillion: 100000   # 10% de las trazas

Con esto, el kubelet exporta por gRPC/OTLP a tu colector. Del otro lado necesitás un OpenTelemetry Collector recibiendo en el puerto 4317 y reenviando al backend de trazas que uses. Empezá con un muestreo bajo (5-10%) y subilo solo cuando estés cazando un problema puntual: las trazas de nodo pueden ser muchísimas.

¿Qué resuelve VolumeAttributesClass ahora que es GA?

VolumeAttributesClass (VAC) es un recurso cluster-scoped que define parámetros mutables de un volumen — IOPS, throughput, tipo de disco — y permite cambiarlos en línea, sin recrear el PVC ni mover datos. La documentación oficial lo describe como "un perfil para tu almacenamiento" que expone distintos niveles de calidad de servicio. En 1.34 pasó a GA, o sea que es API estable y usable en clusters de producción.

El flujo tiene dos objetos. El administrador define la clase con un driverName (el de tu driver CSI) y sus parámetros; el usuario referencia esa clase desde el PVC con el campo volumeAttributesClassName:

apiVersion: storage.k8s.io/v1
kind: VolumeAttributesClass
metadata:
  name: alto-rendimiento
driverName: csi.storage.example.com
parameters:
  iops: "5000"
  throughput: "250"
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: datos-postgres
spec:
  accessModes: ["ReadWriteOnce"]
  volumeAttributesClassName: alto-rendimiento
  resources:
    requests:
      storage: 100Gi

Cuando cambiás el volumeAttributesClassName del PVC, el driver CSI habla con el sistema de almacenamiento y aplica la modificación sobre el volumen vivo. La graduación a GA sumó dos cosas importantes:

  • Cancelación explícita ante errores. Si una modificación falla, ahora hay soporte para cancelarla, evitando que el volumen quede en un estado inconsistente a medio camino.
  • Integración con ResourceQuota. Podés limitar por cuota qué PVCs usan una clase determinada mediante scopeSelector, útil para que nadie se cuelgue una clase premium sin control.
  • Requiere soporte del driver CSI. No es magia del core de Kubernetes: solo funciona si tu driver de almacenamiento implementa la modificación de VolumeAttributesClass. Verificá esa capacidad antes de diseñar tu estrategia de tiers.

El caso de uso concreto: arrancás una base de datos con un tier económico y, cuando la carga sube, escalás IOPS y throughput cambiando una línea del PVC — sin ventana de mantenimiento ni migración de datos. Esto se complementa bien con la gestión de recursos de cómputo que vimos en la nota sobre límites de CPU y memoria para evitar vecinos ruidosos: ahora también podés ajustar el almacenamiento con la misma lógica declarativa.

¿Qué otras novedades relevantes trae la 1.34?

Además de los dos protagonistas, 1.34 consolidó varias features que veníais esperando en beta. Un resumen para ubicarte:

FeatureEstado en 1.34Para qué sirve
Dynamic Resource Allocation (DRA) coreEstable (KEP-4381)Seleccionar y compartir GPUs, TPUs y NICs de forma declarativa
Swap por nodo (LimitedSwap)EstablePermitir swap acotado al límite de memoria del pod
Ordered Namespace DeletionEstableBorrar recursos respetando dependencias (mitiga CVE-2024-7598)
KYAMLAlphaVariante de YAML sin ambigüedad de espacios ni coerción de tipos

¿Qué podés hacer con esto hoy?

Bastante, sin esperar a la próxima versión. Si tu cluster ya corre 1.34 o posterior, estas dos features están disponibles como API estable. Un plan concreto para empezar:

  1. Desplegá un OpenTelemetry Collector. Es el receptor de las trazas del kubelet y del API server; sin él no hay adónde exportar.
  2. Activá el tracing con muestreo bajo. Poné samplingRatePerMillion en 50000-100000 (5-10%) y validá que las trazas lleguen antes de subir el volumen.
  3. Verificá el soporte VAC de tu driver CSI. Consultá la documentación de tu driver para saber qué parámetros admite modificar en caliente.
  4. Definí tiers de almacenamiento. Creá dos o tres VolumeAttributesClass (económico, balanceado, alto rendimiento) y probá el cambio en un PVC de prueba antes de tocar producción.

Preguntas frecuentes

¿El tracing del kubelet reemplaza a las métricas de Prometheus?

No, son señales complementarias. Las métricas te dicen qué está mal (latencia alta, errores) de forma agregada; las trazas te dicen dónde exactamente en la cadena de una operación individual. El tracing del kubelet sirve para depurar operaciones puntuales, no para reemplazar tu monitoreo de series de tiempo.

¿VolumeAttributesClass funciona con cualquier tipo de almacenamiento?

No. Requiere que el driver CSI de tu proveedor de almacenamiento implemente la modificación de VolumeAttributesClass. Los volúmenes gestionados por plugins legacy o drivers que no soportan la capacidad no van a poder modificarse en línea, aunque el resto del cluster esté en 1.34.

¿Activar tracing impacta el rendimiento del nodo?

El impacto depende directamente del muestreo. Con una tasa baja (5-10%) el overhead es marginal; con muestreo al 100% (samplingRatePerMillion: 1000000) generás un volumen enorme de spans que consume CPU y red. La recomendación práctica es mantener el muestreo bajo y subirlo temporalmente solo mientras investigás un incidente.

¿Necesito estar en la última versión de Kubernetes para usar estas features?

No, alcanza con Kubernetes 1.34 o posterior, ya que ambas graduaron a estable en esa versión. Como se publicó en agosto de 2025, hoy es una base madura y presente en las versiones actuales del proyecto; si estás en una versión anterior, esta es una buena razón concreta para planificar la actualización.

¿Dónde confirmo los detalles oficiales?

En la documentación y el anuncio oficiales del proyecto, que valen más que cualquier resumen de terceros:

Cloud Serversby Donweb

Todo el poder de la nube a tus proyectos y aplicaciones.
Alojamiento ultra rápido, escalable y con alta disponibilidad.

  • Performance que te sorprenderá
  • Rápida escalabilidad y sin limitaciones
  • Arquitectura de alta disponibilidad
  • Soporte experto y ejecutivos de cuenta
  • Pagos en tu moneda y facturación local

Descubre la mejor solución de Cloud Hosting