Outcome
This guide takes a configuration written for Envoy and runs it under Arion — first as a static file, then attached to the xDS control plane you already operate. Use it when you have working Envoy config and want to move it, not rewrite it.
The compatibility promise
If Arion accepts a configuration meant for Envoy, it behaves essentially like Envoy: filters run in the expected order and requests are routed or rejected as Envoy would. If Arion cannot honour part of a config the same way, it refuses to start when loading from a file, or rejects the update when it arrives over xDS — it never silently ignores what you wrote. The reasoning behind this is laid out in Envoy compatibility.
Prerequisites
- Your Envoy bootstrap YAML.
- An
arionbinary — see install.
Run your bootstrap under Arion
There are two ways in, and neither changes the Envoy dialect itself.
The first is to wrap the bootstrap in an Arion file: everything that was top-level in Envoy moves under an envoy_bootstrap: key, leaving room for Arion-native keys such as logging beside it. A complete minimal example:
envoy_bootstrap:
static_resources:
listeners:
- name: http_8080
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- name: http_8080_chain
filters:
- name: http_gateway
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: http_8080_routes
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: /
route:
cluster: backend
clusters:
- name: backend
connect_timeout: 5s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5678 }arion --config arion.yaml
The second way skips the wrapper entirely: point Arion straight at the unmodified Envoy file with --with-envoy-bootstrap.
arion --with-envoy-bootstrap envoy.yaml
The two flags combine — --config supplies Arion-native settings while --with-envoy-bootstrap overrides whatever bootstrap the config file carried. Inside a config file the same exclusivity holds: a file sets envoy_bootstrap or Arion's native bootstrap key, never both.
Nothing inside the bootstrap is translated by hand. Filter names, @type URLs, route match shapes, cluster fields — everything keeps its Envoy spelling, which is what makes the move reversible while you evaluate. Two dialect notes from real migrations: Arion requires name on resources Envoy lets you leave anonymous, filter chains especially, so name them before converting; and the connection manager's stat_prefix, mandatory in Envoy, is accepted but ignored with a startup warning.
Read the refusals
The first run of a real-world bootstrap usually fails, deliberately. Suppose a cluster named web carries outlier_detection. Arion exits with an error that names the field and where it sits:
Error parsing field static_resources / clusters ["web"]
Unsupported field: outlier_detection
The reaction is always the same: delete the field or replace it with a supported equivalent, consult the supported configuration reference for what the surrounding resource accepts, and run again until Arion starts. An unsupported filter or extension fails as Unsupported enum variant naming its @type URL; a key Envoy itself does not know fails earlier, as a YAML error naming the position. Each refusal is a statement that Arion could not have honoured that line the way Envoy does — not a parser bug to work around.
Once it starts, treat that as the halfway point, not the finish. Run Arion beside the Envoy it replaces — on a different port or host — send the same requests through both, and compare status codes, routing decisions and access logs before cutting traffic over. Refusals catch what Arion will not do; a side-by-side soak is how you confirm what it does.
Under your control plane
Dynamic configuration is the same story: Envoy's bootstrap shape, consumed unchanged, and to the control plane Arion looks like one more Envoy client identified by its node.id and node.cluster. Arion connects through ads_config, with a static cluster carrying the xDS server address:
envoy_bootstrap:
node:
id: arion-1
cluster: edge
dynamic_resources:
ads_config:
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
static_resources:
clusters:
- name: xds_cluster
connect_timeout: 0.25s
type: STATIC
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: {}
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 50051 }
Arion speaks the incremental (delta) variant of ADS, so the control plane must serve delta streams. Over that stream it subscribes to listeners, clusters, routes, endpoints and secrets — LDS, CDS, RDS, EDS and SDS — so a listener delivered dynamically may use rds with config_source: { ads: {} } and a route_config_name exactly as under Envoy. Everything must flow through ADS: separate lds_config or cds_config sources are refused at startup. When the control plane pushes a resource Arion cannot honour, the compatibility promise switches from refusing to start to rejecting the update: Arion NACKs, carrying the same error text back over the stream for the control plane to log, and the invalid resource is not applied. Setup detail is in xDS control planes.
Commonly hit unsupported areas
Fields that make working Envoy configs fail their first Arion run, all refused at load rather than ignored:
ext_authz, as an HTTP or network filter — no external authorization callout exists.- Cluster
outlier_detection— active health checks are the ejection mechanism. - Cluster
type: LOGICAL_DNS— useSTRICT_DNSorSTATIC. - Access log
json_format— write atext_formatwhose template is a JSON object instead. - Bootstrap-level
layered_runtime,overload_manager,stats_config,watchdog,cluster_managerandhds_config. lds_config/cds_configindynamic_resources— ADS only.
The list is not exhaustive; the supported configuration reference is the authoritative inventory.
Next
Read Envoy compatibility for what the guarantee promises and why, then move real traffic with the L7 load balancer pattern under Arion.