A cluster names a group of upstream endpoints and tells Arion how to reach them: how endpoints are discovered, which protocol to speak, and how to spread load across them. Define one cluster per backend service, then route to it by name.
Define a cluster
clusters:
- name: api
type: STATIC
connect_timeout: 0.25s
lb_policy: ROUND_ROBIN
load_assignment:
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5678 }
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5679 }Discovery types
type | Endpoints come from |
|---|---|
STATIC | The inline load_assignment; addresses must be IPs, pipes, or internal |
STRICT_DNS | The inline load_assignment, hostnames resolved at connection time |
EDS | The control plane over xDS; no inline load_assignment allowed |
ORIGINAL_DST | The connection's original destination, a header, or metadata |
ORIGINAL_DST clusters must set lb_policy: CLUSTER_PROVIDED; the target comes from the original destination address by default, or from original_dst_lb_config with use_http_header (default header x-envoy-original-dst-host, or a custom http_header_name) or a metadata_key, optionally overriding the port with upstream_port_override. LOGICAL_DNS is not supported and is refused at startup.
Load-balancing policies
lb_policy accepts ROUND_ROBIN (the default), RANDOM, LEAST_REQUEST, RING_HASH, MAGLEV, and CLUSTER_PROVIDED. Endpoints take a load_balancing_weight (default 1), which every policy respects:
lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5678 }
load_balancing_weight: 3
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5679 }
load_balancing_weight: 1
RING_HASH and MAGLEV are consistent-hashing policies: they need a hash_policy on the route to build the hash from a header, query parameter, or source IP:
route:
cluster: api
hash_policy:
- header: { header_name: x-session-id }
- connection_properties: { source_ip: true }
Policies apply in order; a matching policy marked terminal: true stops the walk, and if nothing matches the hash is random. The load_balancing_policy extension point accepts the typed equivalents of the same policies plus override_host, which pins the upstream host to the value of a request header and falls back to a standard policy when the header is absent or invalid.
Priorities and failover
Endpoint groups carry a priority (0 is highest; levels must be contiguous from 0). Traffic goes to priority 0 while it is healthy; as its healthy share drops, load spills to the next level following Envoy's priority-levels algorithm with a 1.4 overprovisioning factor:
load_assignment:
endpoints:
- priority: 0
lb_endpoints:
- endpoint:
address:
socket_address: { address: 10.0.0.1, port_value: 5678 }
- priority: 1
lb_endpoints:
- endpoint:
address:
socket_address: { address: 10.1.0.1, port_value: 5678 }
Health comes from active health checks and the endpoint's configured health_status.
Upstream protocol
Arion speaks HTTP/1.1 to upstreams unless the cluster says otherwise through typed_extension_protocol_options:
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
Only explicit configuration is supported (http_protocol_options for HTTP/1.1 with optional enable_trailers, or http2_protocol_options with max_concurrent_streams, initial window sizes, and connection_keepalive); auto-negotiation and use-downstream-protocol are not. common_http_protocol_options.idle_timeout closes idle upstream connections.
Upstream TLS
Add a transport_socket with an UpstreamTlsContext to encrypt traffic to the backend; sni is required:
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: api.example.com
common_tls_context:
validation_context:
trusted_ca: { filename: ./certs/ca.pem }
Add one tls_certificates entry (or an SDS reference) for mTLS toward the upstream — see TLS and mTLS.
Verify
curl -s http://127.0.0.1:9901/clusters | grep "^api::"api::127.0.0.1:5678::health_flags::healthy
api::127.0.0.1:5678::weight::3
api::127.0.0.1:5678::priority::0
...Limits
- Endpoint
localityis not supported — grouping is bypriorityonly, and a config that sets locality is refused. - Policy tuning knobs (ring size, Maglev table size, least-request choice count, slow start) are not supported.
- Outlier detection, subset load balancing, and DNS tuning fields (
dns_refresh_rate,respect_dns_ttl) are not supported. - One health check and one set of protocol options per cluster.
override_hostreads a header; metadata as a host source is not yet supported.
The full cluster surface is in the cluster reference, and failure handling continues in health checks and resilience.