PerfectScale

Escalado fino de pods en Kubernetes: más allá de HPA y VPA

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

Jun 25, 20264 min read
Joshua Fox

About Joshua Fox

Joshua Fox has been a software architect in innovative technology companies for 20 years. Now, he advises tech startups and growth companies on architecture and cost optimization for Google Cloud Platform and Amazon Web Services; also publishing articles, and speaking to cloud engineers.

He has a PhD from Harvard University and a BA in math from Brandeis.

My personal page

1. Introducción

El autoescalado en Kubernetes está pensado para mantener la robustez sin disparar los costos. Los autoescaladores pueden ajustar la cantidad de nodos con el Cluster Autoscaler, o bien la cantidad y el tamaño de los pods con un Vertical o Horizontal Pod Autoscaler.

Pero tiene sus límites: los autoescaladores estándar dependen de métricas demasiado generales, como el uso promedio de CPU. Esa imprecisión termina en dos escenarios: o se retienen recursos que se desperdician, o el sistema se vuelve inestable bajo carga. En este artículo me voy a centrar en los autoescaladores de pods y explicaré cómo la telemetría fina de cAdvisor, Kube-State-Metrics y eBPF permite tomar decisiones de escalado más precisas y adaptadas al workload. Esas decisiones luego se aplican a pods en vivo a través de la API InPlacePodVerticalScaling de Kubernetes.

2. Las fallas del autoescalado actual

El autoescalado estándar tiene tres limitaciones de fondo:

  • Granularidad de señal insuficiente: los promedios simples de CPU no reflejan el perfil de rendimiento completo de aplicaciones complejas, lo que deriva en decisiones de escalado tardías o equivocadas.
  • Conflicto entre HPA y VPA: HPA escala según los recursos solicitados, mientras que VPA modifica esas solicitudes. Cuando ambos operan de forma independiente, pueden emitir instrucciones contradictorias y provocar oscilaciones.
  • Redimensionamiento por desalojo: el VPA legado requiere desalojar pods para aplicar cambios de recursos, lo que interrumpe workloads con estado o sensibles a la caché que no toleran la latencia del arranque en frío.

3. El pipeline de telemetría multicapa

Partimos de las métricas a nivel de nodo como línea base y sumamos cuatro capas adicionales de telemetría para obtener señales más finas:

  • Capa 0 (línea base): utilización de CPU y memoria a nivel de nodo desde el Kubernetes Metrics Server, que aporta la base de granularidad gruesa.
  • Capa 1: telemetría a nivel de contenedor vía cAdvisor. Esta capa captura la latencia de micro-bursts —picos cortos de CPU que inflan los promedios sin reflejar carga sostenida— y los working sets de memoria, evitando decisiones de escalado motivadas por un crecimiento inocuo del page cache del kernel.
  • Capa 2: Kube-State-Metrics (KSM) aporta contexto sobre la salud del workload, como réplicas pendientes y señales de saturación del HPA. Así, el controlador puede determinar si el escalado es necesario o si ya está en curso antes de lanzar nuevas acciones.
  • Capa 3: eBPF sondea el kernel para exponer señales profundas de la aplicación, como las tasas de asignación del heap de la JVM y la presión del Garbage Collector (GC). Esto permite un ajuste preventivo de recursos antes de que ocurran eventos OOM. Por ejemplo, una sonda bpftrace que use marcadores USDT de HotSpot como usdt:/path/to/libjvm.so:hotspot:mem__pool__gc__begin puede detectar picos en la frecuencia del GC segundos antes de que afecten la latencia, dándole al controlador una ventaja inicial.
  • Capa 4: las GPU son hoy un recurso crítico para el costo y el rendimiento de AI/ML. Las métricas específicas de GPU vía NVIDIA DCGM permiten escalar en función de cuellos de botella de GPU, como la utilización de SM o la saturación del ancho de banda de memoria.

4. Cómo construir el controlador de escalado unificado

Un controlador unificado armoniza estas señales como una máquina de estados: mantiene estados explícitos (stable, scaling-horizontal, scaling-vertical, cooldown) y solo transita entre ellos cuando se cumplen condiciones definidas. Esto lo diferencia de los escaladores actuales, que en general funcionan como motores de reglas, evalúan cada señal de forma independiente y, por eso mismo, corren el riesgo de emitir instrucciones contradictorias.

El controlador opera en tres fases:

Fase 1: agregación de señales

Cada capa de telemetría aporta un puntaje ponderado a una única métrica de presión por workload. Las señales de la capa de aplicación, como la Capa 3 (presión de eBPF/GC), reciben un peso mayor.

Fase 2: arbitraje entre ejes

El controlador evita el conflicto al detectar que ya hay un escalado horizontal en curso; un escalado en progreso se evidencia con AbleToScale=True junto con una diferencia distinta de cero entre currentReplicas y desiredReplicas.

A la inversa, si un workload se declara como singleton o con estado (vía anotación o pertenencia a un StatefulSet), el controlador lo enruta hacia el escalado vertical, nunca al horizontal.

Fase 3: reconciliación y cooldown

Después de cualquier acción de escalado, un período de cooldown evita el thrashing. El controlador vuelve a evaluar solo tras observar al menos dos ventanas de métricas consecutivas por encima o por debajo del umbral, de modo que los picos transitorios no disparen eventos de escalado repetidos.

5. Escalado vertical in-place de pods

La API InPlacePodVerticalScaling, que alcanzó Disponibilidad General en diciembre de 2025 con Kubernetes v1.35, permite modificar recursos sin desalojar al pod. El controlador aplica un parche a la especificación del pod y, a continuación, el kubelet actualiza dinámicamente los cgroups del contenedor: sin caídas de conexión, sin reinicios de procesos.

Un ejemplo concreto: si la capa eBPF detecta una presión sostenida del GC de Java que indica que el agotamiento del heap es probable en los próximos 30 segundos, el controlador emite un PATCH /api/v1/namespaces/{ns}/pods/{name} con resources.requests.memory y resources.limits.memory actualizados. El kubelet aplica el cambio ajustando in-place el límite de memoria del cgroup del contenedor.

Esto resulta especialmente valioso para servicios con tiempos de arranque en frío significativos, como aplicaciones JVM, sidecars de bases de datos y cachés en memoria, donde el redimensionamiento por desalojo introduciría picos de latencia de decenas de segundos.

6. Conclusión

Las configuraciones estándar de HPA y VPA suelen quedarse cortas cuando hay que sostener al mismo tiempo un alto uptime y la eficiencia en costos. Al combinar la observabilidad fina de eBPF y cAdvisor con un escalado horizontal/vertical coordinado mediante una máquina de estados unificada, y al aplicar los cambios con redimensionamiento in-place de pods, las organizaciones pueden construir clusters auto-reparables y correctamente dimensionados, con una disrupción mínima.

PerfectScale es una implementación inspirada en los patrones arquitectónicos descritos aquí. Trabajo en Forward Deployed Engineering en DoiT, asesorando a clientes en AWS y Google Cloud Platform. No dudes en escribirme si tienes preguntas.