🎨 Sysprovider Code
Sysprovider LogoWiki
🇪🇸Hosting español para ecommerce

Balanceo de Carga con Envoy Proxy para Microservicios

Actualizado el 1 de noviembre de 2025

Introducción

La arquitectura de microservicios ha revolucionado el desarrollo de aplicaciones modernas, pero introduce desafíos complejos de gestión de tráfico. A medida que los servicios se multiplican, garantizar la disponibilidad, la baja latencia y la tolerancia a fallos se convierte en una tarea crítica. Aquí es donde entra en juego Envoy Proxy, un proxy de alto rendimiento diseñado específicamente para entornos de microservicios. En este artículo, exploraremos cómo implementar balanceo de carga efectivo con Envoy, combinando enrutamiento inteligente, observabilidad profunda y resiliencia a nivel de red.

Envoy no es solo un balanceador de carga; es una plataforma de datos de servicio completa. Funciona como un proxy de sidecar en cada instancia de microservicio, capturando todo el tráfico de entrada y salida. Esto permite aplicar políticas de enrutamiento, realizar balanceo de carga avanzado y recolectar métricas detalladas sin modificar el código de la aplicación.


¿Por qué Envoy Proxy para Microservicios?

A diferencia de los balanceadores de carga tradicionales (HAProxy, Nginx), Envoy está diseñado desde cero para la malla de servicios. Sus características clave incluyen:

  • Descubrimiento de servicios dinámico: se integra con sistemas como Consul, Kubernetes o Eureka.
  • Balanceo de carga avanzado: soporta algoritmos como Round Robin, Least Request, Ring Hash y Maglev.
  • Enrutamiento basado en contenido: permite dividir tráfico por headers, rutas, pesos o incluso por versión del servicio.
  • Observabilidad nativa: genera métricas detalladas (latencia, tasa de errores, conteo de peticiones) y trazas distribuidas.
  • Resiliencia: circuit breakers, timeouts, reintentos y límites de tasa.

[INFO] Envoy proxy es la base de proyectos como Istio y Consul Connect. Dominarlo te da control absoluto sobre el plano de datos de tu infraestructura.


Configuración Básica de Balanceo de Carga

Para empezar, necesitamos un archivo de configuración envoy.yaml. La estructura se divide en listeners, clusters y rutas. Un listener escucha peticiones entrantes, define rutas que determinan a qué cluster enviar el tráfico, y cada cluster contiene los endpoints de los microservicios.

Ejemplo de configuración mínima:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/api/v1" }
                route: { cluster: service_v1 }
              - match: { prefix: "/api/v2" }
                route: { cluster: service_v2 }
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: service_v1
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: LEAST_REQUEST
    load_assignment:
      cluster_name: service_v1
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: 10.0.0.1, port_value: 8080 }
        - endpoint:
            address:
              socket_address: { address: 10.0.0.2, port_value: 8080 }
  - name: service_v2
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_v2
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: 10.0.1.1, port_value: 8081 }

En este ejemplo:

  • El listener escucha en el puerto 10000.
  • Las rutas /api/v1 y /api/v2 dirigen el tráfico a clusters diferentes.
  • service_v1 usa Least Request (envía la petición al endpoint con menos conexiones activas).
  • service_v2 usa Round Robin clásico.

Algoritmos de balanceo soportados

Envoy ofrece múltiples estrategias:

AlgoritmoDescripciónUso recomendado
ROUND_ROBINDistribuye equitativamenteCargas homogéneas
LEAST_REQUESTEnvía al host con menos peticiones activasPeticiones con tiempos de respuesta variables
RING_HASHBasado en hash consistenteSession affinity o caché
RANDOMSelección aleatoriaPruebas o cargas muy balanceadas
MAGLEVHash consistente mejoradoAlta escalabilidad (usado en Google)

[TIP] Para microservicios con peticiones de duración variable, LEAST_REQUEST suele dar mejor rendimiento que ROUND_ROBIN.


Enrutamiento Avanzado con Envoy

El enrutamiento en Envoy va mucho más allá del prefijo de URL. Podemos enrutar basándonos en headers, parámetros de query, método HTTP o incluso metadatos dinámicos.

Enrutamiento por header (canary releases)

routes:
- match:
    prefix: "/api"
    headers:
    - name: "x-canary"
      string_match:
        exact: "true"
  route:
    cluster: service_canary
    weight: 10
- match:
    prefix: "/api"
  route:
    cluster: service_stable

Este ejemplo envía el 10% del tráfico con header x-canary: true al cluster canary, y el resto al estable. Es una técnica común para pruebas en producción.

Enrutamiento por peso (traffic splitting)

route:
  weighted_clusters:
    clusters:
    - name: service_v1
      weight: 80
    - name: service_v2
      weight: 20

Ideal para migraciones graduales de versiones.

Enrutamiento por método HTTP

match:
  safe_regex:
    google_re2: {}
    regex: "/users/.*"
  headers:
  - name: ":method"
    string_match:
      exact: "POST"

Observabilidad: Métricas, Logs y Trazas

Una de las mayores fortalezas de Envoy es la observabilidad integrada. Cada petición que pasa por el proxy genera datos que permiten entender el comportamiento del sistema.

Métricas clave

Envoy expone métricas en formato Prometheus en :9901/stats/prometheus. Las más importantes para microservicios:

  • cluster.upstream_rq_total: total de peticiones enviadas al cluster.
  • cluster.upstream_rq_xx: desglose por código de respuesta (2xx, 5xx, etc.).
  • cluster.upstream_rq_duration_ms: histograma de latencia.
  • listener.downstream_rq_total: peticiones recibidas.

Configuración de métricas

admin:
  access_log_path: /dev/null
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

Trazas distribuidas

Envoy soporta Zipkin, Jaeger, Datadog y OpenTelemetry. Con trazas distribuidas puedes seguir una petición a través de múltiples microservicios.

http_filters:
- name: envoy.filters.http.router
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
    start_child_spans: true
tracing:
  http:
    name: envoy.tracers.zipkin
    typed_config:
      "@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
      collector_cluster: zipkin
      collector_endpoint: "/api/v2/spans"

[WARNING] No olvides configurar el cluster zipkin en la sección de clusters, apuntando a tu servicio de trazas.

Logging de acceso

Para depuración, puedes habilitar logs detallados por petición:

access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: /var/log/envoy/access.log
    format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION%"

Estrategias de Resiliencia

Envoy incluye mecanismos para manejar fallos de forma elegante.

Circuit Breaker

Protege a los microservicios de sobrecarga. Si un cluster empieza a fallar, el circuito se abre y las peticiones se rechazan rápidamente.

circuit_breakers:
  thresholds:
  - priority: DEFAULT
    max_connections: 1024
    max_pending_requests: 1024
    max_requests: 1024
    max_retries: 3

Timeouts

route:
  cluster: service_v1
  timeout: 5s
  idle_timeout: 30s

Reintentos

route:
  cluster: service_v1
  retry_policy:
    retry_on: "5xx,gateway-error,connect-failure"
    num_retries: 3
    retry_host_predicate:
    - name: envoy.retry_host_predicates.previous_hosts

[INFO] Los reintentos deben usarse con cuidado. Demasiados reintentos pueden amplificar la carga en sistemas ya sobrecargados. Combínalos con circuit breakers.

Limitación de tasa (Rate Limiting)

Envoy puede limitar peticiones por usuario, IP o cualquier criterio. Se configura mediante un filtro global o por ruta.

http_filters:
- name: envoy.filters.http.local_ratelimit
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    stat_prefix: http_local_rate_limiter
    token_bucket:
      max_tokens: 100
      tokens_per_fill: 10
      fill_interval: 1s
    filter_enabled:
      default_value:
        numerator: 100
        denominator: HUNDRED

Integración con Kubernetes

Envoy es el proxy predeterminado en Istio, pero también puedes desplegarlo como un DaemonSet o Deployment independiente. Para entornos Kubernetes, la configuración dinámica es clave.

Usando xDS (Discovery Service)

Envoy puede obtener su configuración de un servidor de control (como Istio Pilot o Consul). Esto permite cambiar reglas de enrutamiento sin reiniciar el proxy.

dynamic_resources:
  ads_config:
    api_type: GRPC
    transport_api_version: V3
    grpc_services:
    - envoy_grpc:
        cluster_name: xds_cluster
  cds_config:
    ads: {}
  lds_config:
    ads: {}

Con xDS, el balanceo de carga se vuelve completamente dinámico: los clusters y rutas se actualizan en tiempo real a medida que los servicios escalan.


Buenas Prácticas y Recomendaciones Finales

  1. Empieza con configuración estática: para entornos pequeños, la configuración YAML es suficiente.
  2. Monitorea las métricas de Envoy: usa Prometheus + Grafana para dashboards de latencia, errores y throughput.
  3. Usa health checks: configura health checks activos (Envoy hace pings periódicos a los endpoints) para evitar enviar tráfico a instancias muertas.
  4. Aplica principios de seguridad: utiliza TLS mutuo (mTLS) entre proxies para cifrar la comunicación entre microservicios.
  5. Prueba el enrutamiento canary: el tráfico ponderado te permite lanzar nuevas versiones de forma segura.
  6. Documenta las políticas de reintentos: un exceso de reintentos puede causar tormentas de tráfico.

[WARNING] Evita configuraciones demasiado complejas al inicio. Envoy tiene una curva de aprendizaje pronunciada. Comienza con un listener, un cluster y una ruta, y luego añade funcionalidades gradualmente.


Conclusión

Envoy Proxy se ha convertido en el estándar de facto para el balanceo de carga en arquitecturas de microservicios. Su capacidad para combinar enrutamiento avanzado, observabilidad profunda y resiliencia en un solo proxy lo hace indispensable para equipos que buscan escalar con confianza. Ya sea que despliegues una malla de servicios completa con Istio o un proxy sidecar manual, Envoy te proporciona el control granular que necesitas para gestionar el tráfico en entornos distribuidos.

La inversión en aprender Envoy proxy se amortiza rápidamente cuando te enfrentas a problemas de latencia, caídas de servicio o despliegues complejos. Empieza a experimentar hoy con una configuración simple y descubre cómo transforma tu infraestructura de microservicios.

¿Necesitas ayuda?Son dos de nuestros técnicos, Agustín y Mikel, y están disponibles para resolver cualquier problema.

Hablar con ellos ahora
Agustín y Mikel