aether.registry.v1 — The service registry: what an endpoint is, how a service is keyed, and the route and configuration projections that travel between clusters. Written through the registrar, read by every node agent.
Rendered by protoc from api/aether/registry/v1/ when this site was built, so it
cannot drift from the compiled schema — there is no committed copy of this page.
Field constraints are carried as buf.validate options and are not shown here;
read the .proto for those.
ExtensionFilter is a proxy-extension escape-hatch filter (proposal 025) carried with
the projection: the Envoy filter name + its opaque per-route typed_config.
GammaRoute mirrors the in-memory proxy.GammaRoute: one HTTPRoute/GRPCRoute rule
projected to data-plane vocabulary. Backends are already resolved to data-plane
cluster names by the exporting reconciler.
ServiceConfigProjection is the cross-cluster wire form of one service's projected
GAMMA config (proposal 026, multi-cluster config propagation — Option E/C). The
authoritative (exporting) cluster's GAMMA reconciler projects an HTTPRoute/GRPCRoute
attached to a Service into the RECONCILED GammaRoute form and writes this record to
the shared registry, origin-stamped + versioned; consuming clusters import it
read-only and materialize the routes WITHOUT re-running the reconciler or holding
cross-cluster Kubernetes credentials. The in-memory proxy.GammaRoute is the source;
config.go converts to/from this proto. See docs/proposals/026.
Field
Type
Label
Description
service
string
service is the route-target key "<ns>/<svc>" the projection applies to.
origin_cluster
string
origin_cluster is the authoritative exporting cluster (the conflict-resolution + import-authorization key — a consumer rejects a projection from a non-authority).
version
string
version is the exporter's monotonic version for this service's projection (last-writer-by-origin; consumers ignore an older version than they hold).
service_filter is the service-wide always-on extension filter (proposal 025 M4 CHAIN scope): at most one per service, enabled at the service's capture vhost (vhost-level typed_per_filter_config). Rides the 026 channel like routes.
ports is the full set of application ports this endpoint serves (multi-port pods). port (above) remains the default/primary port — what the portless FQDN resolves to and the fallback when ports is empty. Each client builds a per-port cluster whose EDS membership is filtered to endpoints advertising that port, so a new version adding a port rolls out safely (callers of the new port only ever land on pods that serve it). See proposal 005.
port_protocols is the wire protocol of each advertised port (proposal 037). REQUIRED (proposal 043). It names every port the endpoint lists (port, ports), each with a class other than UNSPECIFIED. An endpoint that does not is refused where it is written (RegisterEndpoint answers INVALID_ARGUMENT, on every backend), filtered by the registrar where it is already stored, and contributes nothing in an agent that is handed one. No reader derives a class from the protocol the endpoint was registered under any more: a class that is not stated is not guessed. (Before 043 a port absent here took the protocol of the registry key, the pre-037 whole-pod classification.) Every writer since 037 populates the full map. The map is a property of the endpoint, not of the registry key: a pod that serves both an HTTP and a raw-TCP port is registered once per distinct protocol, and BOTH registrations carry the same full map. That keeps the key layout, the etcd paths, the registrar snapshot key and every watch consumer unchanged — a pod appears under two keys rather than the schema growing a port dimension. The codec (h1 vs h2c) is deliberately not represented. It is an agent-local inbound concern carried by the =h2 suffix on endpoint.aether.io/ports, stripped before registration; the registry records only the L4 class the mesh hop has to know about.
node_ip is the node's routable InternalIP. It is the dial target for a cross-cluster endpoint whose pod IP is not routable across clusters: the consuming cluster's proxy dials node_ip:<tunnel-port> and that node's host-network proxy SNI-forwards to the local pod (proposal 019, per-node east/west waypoint). Empty when unknown (e.g. non-Kubernetes backends) or for same-cluster endpoints, which are dialed at the pod IP directly.
PortProtocol is the L4 class of ONE advertised port (proposal 037).
Values are numerically identical to Service.Protocol, and
TestPortProtocolMatchesServiceProtocol pins that correspondence so the two
cannot drift. They are separate declarations only because service.proto
already imports this file — a Service carries its endpoints — so referencing
Service.Protocol from here would be a circular import. The proposal specified
map<uint32, Service.Protocol> without noticing that cycle.
Unifying them means moving Protocol out of Service into a file both import,
which renames registryv1.Service_Protocol at 441 call sites across 47 files.
That is a mechanical change worth doing on its own, not folded into a feature
diff where it would hide the feature.
Name
Number
Description
PORT_PROTOCOL_UNSPECIFIED
0
PORT_PROTOCOL_HTTP
1
PORT_PROTOCOL_TCP
2
PORT_PROTOCOL_TCP marks a port reached through the transparent-capture TCP floor as a raw mTLS passthrough, not the HTTP HCM path.
PORT_PROTOCOL_UDP
3
PORT_PROTOCOL_UDP marks a datagram port reached through the UDP floor. Plaintext — see Service.Protocol.PROTOCOL_UDP for the security note and for why these ports are health-checked differently.
Health reflects whether the endpoint's application is serving, as actively
health-checked by the node-local agent (delegated liveness). The default
(HEALTH_UNSPECIFIED) is treated as healthy so endpoints from older agents and
freshly registered endpoints route normally until proven otherwise.
Name
Number
Description
HEALTH_UNSPECIFIED
0
HEALTH_HEALTHY
1
HEALTH_UNHEALTHY
2
HEALTH_DRAINING
3
HEALTH_DRAINING marks an endpoint whose pod's deletion has been requested: clients must stop selecting it for new requests (Envoy EDS DRAINING) while established connections finish through the pod's termination grace period. Set by the agent's termination watch; the endpoint is removed entirely at CNI DEL.
HealthCheckMode selects how client proxies determine this endpoint's health.
ACTIVE (the default, including UNSPECIFIED): each client proxy actively
HTTP-health-checks the endpoint's mesh readiness path. EDS: clients instead
rely on the EDS health status pushed by the node-local agent (delegated
liveness) and do not probe the endpoint themselves. Set per pod via the
endpoint.aether.io/health-check-mode annotation.
PROTOCOL_TCP marks a non-HTTP (raw TCP-over-mTLS) mesh service. Its endpoints are reached through the transparent-capture TCP floor as a raw mTLS passthrough (proposal 018, Phase 3a), not the HTTP HCM path.
PROTOCOL_UDP
3
PROTOCOL_UDP marks a datagram mesh service, reached through the UDP floor (proposal 018, Phase 3b): a udp_proxy capture listener forwarding to the backend's application UDP port. SECURITY NOTE: the UDP floor carries datagrams in PLAINTEXT. mTLS is a TCP/TLS construct and there is no DTLS, so a PROTOCOL_UDP service gets neither encryption nor peer authentication on the mesh hop. This is the one protocol for which that is true. It also means a UDP service's endpoints cannot be liveness-probed at their application port the way the other two are: a TCP connect to a UDP port always fails. Health for these endpoints comes from the mesh inbound hop instead — see NewAppHealthProbeCluster. Registering a UDP-only workload as PROTOCOL_TCP to get past that gap is what made every such backend permanently UNHEALTHY, and every datagram to it silently discarded (#931).