TL;DR — Resumen Rápido
Guía completa de Envoy Proxy para service mesh y edge proxy. Cubre xDS API, balanceo de carga, mTLS, observabilidad, circuit breaking y sidecar en Kubernetes.
Envoy Proxy es el plano de datos en el corazón de los service mesh modernos. Creado originalmente en Lyft para resolver la observabilidad y confiabilidad de microservicios a escala, Envoy es hoy el sidecar de facto para Istio, el edge proxy de muchos controladores de ingress y un proxy L3/L4/L7 de propósito general usado por Google, AWS y miles de empresas. Esta guía cubre la arquitectura de Envoy, configuración estática y dinámica, algoritmos de balanceo de carga, pipeline de observabilidad, gestión de TLS y filtros avanzados.
Requisitos Previos
- Docker (para pruebas autónomas) o un clúster de Kubernetes.
- Conocimiento básico de HTTP, TLS y conceptos de proxy inverso.
- Familiaridad con la sintaxis de configuración YAML.
curly opcionalmentejqpara probar endpoints.
Arquitectura de Envoy
Envoy opera como un proxy de red fuera del proceso — se ejecuta junto a tu aplicación en lugar de como una biblioteca dentro de ella. Esto mantiene el proxy independiente del lenguaje y permite actualizaciones independientes.
Componentes principales:
- Listeners — Puertos de red donde Envoy escucha (aquí llegan las conexiones downstream).
- Cadenas de filtros — Lista ordenada de filtros de red y HTTP aplicados a cada conexión.
- Clústeres — Grupos nombrados de endpoints upstream (tus servicios backend).
- Endpoints — Pares IP:puerto individuales dentro de un clúster, descubiertos vía EDS o config estática.
- Rutas — Reglas que mapean solicitudes entrantes a clústeres basadas en ruta, cabecera o parámetros de consulta.
Modelo de hilos: Envoy usa un hilo principal para gestión más un hilo trabajador por núcleo de CPU. Cada hilo trabajador gestiona conexiones de forma independiente usando I/O no bloqueante. No hay contención de bloqueos en el camino caliente — cada worker tiene su propio pool de conexiones.
Hot restart: Envoy soporta actualizaciones binarias sin tiempo de inactividad mediante un handshake en memoria compartida entre el proceso antiguo y el nuevo. El nuevo proceso toma el control de las conexiones existentes sin perder tráfico.
Configuración Estática (envoy.yaml)
La forma más rápida de comenzar es una configuración YAML estática con todos los recursos definidos en línea:
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
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: "/"
route:
cluster: service_backend
timeout: 15s
retry_policy:
retry_on: "5xx,reset,connect-failure"
num_retries: 3
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: service_backend
connect_timeout: 0.5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: backend-service
port_value: 8080
health_checks:
- timeout: 1s
interval: 10s
unhealthy_threshold: 2
healthy_threshold: 2
http_health_check:
path: /health
El bloque admin expone la API de gestión de Envoy en el puerto 9901. Úsalo para consultar /stats, /clusters, /config_dump y /healthcheck/fail para pruebas de circuit-breaker.
Configuración Dinámica: La API xDS
Las configuraciones estáticas funcionan para despliegues simples pero se vuelven difíciles de manejar a escala. El protocolo xDS (x Discovery Service) de Envoy permite que un plano de control envíe cambios de configuración en tiempo de ejecución — sin recarga, sin reinicio.
Tipos de recursos xDS:
| API | Gestiona |
|---|---|
| LDS (Listener Discovery Service) | Listeners y cadenas de filtros |
| RDS (Route Discovery Service) | Hosts virtuales y tablas de rutas |
| CDS (Cluster Discovery Service) | Definiciones de clústeres y políticas |
| EDS (Endpoint Discovery Service) | Salud individual de endpoints IP:puerto |
| SDS (Secret Discovery Service) | Certificados TLS y claves privadas |
ADS (Aggregated Discovery Service): Combina todas las APIs xDS en un único stream gRPC bidireccional. Es el modo recomendado porque garantiza el orden — un nuevo clúster siempre se entrega antes que la ruta que lo referencia, evitando errores 503 temporales durante las actualizaciones.
Delta xDS: En lugar de enviar el estado completo en cada actualización, delta xDS envía solo los recursos añadidos, modificados o eliminados. Esencial para mallas grandes con miles de clústeres.
Algoritmos de Balanceo de Carga
Envoy soporta seis políticas de balanceo de carga seleccionables por clúster:
| Política | Mejor Para |
|---|---|
ROUND_ROBIN | Capacidad uniforme del backend, elección predeterminada |
LEAST_REQUEST | Duración variable de solicitudes, evita backends sobreocupados |
RING_HASH | Hash consistente — afinidad de caché, servicios con estado |
RANDOM | Simple, bajo overhead, resistente a endpoints lentos |
MAGLEV | Hash consistente de Google — distribución más uniforme |
CLUSTER_PROVIDED | Delega la decisión al tipo de clúster upstream |
Observabilidad
Envoy es dogmático sobre la observabilidad — fue construido para hacer depurables los sistemas distribuidos. Tres pilares integrados:
Estadísticas: Envoy emite miles de contadores, indicadores e histogramas. Expónlos a Prometheus en el endpoint admin:
curl http://localhost:9901/stats/prometheus
Trazabilidad Distribuida: Envoy genera y propaga automáticamente cabeceras de contexto de traza para Jaeger, Zipkin y OpenTelemetry. Tu aplicación solo necesita reenviar estas cabeceras — Envoy maneja la creación de trazas.
Registro de Acceso: Logs de acceso JSON estructurado con todos los metadatos de la solicitud, incluyendo clúster upstream, duración, código de respuesta y bytes enviados.
TLS y mTLS con SDS
El Secret Discovery Service (SDS) de Envoy resuelve la distribución manual de certificados: los certificados se obtienen de un plano de control en tiempo de ejecución y se rotan sin reinicio del proceso.
Para TLS mutuo entre servicios, el campo match_subject_alt_names aplica la identidad SPIFFE — solo se aceptan conexiones de servicios con el URI SPIFFE esperado. Así es como Istio implementa redes de confianza cero: cada conexión pod a pod se autentica mutuamente mediante certificados de corta duración rotados por SPIRE.
Filtros Avanzados
Circuit Breaking: Previene fallos en cascada limitando solicitudes pendientes, reintentos y conexiones. Configura max_connections, max_pending_requests, max_requests y max_retries por clúster.
Detección de Outliers: Expulsa automáticamente hosts no saludables del pool de balanceo. Tras cinco respuestas 5xx consecutivas, el endpoint se expulsa durante 30 segundos. max_ejection_percent evita expulsar todos los hosts cuando el upstream degrada globalmente.
Inyección de Fallos: Inyecta latencia o errores en un porcentaje de solicitudes para pruebas de caos, configurable por ruta sin cambios en el código de la aplicación.
Autorización Externa: Delega decisiones de autorización a un servicio gRPC externo (OPA, Ory Keto). El filtro ext_authz envía cabeceras de solicitud al servicio de autorización antes de reenviar upstream.
Extensiones Wasm: Envoy soporta plugins de filtro WebAssembly para lógica de negocio personalizada en cualquier lenguaje que compile a Wasm (Go, Rust, C++). Los filtros Wasm se recargan en caliente sin actualizaciones binarias.
Envoy vs Otros Proxies
| Característica | Envoy | Nginx | HAProxy | Traefik | Linkerd | MOSN |
|---|---|---|---|---|---|---|
| Config dinámica | API xDS (sin recarga) | nginx -s reload | API en tiempo real | Auto-descubre K8s | xDS (limitado) | API xDS |
| Service mesh | Sí (Istio, Consul) | No | No | No (solo ingress) | Sí (Linkerd2) | Sí |
| Protocolos L7 | HTTP/1.1, HTTP/2, gRPC, Thrift | HTTP/1.1, HTTP/2 | HTTP/1.1, HTTP/2 | HTTP/1.1, HTTP/2 | HTTP/1.1, HTTP/2, gRPC | HTTP/1.1, HTTP/2, Dubbo |
| Observabilidad | Stats + tracing integrados | Basado en módulos | Socket de stats | Plugin Prometheus | Señales doradas integradas | Stats integrados |
| mTLS | SDS + SPIFFE | Certs manuales | Certs manuales | Certs manuales | Automático | SDS |
| Filtros Wasm | Sí | No | No | No | No | Sí |
Ejemplo Práctico: Envoy como Proxy Frontal
Tienes tres microservicios (users, orders, products) detrás de Envoy como edge proxy, con tráfico dividido entre v1 y v2 del servicio de órdenes para un despliegue canary:
routes:
- match:
prefix: "/orders"
route:
weighted_clusters:
clusters:
- name: orders_v1
weight: 90
- name: orders_v2
weight: 10
total_weight: 100
Esta configuración de clúster ponderado envía el 10% del tráfico /orders al canary v2 sin cambios en el código de la aplicación.
Errores Comunes y Casos Límite
- Sensibilidad a mayúsculas de cabeceras: Las cabeceras HTTP/2 son minúsculas por defecto. Envoy las normaliza — asegúrate de que tus servicios manejen
content-type,authorizationen minúsculas. - Timeouts upstream vs de ruta:
connect_timeoutdel clúster (TCP) ytimeoutde la ruta (solicitud) son independientes. El timeout de ruta predeterminado es 15 segundos — establécelo explícitamente. - Presupuesto de reintentos: Sin límites en
retry_on, los reintentos bajo carga pueden amplificar fallos. Combina siempre los reintentos con un circuit breaker.
Solución de Problemas
| Síntoma | Causa Probable | Solución |
|---|---|---|
503 upstream_reset_before_response_started | Upstream cerró conexión antes de responder | Verifica la ruta de health check; aumenta connect_timeout |
| 404 de Envoy (no del upstream) | Sin ruta coincidente | Ejecuta /config_dump en el puerto admin; verifica el dominio del virtual host |
| Circuit breaker abierto en stats | Upstream sobrecargado | Aumenta max_pending_requests o escala el upstream |
| Fallo de handshake mTLS | Discrepancia en SAN del certificado | Verifica que match_subject_alt_names coincida con el URI SPIFFE real |
| Alta latencia P99 | Inanición de hilos | Aumenta el conteo de worker threads con concurrency en el bootstrap |
Resumen
- La API xDS habilita configuración completamente dinámica sin reinicios — clústeres, rutas, listeners y certificados se actualizan en vivo.
- El balanceo de carga ofrece seis algoritmos incluyendo Ring Hash para afinidad de caché y Least Request para cargas de trabajo heterogéneas.
- La observabilidad integrada proporciona stats Prometheus, cabeceras de trazado distribuido y logs de acceso JSON estructurado.
- mTLS vía SDS + SPIFFE entrega redes de confianza cero con certificados de corta duración rotados automáticamente.
- Los filtros avanzados hacen a Envoy extensible sin tocar el código de la aplicación.