Expand description
DNS-based dynamic upstream discovery (DW-042, feature analysis 4.4).
When an upstream configures dns_discovery, a background
DiscoveryTasks resolves the hostname via DNS (A or SRV records),
updates the upstream’s endpoint set in the UpstreamLb live, and
re-resolves when the record TTL expires (or at refresh_interval_s,
whichever comes first). Endpoint scale-up/down is reflected without a
restart — new connections use the updated set; existing connections
stay alive until they close.
§Resolution
DnsResolver wraps a hickory_resolver::TokioAsyncResolver. A
records are resolved to (IpAddr, ttl) pairs; SRV records to
(IpAddr, port, ttl) triples (the SRV target is resolved to an IP by
the resolver’s recursive lookup). The resolver is configured with the
SYSTEM resolver’s name servers when /etc/resolv.conf is readable
(so container-internal names resolve), and the public Google
resolvers otherwise.
§Refresh cycle
Each cycle: resolve, update the endpoint set, sleep
min(refresh_interval_s, record_ttl), repeat. On DNS failure:
fail_open: true keeps the last resolved set; fail_open: false
clears endpoints (the upstream answers 503 until DNS recovers). The
min_endpoints floor prevents shrinking below a configured minimum —
if a resolution yields fewer endpoints, the previous set is kept.
§Task lifecycle
DiscoveryTasks owns one [tokio::task::JoinSet] for every
discovery task. The operator (dwara-bin) calls
DiscoveryTasks::respawn after every snapshot swap (startup and
each reload): all previous tasks are aborted and new ones spawned for
the new generation’s upstreams. Dropping DiscoveryTasks (or
calling DiscoveryTasks::abort_all) aborts every task — the
graceful-shutdown path. This mirrors crate::dataplane::active::ActiveProbes (DW-013), the
closest precedent for a long-running dataplane task.
Consul watch and Kubernetes EndpointSlice watch are DEFERRED to a future milestone — DNS is the first discovery source.
Structs§
- Discovery
Tasks - Owns every DNS discovery task for the running generation. Call
DiscoveryTasks::respawnon startup and after every snapshot swap; dropping it (or shutdown) aborts all tasks. Mirrorscrate::dataplane::active::ActiveProbes(DW-013), the closest precedent for a long-running dataplane task. - DnsCache
- A TTL-cached async DNS resolver for the pooled dial path (PERF-05, #170).
- DnsResolver
- A TTL-aware DNS resolver wrapping
hickory_resolver::TokioResolver.