Envoy’s routing capabilities, especially within a single Availability Zone (AZ), are far more granular and dynamic than a simple load balancer.
Let’s see it in action. Imagine you have two services, frontend and backend, running on different ports but within the same AZ.
# Envoy Configuration Snippet
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
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
codec_type: auto
route_config:
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/api/v1/users"
route:
cluster: backend_users
- match:
prefix: "/"
route:
cluster: frontend_web
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: frontend_web
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: frontend_web
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.1.10 # Example IP within the AZ
port_value: 8001
- endpoint:
address:
socket_address:
address: 10.0.1.11 # Another example IP within the AZ
port_value: 8001
- name: backend_users
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: backend_users
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.1.20 # Example IP within the AZ
port_value: 9000
- endpoint:
address:
socket_address:
address: 10.0.1.21 # Another example IP within the AZ
port_value: 9000
In this setup, Envoy acts as a local proxy. It listens on port 8080. When a request comes in for /api/v1/users, Envoy consults its route_config. It finds a match for the /api/v1/users prefix and forwards the request to the backend_users cluster. If the request path doesn’t match /api/v1/users (e.g., it’s just / or /index.html), it falls through to the next route, which matches / and sends the request to the frontend_web cluster.
The clusters define the actual upstream services. Each cluster has load_assignment which lists the endpoints – the IP addresses and ports of the service instances. Envoy uses the specified lb_policy (here ROUND_ROBIN) to distribute requests across these endpoints. The type: STRICT_DNS means Envoy will resolve the service names (though here we’ve used IPs directly for simplicity within an AZ context) and maintain a cache.
This isn’t just about directing traffic; it’s about intelligent distribution and service discovery within your infrastructure. You can define sophisticated routing rules based on request headers, query parameters, or even the source IP address, all without those requests ever leaving the Availability Zone. This significantly reduces latency and egress costs compared to routing traffic across AZs unnecessarily.
Envoy’s routing is not limited to simple path matching. You can use regex_match for more complex URL structures, safe_regex_match for enhanced safety, or even match on specific request headers using header_match. For example, to send requests with a specific x-version: beta header to a separate beta_backend cluster, you’d add another route:
- match:
prefix: "/api/v1/users"
headers:
- name: "x-version"
exact_match: "beta"
route:
cluster: beta_backend
This allows for blue-green deployments, canary releases, or A/B testing managed entirely by Envoy’s routing logic, even for services co-located within the same AZ. The connect_timeout is crucial for ensuring Envoy doesn’t wait indefinitely for an unhealthy upstream.
When configuring Envoy to route traffic within an AZ, especially for services that might have rapidly changing IP addresses (like those managed by Kubernetes or other orchestrators), using type: EDS (Endpoint Discovery Service) instead of STRICT_DNS is often more robust. EDS allows Envoy to dynamically receive lists of healthy endpoints from a control plane, rather than relying solely on DNS resolution. This offers more immediate updates and better health checking integration.
The next step is to understand how Envoy handles health checking and circuit breaking to ensure the reliability of this intra-AZ traffic routing.