Documentation
¶
Overview ¶
Package dns implements the per-node embedded DNS server (RUNE-063).
The agent serves an authoritative zone for `.rune` and forwards every other query to host upstream resolvers read from /etc/resolv.conf. Records are A only and resolve `<service>.<namespace>.rune` to the service's stable VIP allocated by the control plane (RUNE-040). TTL is intentionally short (5s) so dropped/replaced services are noticed quickly.
Bind addresses default to 127.0.0.123:53 (UDP+TCP). 127.0.0.123 is chosen rather than 127.0.0.53 because the latter is reserved by systemd-resolved on most Linux distributions and would conflict. Additional bind addresses (typically Docker bridge gateways) can be supplied at construction time so containers reach the DNS server through their own gateway IP.
The Subsystem implements the same Name / Start / Ready / Stop contract as the agent's other subsystems (see internal/agent), but does not import the agent package directly to avoid cycles.
Index ¶
Constants ¶
const ( // DefaultBindAddr is the loopback address the agent binds for // host-side DNS injection. Avoids systemd-resolved on .53. DefaultBindAddr = "127.0.0.123:53" // Zone is the authoritative zone (always trailing dot for miekg). Zone = "rune." // DefaultTTL is the TTL stamped on every answer. DefaultTTL uint32 = 5 // DefaultStaleBudget mirrors the dataplane: after this much time // without a refresh signal, the resolver returns SERVFAIL for // .rune queries instead of stale data. DefaultStaleBudget = 30 * time.Second )
Defaults.
Variables ¶
This section is empty.
Functions ¶
func ResolvConfUpstreams ¶
func ResolvConfUpstreams() func() []string
ResolvConfUpstreams returns an UpstreamProvider that re-reads /etc/resolv.conf on every call. Loopback servers (e.g. systemd-resolved) are filtered to avoid forwarding loops back into our own bind.
Types ¶
type Config ¶
type Config struct {
// Zone provides the in-zone resolutions. Required.
Zone ZoneProvider
// Freshness gates .rune answers; nil means always fresh.
Freshness Freshness
// BindAddrs are host:port pairs to bind. If empty, defaults to
// just DefaultBindAddr. Each address is bound on both UDP and TCP.
BindAddrs []string
// TTL stamped on answers; defaults to DefaultTTL.
TTL uint32
// StaleBudget; informational, used by callers to align with the
// dataplane budget. The Freshness interface is the actual gate.
StaleBudget time.Duration
// UpstreamProvider, if set, is consulted for the forwarder
// upstream list on every query. If nil, /etc/resolv.conf is
// parsed at Start and on each Refresh() call.
UpstreamProvider func() []string
// ForwardTimeout caps each upstream query; defaults to 2s.
ForwardTimeout time.Duration
// Logger; defaults to the global logger with component "dns".
Logger log.Logger
}
Config bundles the parameters for constructing a Subsystem.
type EndpointPublisher ¶
type EndpointPublisher struct {
// contains filtered or unexported fields
}
EndpointPublisher fans the orchestrator's endpoint + local-instance updates into the OrderedLog-backed publishers from pkg/networking/endpoints and pkg/networking/localinstances.
It implements the pkg/orchestrator/controllers.EndpointPublisher interface (kept loose-coupled to avoid an import cycle: this package only refers to pkg/types).
func NewEndpointPublisher ¶
func NewEndpointPublisher(olog orderedlog.OrderedLog, logger log.Logger) (*EndpointPublisher, error)
NewEndpointPublisher constructs an EndpointPublisher. Both underlying publishers are required.
func (*EndpointPublisher) PublishLocalInstances ¶
func (p *EndpointPublisher) PublishLocalInstances(ctx context.Context, nodeID string, table map[string]types.InstanceIdentity) error
PublishLocalInstances implements controllers.EndpointPublisher.
func (*EndpointPublisher) PublishService ¶
func (p *EndpointPublisher) PublishService(ctx context.Context, service *types.Service, eps []types.Endpoint) error
PublishService implements controllers.EndpointPublisher.
type Freshness ¶
type Freshness interface {
IsFresh() bool
}
Freshness reports whether the underlying state (orderedlog watch) is fresh enough to answer authoritatively. When false, .rune queries are answered with SERVFAIL.
func AlwaysFresh ¶
func AlwaysFresh() Freshness
AlwaysFresh returns a Freshness that always reports fresh.
func FreshnessFromDataplane ¶
FreshnessFromDataplane builds a Freshness implementation from any type that exposes an IsFresh() bool method (e.g. dataplane.Subsystem once it grows that accessor). When the supplied function is nil, the DNS server treats the data plane as always fresh — appropriate for dev/standalone mode.
type StoreZone ¶
type StoreZone struct {
// contains filtered or unexported fields
}
StoreZone is a ZoneProvider that resolves <svc>.<ns>.rune queries against the agent's store.Store. The VIP for a service is read from Service.Discovery.VIP (populated by RUNE-040).
Lookups are memoized for a short TTL to avoid hammering the store on bursts of repeated DNS queries from a single client.
func NewStoreZone ¶
NewStoreZone constructs a StoreZone with a 1s lookup cache.
type Subsystem ¶
type Subsystem struct {
// contains filtered or unexported fields
}
Subsystem is the per-node embedded DNS server.
func (*Subsystem) Ready ¶
func (s *Subsystem) Ready() <-chan struct{}
Ready returns a channel closed when the server has bound and is serving on at least one address.
func (*Subsystem) Refresh ¶
Refresh re-reads /etc/resolv.conf for upstream resolvers. Wire this to SIGHUP at the daemon level. Returns an error if no upstreams could be loaded; the previous list is retained on error.
type ZoneProvider ¶
type ZoneProvider interface {
// LookupA returns the IPv4 addresses for service `name` in
// namespace `ns`. ok=false means the service is not known.
LookupA(ns, name string) (ips []net.IP, ok bool)
}
ZoneProvider resolves an in-zone name to one or more A records. LookupA is called for every <service>.<namespace>.rune query the server receives.