Clusters are declared under envoy_bootstrap.static_resources.clusters (or delivered over CDS) using standard Envoy field names; fields outside this reference make Arion refuse the configuration.
| Field | Type | Required | Default | Description |
name | string | yes | — | Unique cluster name; routes reference it. |
type | enum | yes | — | STATIC, STRICT_DNS, EDS or ORIGINAL_DST. LOGICAL_DNS is not supported. |
load_assignment | object | see below | — | Endpoints. Required for STATIC (IP, pipe or internal addresses) and STRICT_DNS (host names resolved over DNS); forbidden for EDS (endpoints arrive over ADS, see xDS resource types) and ignored for ORIGINAL_DST. |
lb_policy | enum | no | ROUND_ROBIN | ROUND_ROBIN, RANDOM, LEAST_REQUEST, RING_HASH, MAGLEV or CLUSTER_PROVIDED. RING_HASH and MAGLEV hash with the route's hash_policy; ORIGINAL_DST clusters must use CLUSTER_PROVIDED. |
load_balancing_policy | object | no | — | Typed alternative to lb_policy: exactly one policy whose typed_config is one of the six accepted @types (below). |
connect_timeout | duration | no | none | Upstream connection establishment timeout. |
cleanup_interval | duration | no | 5s | How long an idle ORIGINAL_DST host is kept before it is expired. |
health_checks | list | no | [] | At most one health check. |
circuit_breakers | object | no | defaults | Thresholds per routing priority. |
typed_extension_protocol_options | map | no | HTTP/1.1 | One entry of HTTP protocol options. |
transport_socket | object | no | plaintext | Upstream TLS, RawBuffer, or PROXY protocol upstream transport. |
upstream_bind_config | object | no | — | Only socket_options with a single SO_BINDTODEVICE entry (level: 1, name: 25). |
original_dst_lb_config | object | no | — | Original-destination routing settings; only valid with type: ORIGINAL_DST. |
load_balancing_policy accepts these typed_config types (all under type.googleapis.com/envoy.extensions.load_balancing_policies.): round_robin.v3.RoundRobin, random.v3.Random, least_request.v3.LeastRequest, ring_hash.v3.RingHash, maglev.v3.Maglev and override_host.v3.OverrideHost — each with an empty config, except OverrideHost which takes exactly one override_host_sources entry with header: <name> plus a required fallback_policy (any of the other five).
clusters:
- name: api
type: STATIC
lb_policy: ROUND_ROBIN
connect_timeout: 0.25s
load_assignment:
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5678 }
| Field | Type | Required | Default | Description |
cluster_name | string | no | — | Informational; the enclosing cluster's name is what routes use. |
endpoints | list | yes | — | Endpoint groups. locality metadata is not supported inside a group. |
endpoints[].priority | uint32 | no | 0 | Failover priority. Priorities used across groups must run 0..N without gaps; priority 0 serves first and traffic spills to the next priority as its hosts become unhealthy. |
endpoints[].lb_endpoints | list | yes | — | The endpoints of the group. |
lb_endpoints[].endpoint.address | object | yes | — | socket_address (address, port_value), pipe (path) or envoy_internal_address (server_listener_name). |
lb_endpoints[].load_balancing_weight | uint32 | no | 1 | Relative weight, at least 1. |
lb_endpoints[].health_status | enum | no | HEALTHY | Initial health (HEALTHY, UNHEALTHY; UNKNOWN counts as healthy). |
load_assignment:
endpoints:
- priority: 0
lb_endpoints:
- endpoint:
address:
socket_address: { address: 10.0.0.1, port_value: 8080 }
load_balancing_weight: 3
- endpoint:
address:
socket_address: { address: 10.0.0.2, port_value: 8080 }
load_balancing_weight: 1
- priority: 1
lb_endpoints:
- endpoint:
address:
socket_address: { address: 10.0.1.1, port_value: 8080 }
One entry under health_checks. The timing fields sit at the top level; the checker itself is one of http_health_check, tcp_health_check or grpc_health_check.
| Field | Type | Required | Default | Description |
timeout | duration | yes | — | Time to wait for a check response. |
interval | duration | yes | — | Interval between checks. |
unhealthy_threshold | uint16 | yes | — | Failures before a host is marked unhealthy. |
healthy_threshold | uint16 | yes | — | Successes before a host is marked healthy again. |
initial_jitter | duration | no | none | Random delay before the first check. |
interval_jitter | duration | no | none | Random amount added to each interval. |
interval_jitter_percent | float | no | 0 | Fraction of interval (0.0-1.0) added as jitter; combines with interval_jitter. |
unhealthy_interval | duration | no | interval | Interval used while a host is unhealthy. |
unhealthy_edge_interval | duration | no | unhealthy_interval | Interval for the first check after a host turns unhealthy. |
healthy_edge_interval | duration | no | interval | Interval for the first check after a host turns healthy. |
| Field | Type | Required | Default | Description |
path | string | no | none | Request path; must not contain a query string. |
host | string | no | cluster name | Value of the Host header; the cluster name must be a valid authority if this is unset. |
method | enum | no | GET | Only GET is supported. |
expected_statuses | list | no | [[200,201)] | Status ranges (start inclusive, end exclusive, within 100-600) that count as healthy. |
retriable_statuses | list | no | [] | Status ranges that do not immediately mark the host unhealthy. |
codec_client_type | enum | no | HTTP1 | HTTP1 or HTTP2; must match the cluster's protocol options. |
| Field | Type | Required | Default | Description |
send | object | no | connect only | Payload to send: {text: "<hex>"} (hex-encoded bytes) or {binary: <bytes>}. |
receive | list | no | [] | Payloads that must appear in the response, same forms as send. |
| Field | Type | Required | Default | Description |
service_name | string | no | "" | Service name passed to the standard gRPC health service. The cluster must use HTTP/2 protocol options. |
health_checks:
- timeout: 0.1s
interval: 5s
healthy_threshold: 3
unhealthy_threshold: 2
http_health_check:
path: /health
circuit_breakers.thresholds is a list; each entry applies to one routing priority and the last entry for a priority wins. Requests routed with priority: HIGH on the route action use the HIGH entry. When a limit trips, HTTP requests are rejected with 503 and x-envoy-overloaded: true.
| Field | Type | Required | Default | Description |
priority | enum | no | DEFAULT | DEFAULT or HIGH. |
max_connections | uint32 | no | 1024 | Maximum concurrent upstream connections. |
max_requests | uint32 | no | 1024 | Maximum concurrent in-flight requests. |
max_retries | uint32 | no | 3 | Maximum concurrent retries. |
track_remaining | bool | no | false | Track remaining capacity for observability. |
max_pending_requests, retry_budget and per_host_thresholds are not supported.
circuit_breakers:
thresholds:
- priority: DEFAULT
max_requests: 50
max_retries: 3
- priority: HIGH
max_requests: 100
max_retries: 5
One entry under typed_extension_protocol_options with @type: type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions. Only explicit_http_config is supported (auto_config and use_downstream_protocol_config are not).
| Field | Type | Required | Default | Description |
common_http_protocol_options.idle_timeout | duration | no | none | Idle timeout for upstream connections. |
explicit_http_config.http_protocol_options | object | one of | selected | Selects HTTP/1.1. Only enable_trailers (bool, default false) is accepted inside. |
explicit_http_config.http2_protocol_options | object | one of | — | Selects HTTP/2; fields below. |
| Field | Type | Required | Default | Description |
max_concurrent_streams | uint32 | no | none | Maximum concurrent streams per connection. |
initial_stream_window_size | uint32 | no | none | Per-stream flow-control window; must be greater than 0. |
initial_connection_window_size | uint32 | no | none | Per-connection flow-control window; must be greater than 0. |
connection_keepalive.interval | duration | yes* | — | PING keepalive interval (* required inside connection_keepalive). |
connection_keepalive.timeout | duration | no | none | Time to wait for a PING response before closing the connection. |
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: {}
Set as the cluster transport_socket with @type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext.
| Field | Type | Required | Default | Description |
sni | string | yes | — | Server name sent in the TLS handshake and used to verify the upstream certificate. |
common_tls_context.tls_params | object | no | min TLS 1.2 | Same protocol bounds as downstream TLS. |
common_tls_context.tls_certificates | list | no | none | At most one client certificate ({certificate_chain, private_key}) for mTLS. |
common_tls_context.tls_certificate_sds_secret_configs | list | no | none | At most one named secret reference instead of an inline certificate. |
common_tls_context.validation_context | object | no | — | {trusted_ca, trust_chain_verification} for verifying the upstream certificate. |
common_tls_context.validation_context_sds_secret_config | object | no | — | Named reference to a validation-context secret. |
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: /etc/ssl/certs/ca-certificates.crt
@type: type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport wraps the upstream connection in a PROXY protocol header.
| Field | Type | Required | Default | Description |
config.version | enum | yes | — | V1 or V2. |
config.pass_through_tlvs | object | no | none | match_type (INCLUDE_ALL or INCLUDE) and tlv_type list — TLVs copied from the downstream PROXY header (v2). |
config.added_tlvs | list | no | [] | {type, value} TLV entries to append (type 0-255). |
transport_socket | object | no | plaintext | Inner transport: an UpstreamTlsContext or RawBuffer. |
type: ORIGINAL_DST clusters pick the upstream address per request instead of from load_assignment; lb_policy must be CLUSTER_PROVIDED. The routing method comes from original_dst_lb_config; with neither method configured, the request authority (Host) is used as the destination:
| Field | Type | Required | Default | Description |
use_http_header | bool | no | false | Take the destination from a request header. Mutually exclusive with metadata_key. |
http_header_name | string | no | x-envoy-original-dst-host | Header carrying host:port when use_http_header is true. |
metadata_key | object | no | — | {key, path: [{key: ...}]} — read the destination from request metadata set by an earlier filter. |
upstream_port_override | uint16 | no | none | Replace the port of the resolved destination. |
clusters:
- name: dynamic
type: ORIGINAL_DST
lb_policy: CLUSTER_PROVIDED
connect_timeout: 5s
original_dst_lb_config:
use_http_header: true