Balanceo de Carga con HAProxy y Envoy: Estrategias Avanzadas
El ecosistema moderno de infraestructura cloud-native exige soluciones de balanceo de carga que no solo distribuyan tráfico, sino que integren observabilidad, resiliencia y automatización. HAProxy y Envoy son dos pesos pesados en este ámbito, pero representan filosofías distintas: HAProxy es el veterano consolidado, de alto rendimiento y configuración predecible; Envoy es el proxy moderno, diseñado para mallas de servicios y ecosistemas dinámicos. Dominar ambos y sus estrategias avanzadas es clave para cualquier SysAdmin que gestione desde un clúster de microservicios hasta un sitio web con picos de tráfico.
Este artículo profundiza en técnicas avanzadas de balanceo de carga con HAProxy y Envoy, cubriendo desde afinidad de sesión hasta circuit breakers y canary deployments.
HAProxy: Estrategias Avanzadas para Alto Rendimiento
HAProxy sigue siendo el estándar de facto para balanceo de carga TCP/HTTP por su eficiencia y su modelo de eventos asíncronos. Más allá de los algoritmos roundrobin o leastconn, existen configuraciones que marcan la diferencia en entornos de producción.
Afinidad de Sesión (Sticky Sessions) sin Cookies
En aplicaciones stateful, la afinidad de sesión es crítica. HAProxy permite fijar un cliente a un servidor backend usando la tabla de persistencia (stick-table) en lugar de cookies, lo que reduce la sobrecarga de procesamiento.
backend web_servers
balance roundrobin
# Tabla de persistencia basada en IP de origen
stick-table type ip size 50k expire 30m
stick on src
server web1 10.0.1.10:80 check
server web2 10.0.1.11:80 check
[TIP] La tabla stick-table consume memoria RAM. Ajusta el parámetro size según el número de clientes concurrentes esperados (50k entradas ≈ 5-10 MB).
Weighted Hashing y Balanceo por URI
Para sistemas de caché o CDN, el hashing consistente sobre la URI o el encabezado Host evita que un cambio en el pool de servidores invalide todo el caché.
backend api_cache
# Algoritmo hash sobre la URI completa
balance uri
hash-type consistent
server cache1 10.0.2.10:8080 weight 2
server cache2 10.0.2.11:8080 weight 1
server cache3 10.0.2.12:8080 weight 1
El parámetro hash-type consistent minimiza la redistribución de claves cuando se añade o elimina un servidor.
Protección ante Fallos Backup y Slow Starts
Cuando un servidor se recupera, no debe recibir tráfico de golpe. La directiva slowstart permite un incremento gradual del peso.
backend app_servers
server app1 10.0.3.10:80 check inter 3s fall 3 rise 2 slowstart 30s
# Servidor de respaldo que solo recibe tráfico si todos los primarios fallan
server backup1 10.0.3.20:80 backup
[WARNING] Un slowstart demasiado corto (ej. 5s) puede saturar la JVM de la aplicación si esta necesita calentar cachés internas.
Envoy: Balanceo Dinámico para Microservicios
Envoy fue diseñado desde cero para ser un proxy de capa 7 en mallas de servicios (Istio, Consul Connect). Su fortaleza reside en la configuración dinámica a través de la API de descubrimiento (xDS) y su modelo de filtros extensible.
Circuit Breakers: Resiliencia ante Fallos en Cascada
Un circuit breaker en Envoy monitoriza el estado de un clúster y detiene las peticiones cuando se superan ciertos umbrales (errores, conexiones pendientes, etc.). Esto evita que un servicio lento derribe a toda la cadena.
static_resources:
clusters:
- name: service_payments
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 100 # Conexiones simultáneas al backend
max_pending_requests: 10000 # Solicitudes en cola
max_requests: 1000 # Solicitudes activas
max_retries: 3 # Reintentos máximos
[INFO] Envoy expone estadísticas detalladas sobre el estado del circuit breaker (cluster.circuit_breakers.*). Es recomendable monitorizarlas con Prometheus para ajustar los umbrales.
Balanceo por Zona y Prioridad (Locality Aware)
En despliegues multi-región (us-east-1, eu-west-1), Envoy puede priorizar el tráfico local para reducir latencia y costes de ancho de banda.
clusters:
- name: service_frontend
lb_policy: LEAST_REQUEST
locality_weighted_lb_config:
# Distribución ponderada por zona
endpoints:
- locality:
region: us-east-1
zone: us-east-1a
lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.1.10
port_value: 8080
load_balancing_weight: 70
- locality:
region: eu-west-1
zone: eu-west-1b
lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.2.10
port_value: 8080
load_balancing_weight: 30
Envoy intentará enrutar el tráfico al endpoint más cercano al origen de la petición, y solo usará los remotos si los locales están saturados o caídos.
Canary Deployments con Envoy y Shadow Traffic
Una estrategia avanzada para microservicios es enrutar un porcentaje del tráfico a una nueva versión (canary) y, además, duplicar peticiones reales a la versión canary en modo “shadow” para medir impacto sin afectar al usuario.
routes:
- match:
prefix: "/api/v2/checkout"
route:
cluster: service_checkout_prod
# 5% del tráfico va al canary
weighted_clusters:
clusters:
- name: service_checkout_prod
weight: 95
- name: service_checkout_canary
weight: 5
# Shadow traffic: duplica el 100% de las peticiones al canary
request_mirror_policy:
cluster: service_checkout_canary
runtime_fraction:
default_value:
numerator: 100
denominator: 100
[WARNING] El shadow traffic duplica las peticiones. Asegúrate de que el clúster canary tenga suficiente capacidad para soportar la carga duplicada sin degradarse.
Comparativa: ¿Cuándo Usar Cada Uno?
La elección no es excluyente; muchos equipos usan HAProxy en el borde (edge proxy) y Envoy dentro del clúster (service mesh).
| Característica | HAProxy | Envoy |
|---|---|---|
| Rendimiento puro | Excelente (modo single-threaded o multi con nbthread) | Bueno, pero con mayor overhead por features |
| Configuración dinámica | Limitada (recarga de ficheros con reload) | Nativa (API xDS, ideal para Kubernetes) |
| Circuit breakers | Básico (maxconn, fall check) | Avanzado (umbrales por prioridad, conexiones, reintentos) |
| Observabilidad | Estadísticas en texto plano, métricas vía socket | Métricas estructuradas (Prometheus, OpenTelemetry) |
| Complejidad | Baja/Media | Alta (requiere entender xDS, filtros, etc.) |
Estrategia Híbrida: HAProxy + Envoy en la Práctica
Un patrón probado en producción es usar HAProxy como balanceador de entrada (L4/L7) y Envoy como sidecar proxy en cada pod de microservicio.
- HAProxy recibe tráfico externo, termina TLS, aplica reglas de rate limiting y distribuye entre los nodos del clúster Kubernetes.
- Envoy (como sidecar en cada pod) maneja el tráfico este-oeste entre microservicios, aplicando circuit breakers, retry budgets y trazabilidad distribuida.
# HAProxy - Frontend externo
frontend external_https
bind :443 ssl crt /etc/ssl/certs/domain.pem
default_backend k8s_ingress
backend k8s_ingress
balance roundrobin
option httpchk GET /healthz
server node1 10.0.0.10:30443 check
server node2 10.0.0.11:30443 check
server node3 10.0.0.12:30443 check
Mientras tanto, Envoy dentro del clúster gestiona la resiliencia entre servicios:
# Envoy sidecar config (fragmento)
clusters:
- name: service_orders
connect_timeout: 0.5s
circuit_breakers:
thresholds:
- priority: DEFAULT
max_retries: 3
max_pending_requests: 1000
retry_policy:
retry_on: connect-failure,refused-stream,unavailable
num_retries: 3
retry_host_predicate:
- name: envoy.retry_host_predicates.previous_hosts
Conclusión: El Balanceo Inteligente es la Clave
El balanceo de carga ya no es solo distribuir peticiones. Con HAProxy se gana madurez y rendimiento bruto; con Envoy se gana dinamismo y control granular sobre el tráfico de microservicios. Implementar circuit breakers, afinidad de sesión sin estado y despliegues canary son habilidades que separan a un SysAdmin operativo de un arquitecto de infraestructura.
La tendencia es clara: el edge seguirá siendo dominio de soluciones como HAProxy o Nginx, mientras que la malla de servicios se apoyará en Envoy. Pero conocer ambas herramientas y saber combinarlas te permitirá diseñar sistemas que no solo escalen, sino que sobrevivan a fallos con elegancia.
[TIP FINAL] No configures estos proxies de forma estática. Adopta herramientas como Ansible, Terraform o el control plane de Istio para gestionar la configuración como código. El balanceo de carga avanzado debe ser reproducible y auditable.
