What is the architecture of Envoy Proxy and how do listeners, clusters, and routes work together?
Quick Answer
Envoy's architecture consists of listeners (accept incoming connections), filter chains (process traffic), routes (match requests to destinations), and clusters (groups of upstream endpoints). Traffic flows from a downstream client through a listener, gets processed by filters, matched by routes, and forwarded to a cluster endpoint.
Detailed Answer
Think of Envoy like a large hotel. Listeners are the doors to the hotel, each accepting guests on different entrances. Filter chains are the check-in procedures that inspect and process each guest. Routes are the directory signs that tell guests which floor and room to go to based on their reservation. Clusters are the actual floors with available rooms, and endpoints are the individual rooms on each floor.
The listener is the first component in Envoy's request processing pipeline. A listener binds to a specific IP address and port, accepting incoming connections from downstream clients. Each Envoy instance can have multiple listeners, for example one on port 80 for HTTP traffic and another on port 443 for HTTPS. Listeners are defined with a name, a bind address, and one or more filter chains. When a connection arrives, the listener selects the appropriate filter chain based on connection properties like SNI (Server Name Indication) for TLS or the source IP address. This is the entry point where all traffic first touches Envoy.
Filter chains contain an ordered list of network filters that process the connection. The most important filter for HTTP traffic is the HTTP Connection Manager (HCM), which upgrades a raw TCP connection into HTTP protocol handling. The HCM parses HTTP requests, manages connection pooling, and applies HTTP-level filters like rate limiting, authentication, and CORS. Within the HCM, the route configuration defines how requests are matched and forwarded. Routes match on URL paths, headers, query parameters, and other HTTP attributes, then direct the request to a specific cluster. The route configuration can be defined statically in the config file or dynamically through the Route Discovery Service (RDS).
Clusters represent groups of logically similar upstream hosts that Envoy forwards traffic to. A cluster named payments-api might contain three backend instances running on different IP addresses. Each cluster defines its load balancing policy (round-robin, least-request, random, ring-hash), health checking configuration, circuit breaker thresholds, and connection pool settings. Endpoints within a cluster are the actual network addresses of upstream service instances. Envoy supports multiple service discovery mechanisms for endpoints: static (hardcoded IPs), strict DNS (DNS resolution), logical DNS, EDS (Endpoint Discovery Service for dynamic environments), and original destination (for transparent proxying).
In production, a typical Envoy configuration for a microservices environment defines one listener on port 15001 that intercepts all outbound traffic from the local application. The route table maps destination hostnames to clusters: requests to order-service.default.svc.cluster.local go to the order-service cluster, requests to inventory-service go to the inventory-service cluster, and so on. Each cluster is configured with appropriate timeouts, retry policies, and health checks. The admin listener on port 9901 provides debugging endpoints. Understanding this architecture is essential because every service mesh configuration ultimately translates into these Envoy primitives.
A common misconception is that routes and clusters are the same thing. Routes define the matching logic (which requests go where), while clusters define the upstream behavior (how to connect, which endpoints to use, what load balancing algorithm to apply). Separating these concerns allows you to route different URL paths to different clusters with different policies, or to route the same path to different clusters based on headers for canary deployments.