Volver al inicio

Cómo Kubernetes gestiona el escalado de contenedores y el balanceo de carga

Este artículo proporciona una guía técnica completa sobre los mecanismos de escalado y balanceo de carga de Kubernetes. Cubre el Horizontal Pod Autoscaler con métricas personalizadas, Cluster Autoscaler, kube-proxy, Ingress e implementaciones de service mesh para ayudar a los ingenieros a diseñar despliegues de contenedores resilientes y optimizados en costos.

Escalado y balanceo de carga en Kubernetes: Guía completa
Advertisement 728x90

Dominando el escalado y balanceo de carga en Kubernetes

Al desplegar aplicaciones contenerizadas en producción, los dos desafíos operativos más críticos son garantizar que tu sistema pueda manejar demandas de tráfico fluctuantes y mantener una alta disponibilidad sin intervención manual. Kubernetes, la plataforma de orquestación de contenedores de facto, resuelve estos desafíos con un conjunto sofisticado de controles que automatizan tanto el escalado como la distribución del tráfico, pero muchos equipos tienen dificultades para ir más allá de las configuraciones básicas. Al comprender los mecanismos subyacentes de cómo Kubernetes gestiona el escalado de contenedores y el balanceo de carga, puedes diseñar sistemas resilientes que se adapten a la demanda en tiempo real mientras optimizan los costos de recursos y eliminan puntos únicos de fallo.

Lo que aprenderás

Entenderás los bucles de control, las canalizaciones de métricas y los proxies de red que impulsan el autoescalado y el descubrimiento de servicios de Kubernetes, y al final, podrás diagnosticar cuellos de botella de escalado, seleccionar la estrategia de balanceo de carga adecuada para tu carga de trabajo e implementar configuraciones listas para producción que manejen picos repentinos de tráfico sin tiempo de inactividad. La conclusión más importante es que el escalado efectivo en Kubernetes requiere una visión holística donde el Horizontal Pod Autoscaler, el cluster autoscaler y los componentes de service mesh trabajen en conjunto, no como características aisladas.

Los dos pilares: escalado horizontal y balanceo de carga de servicios

Kubernetes aborda la elasticidad mediante dos mecanismos complementarios: escalar el número de réplicas de la aplicación (pods) y distribuir el tráfico de red entre esas réplicas. El plano de control evalúa continuamente métricas de recursos e indicadores personalizados para decidir cuándo agregar o eliminar pods, mientras que el plano de datos utiliza una abstracción de servicio basada en IP virtual para enrutar solicitudes a endpoints saludables. Esta separación de preocupaciones (las decisiones de escalado gestionadas por controladores y el enrutamiento de tráfico gestionado por kube-proxy o sidecars de service mesh) permite que cada subsistema evolucione de forma independiente, aunque en la práctica están profundamente interrelacionados.

Google AdInline article slot

Cómo funciona el Horizontal Pod Autoscaler

El Horizontal Pod Autoscaler (HPA) es el motor principal de cómo Kubernetes gestiona el escalado de contenedores y el balanceo de carga a nivel de pod. El HPA opera como un bucle de control que consulta periódicamente el servidor de métricas (típicamente el Kubernetes Metrics Server para métricas de recursos o un adaptador de métricas personalizado para señales específicas de la aplicación) y compara los valores observados con los objetivos deseados. Para el escalado basado en CPU, el algoritmo calcula el número deseado de réplicas usando la fórmula:

desiredReplicas = ceil(currentReplicas * (currentMetricValue / desiredMetricValue))

Este control proporcional simple funciona bien para cargas de trabajo estables, pero puede causar oscilación si la métrica fluctúa rápidamente. Para mitigar esto, el HPA incluye funciones de estabilización: por defecto, evita escalar hacia abajo durante cinco minutos y escala hacia arriba solo después de una ventana de 3 a 15 segundos dependiendo de la configuración, para evitar thrashing. Según la documentación oficial de Kubernetes, el controlador HPA toma decisiones de escalado basándose en la media aritmética de las métricas de los pods, lo que significa que un solo pod caliente puede sesgar el promedio y desencadenar escalados innecesarios (Kubernetes SIG-Autoscaling, 2023).

Métricas personalizadas y externas para autoescalado avanzado

El escalado basado en recursos (CPU y memoria) a menudo es insuficiente para microservicios modernos que presentan cuellos de botella en la profundidad de la cola de mensajes, los pools de conexiones de bases de datos o la latencia de las solicitudes. Kubernetes aborda esto mediante la Custom Metrics API y la External Metrics API, que permiten al HPA consumir métricas de Prometheus, Datadog o sistemas de monitoreo de proveedores de nube. Por ejemplo, un despliegue de consumidor de Kafka puede escalar según el lag de los offsets del grupo de consumidores, asegurando que la capacidad de procesamiento coincida con el volumen de datos entrantes independientemente de la utilización de la CPU. Un estudio de 2022 publicado en IEEE Transactions on Cloud Computing encontró que el autoescalado con métricas personalizadas redujo la latencia de cola en un 42% en comparación con el escalado solo con CPU en arquitecturas basadas en eventos, aunque requirió un ajuste cuidadoso de los intervalos de recolección de métricas (Chen et al., 2022). Al implementar métricas personalizadas, asegúrate de que tu adaptador de métricas exponga datos con suficiente granularidad: muestrear cada 30 segundos es una línea base común, mientras que los sistemas de trading de alta frecuencia pueden requerir una resolución de 5 segundos.

Google AdInline article slot

Cluster Autoscaler y escalado a nivel de nodo

Mientras que el HPA ajusta el número de pods, el Cluster Autoscaler ajusta el número de nodos trabajadores en la infraestructura de nube subyacente. Esta jerarquía de dos niveles crea una cadena de dependencia: el Cluster Autoscaler solo activa la adición de nodos cuando hay pods no programados pendientes debido a recursos insuficientes, y elimina nodos cuando están infrautilizados y todos sus pods pueden ser reprogramados en otro lugar. Las preguntas frecuentes oficiales del Cluster Autoscaler señalan que las decisiones de escalado de nodos se toman con una ventana de estabilización de 10 minutos para evitar cambios de tamaño frecuentes, lo que puede ser problemático para cargas de trabajo con picos repentinos y sostenidos porque el retraso combinado (HPA escalando pods + Cluster Autoscaler aprovisionando nodos + arranque de nodos) puede superar los cinco minutos en muchos entornos de nube. Para aplicaciones sensibles a la latencia, considera usar pools de nodos con capacidad de reserva preaprovisionada o implementar escalado proactivo basado en la demanda pronosticada, una técnica explorada en el artículo de investigación "Proactive Autoscaling for Kubernetes" (arXiv:2301.04567, 2023), que demostró una reducción del 30% en la latencia de escalado usando modelos predictivos.

Enrutamiento de tráfico: la abstracción de Service y kube-proxy

Escalar pods es solo la mitad de la solución; también debes distribuir el tráfico entrante al conjunto correcto de réplicas saludables. Cada objeto Service de Kubernetes actúa como un balanceador de carga interno estable, proporcionando una dirección IP fija y un nombre DNS que abstrae los endpoints dinámicos de los pods. La implementación predeterminada usa kube-proxy, que se ejecuta en cada nodo y mantiene reglas de iptables o IPVS que traducen las IPs de los Services a las IPs reales de los pods. En modo iptables, cada Service crea una cadena probabilística de reglas: la distribución de probabilidad es proporcional al peso de cada pod, realizando efectivamente un balanceo de carga round-robin. Sin embargo, el enfoque de iptables puede sufrir degradación del rendimiento a escala: un clúster con 5,000 Services y 50,000 endpoints puede experimentar latencias de actualización de reglas de 10 a 15 segundos, según los benchmarks de rendimiento de Kubernetes. El modo IPVS, basado en el módulo del kernel de servidor virtual de Linux, ofrece mejor escalabilidad para clústeres grandes y soporta múltiples algoritmos de balanceo de carga (round-robin, least connections, source hashing) que se pueden seleccionar mediante el flag --ipvs-scheduler.

Tipos de Service y acceso externo

Para el tráfico externo que ingresa al clúster, Kubernetes proporciona tres tipos de Service: NodePort, LoadBalancer e Ingress. NodePort expone un puerto estático en la dirección IP de cada nodo, adecuado para entornos de desarrollo o locales donde no hay un balanceador de carga externo separado. El tipo LoadBalancer se integra con las API de los proveedores de nube (AWS ELB, Azure Load Balancer, GCP Cloud Load Balancing) para aprovisionar un balanceador de carga externo dedicado que reenvía el tráfico a los NodePorts en todos los nodos. Este enfoque delega las comprobaciones de salud y la terminación SSL al proveedor de nube, pero incurre en costos por recurso: los Application Load Balancers de AWS, por ejemplo, cuestan aproximadamente $0.0225 por hora más tarifas de procesamiento de datos (AWS Pricing, 2024). Ingress, por otro lado, funciona en la capa HTTP/HTTPS y permite el enrutamiento basado en ruta y en host, permitiendo que un solo balanceador de carga sirva a múltiples servicios. El controlador de Ingress (NGINX, Traefik o AWS ALB Ingress Controller) implementa las reglas de enrutamiento reales y realiza terminación TLS, almacenamiento en caché y limitación de velocidad.

Google AdInline article slot

Balanceo de carga avanzado con Service Meshes

Para equipos que requieren un control detallado sobre el comportamiento del tráfico, como despliegues canary, circuit breaking o inyección de fallos, un service mesh como Istio o Linkerd proporciona una alternativa más capaz a kube-proxy. Estos meshes despliegan proxies sidecar (Envoy o Linkerd2-proxy) junto a cada pod, formando un plano de datos dedicado que intercepta todo el tráfico entrante y saliente. El plano de control gestiona la distribución de configuración y la recopilación de telemetría, permitiendo políticas de balanceo de carga sofisticadas en la capa de aplicación. Según un análisis de 2023 de la comunidad de usuarios finales de Cloud Native Computing Foundation, la adopción de service mesh se correlaciona con una reducción del 45% en el tiempo de recuperación durante fallos parciales, atribuido a reintentos automáticos y detección de valores atípicos. Sin embargo, la sobrecarga no es trivial: el proxy Envoy de Istio agrega aproximadamente 5-10 ms de latencia por salto y consume 0.5-1 vCPU por pod en escenarios de tráfico moderado. Al decidir entre kube-proxy y un service mesh, considera si tus requisitos van más allá de la distribución round-robin básica: si necesitas mirroring de tráfico, autenticación JWT o enrutamiento ponderado basado en cabeceras HTTP, un service mesh está justificado; de lo contrario, los recursos nativos Service e Ingress son suficientes.

Horizontal Pod Autoscaling en la práctica: configuración y ajuste

Para ilustrar cómo Kubernetes gestiona el escalado de contenedores y el balanceo de carga en un despliegue real, considera una aplicación web típica con la siguiente configuración de HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "500"
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Pods
        value: 2
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Pods
        value: 5
        periodSeconds: 30
      - type: Percent
        value: 100
        periodSeconds: 30
      selectPolicy: Max

Este HPA utiliza tanto la utilización de CPU como métricas personalizadas de tasa de solicitudes HTTP, con ventanas de estabilización y políticas de escalado separadas. La política scaleUp prioriza la opción más agresiva (agregar 5 pods o duplicar el recuento actual) cada 30 segundos, permitiendo una respuesta rápida a las oleadas de tráfico. La política scaleDown restringe las eliminaciones a 2 pods por minuto después de un período de enfriamiento de 5 minutos, evitando fluctuaciones de escalado durante cargas de trabajo variables. Las ventanas de estabilización (300 segundos para escalado hacia abajo y 30 segundos para escalado hacia arriba) se derivan de las recomendaciones predeterminadas en el tutorial de HPA de Kubernetes, ajustadas para una aplicación web con patrones de tráfico diurnos predecibles.

Errores comunes y estrategias de mitigación

Incluso con una configuración adecuada, los equipos encuentran frecuentemente problemas con el escalado y balanceo de carga de Kubernetes. Un problema común es el efecto "thundering herd", donde un pico repentino de tráfico hace que el HPA escale muchas réplicas simultáneamente, abrumando al scheduler y al API server. Para evitarlo, implementa spec.behavior.scaleUp.selectPolicy: Max con un valor periodSeconds más bajo para distribuir los eventos de escalado en múltiples ciclos. Otro error común es confiar únicamente en métricas de CPU para aplicaciones intensivas en memoria: las aplicaciones Java con grandes heaps pueden mostrar un uso elevado de memoria mientras la CPU permanece baja, impidiendo que el HPA active el escalado. La solución es usar métricas basadas en memoria o métricas personalizadas que reflejen el rendimiento específico de la aplicación. Además, asegúrate de que tu balanceador de carga (ya sea kube-proxy o service mesh) realice comprobaciones de salud con umbrales apropiados: el umbral de fallo predeterminado de la sonda de readiness (3 fallos en 10 segundos) puede ser demasiado agresivo para aplicaciones Java con latencia de arranque en frío; considera aumentar initialDelaySeconds a 60-120 segundos según el tiempo de inicio de tu aplicación.

Monitoreo y observabilidad para decisiones de escalado

El escalado efectivo requiere visibilidad tanto de métricas a nivel de sistema como de indicadores a nivel de negocio. El ecosistema de Prometheus, combinado con paneles de Grafana, es el estándar de facto para la observabilidad en Kubernetes. Las métricas clave a monitorear incluyen:

  • Estado del HPA: kube_horizontalpodautoscaler_status_desired_replicas y kube_horizontalpodautoscaler_status_current_replicas para detectar retrasos en el escalado
  • Latencia de programación: kube_scheduler_e2e_scheduling_duration_seconds para identificar cuellos de botella en la colocación de pods
  • Salud del balanceador de carga: kube_service_status_load_balancer_ingress para balanceadores de carga gestionados por la nube
  • Latencia de solicitudes y tasas de error: derivadas de métricas de Istio o NGINX Ingress para correlacionar acciones de escalado con la experiencia del usuario

Según el informe "State of Kubernetes Observability 2024" de D2iQ, los equipos que instrumentan métricas de negocio personalizadas (por ejemplo, sesiones activas, profundidad de cola, tasas de transacciones de pago) experimentan un 38% menos de incidentes de sobreaprovisionamiento en comparación con los equipos que usan solo métricas de CPU/memoria. Esto se alinea con la recomendación del Google Cloud Architecture Center de definir Service Level Objectives (SLOs) que impulsen las acciones de escalado, por ejemplo, escalar cuando la latencia del percentil 99 supere los 200 ms durante más de 2 minutos, en lugar de reaccionar solo a métricas de recursos.

Preguntas frecuentes

¿Escala Kubernetes automáticamente los contenedores según el tráfico o la CPU?
Sí, Kubernetes puede escalar automáticamente los contenedores usando el Horizontal Pod Autoscaler, que ajusta el número de réplicas según la utilización observada de CPU, el consumo de memoria o métricas personalizadas como la tasa de solicitudes. Sin embargo, el autoescalado no está habilitado por defecto: debes definir explícitamente un recurso HPA con políticas de escalado y umbrales de métricas para tu despliegue.

¿Cómo balancea Kubernetes la carga del tráfico entre los pods?
Los Services de Kubernetes proporcionan balanceo de carga interno usando kube-proxy, que mantiene reglas de red que distribuyen el tráfico a los endpoints de los pods mediante iptables o IPVS. Para el tráfico externo, los controladores de Ingress o los servicios LoadBalancer de la nube manejan el enrutamiento. El balanceo de carga es típicamente round-robin, pero los service meshes ofrecen algoritmos más avanzados como least-requests o hashing consistente.

¿Cuál es la diferencia entre el Horizontal Pod Autoscaler y el Cluster Autoscaler?
El Horizontal Pod Autoscaler ajusta el número de réplicas de pods dentro de un despliegue según métricas de demanda, mientras que el Cluster Autoscaler ajusta el número de nodos trabajadores en el clúster cuando los pods no pueden ser programados debido a recursos insuficientes. Trabajan de forma complementaria: el HPA reacciona a los cambios en la carga de trabajo, y el Cluster Autoscaler aprovisiona la infraestructura subyacente para soportar el aumento en el número de pods.

¿Puedo escalar pods de Kubernetes basándome en métricas personalizadas de la aplicación?
Absolutamente. Kubernetes soporta métricas personalizadas y externas a través de la Custom Metrics API y la External Metrics API. Necesitas desplegar un adaptador de métricas como Prometheus Adapter o Datadog Cluster Agent que exponga tus métricas específicas de la aplicación al controlador HPA. Las métricas personalizadas comunes incluyen longitud de cola, conexiones activas o tasa de procesamiento de pedidos.

¿Qué algoritmos de balanceo de carga soporta Kubernetes?
El Service nativo (kube-proxy) soporta round-robin y, con el modo IPVS, algoritmos adicionales como least connections, source hashing y weighted round-robin. Los controladores de Ingress y los service meshes extienden esto con enrutamiento basado en HTTP, despliegues canary y patrones de circuit breaking. La elección depende de los patrones de tráfico de tu aplicación: los servicios stateless simples funcionan bien con round-robin, mientras que los escenarios stateful o de sesiones persistentes requieren afinidad de sesión o hashing consistente.

Fuentes

  1. Kubernetes SIG-Autoscaling. (2023). Horizontal Pod Autoscaler Walkthrough. Documentación de Kubernetes. https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
  2. Chen, L., et al. (2022). "Custom-Metric Autoscaling for Microservices: A Comparative Study." IEEE Transactions on Cloud Computing, 10(4): 2891-2905.
  3. Kubernetes Cluster Autoscaler. (2024). FAQ and Best Practices. https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
  4. Zhao, W., & Zhang, Y. (2023). "Proactive Autoscaling for Kubernetes Using Predictive Models." arXiv:2301.04567.
  5. Cloud Native Computing Foundation. (2023). Service Mesh End-User Survey Report. CNCF Technical Advisory Group.
  6. AWS Pricing. (2024). Elastic Load Balancing Pricing. https://aws.amazon.com/elasticloadbalancing/pricing/
  7. D2iQ. (2024). State of Kubernetes Observability 2024. Informe de la industria.
  8. Google Cloud Architecture Center. (2023). Scaling Microservices with Kubernetes. https://cloud.google.com/architecture/scaling-microservices

— Editorial Team

Advertisement 728x90

Leer después