Skip to main content
Version: v3.9.0

DNS

Edgelet provides bridge-network service discovery for microservices on a single node. Behavior depends on containerEngine in config.

EngineMechanismAuthoritative resolver
edgelet (linux embed)Embedded DNS on bridge gateway + per-container resolv.conf / /etc/hostsYes: internal/dnsresolver
dockerUser-defined bridge edgelet + network aliases + ExtraHostsNo
podmanSame as docker (shared client)No

Zone: svc.bridge.local (default).

Bridge: Linux bridge edgelet0, CIDR 172.18.0.0/16, Docker/Podman network name edgelet.

See also: Container engines, Workload metadata, Local control plane, Bridge DNS for workload authors.


When DNS applies​

ModeBridgeService discovery
hostNetworkMode: falseWorkload joins edgelet bridgeAliases + (embed) resolver records
hostNetworkMode: trueHost networkNo bridge aliases; no embed resolv.conf mount

Host-network workloads use the host resolver directly.


FQDN catalog​

Reserved system names (managed scope)​

FQDNRole
edgelet.default.svc.bridge.localEdgelet node agent (bridge gateway)
router.default.svc.bridge.localRouter microservice
nats.default.svc.bridge.localNATS microservice

Per-workload names​

For application myapp and microservice worker:

FormExample
Short (bridge alias / in-zone)myapp.worker
FQDNmyapp.worker.svc.bridge.local
UUID aliasiofog_<uuid> and iofog_<uuid>.svc.bridge.local

The iofog_ prefix on UUID aliases is a stable token in resolver code; it is not related to legacy product naming elsewhere.

Control plane (three FQDNs)​

For metadata.namespace = default, metadata.name = pot:

#FQDN
1edgelet.controller.svc.bridge.local
2controller.default.svc.bridge.local
3default.pot.svc.bridge.local

Identity comes from manifest metadata. Not hardcoded "controller" as the microservice name. See Local control plane.

Compatibility aliases (optional, embed engine)​

When enabled, the embedded resolver also publishes:

  • host.docker.internal
  • host.container.internal

Controlled by resolver config (dnsCompatAliasesEnabled in status).


Embedded engine (containerEngine: edgelet)​

Linux only. Started from pkg/engine/edgelet when the CRI engine creates workloads.

Architecture​

┌─────────────────────────────────────────────────────────┐
│ Bridge edgelet0 (172.18.0.0/16) │
│ Gateway .1 ──► embedded DNS :53 (managed + local) │
│ │
│ Pod sandboxes ──► resolv.conf → gateway │
│ └── /etc/hosts (extraHosts + baseline) │
└─────────────────────────────────────────────────────────┘
│
│ out-of-zone queries
▼
host /etc/resolv.conf upstreams

Scopes (listener partitioning)​

Internal scope constants (internal/dnsresolver/resolver.go):

Scope constantLabel scopeListener
edgelet (managed)managed workloadsBridge gateway :53
iofog-local (local)local workloads (namespace: edgelet)Separate bind address on same bridge

Reconcile loop pulls live container state from containerd (runtimeDNSSnapshot) and upserts WorkloadRecord entries. Control plane rows are also upserted via internal/processmanager/controlplane_dns.go.

Record publication (aliasesForWorkload)​

For each active workload IP, the resolver answers A/AAAA for:

  • <app>.<name> (+ FQDN)
  • iofog_<uuid> (+ FQDN)
  • Control-plane extras when IsController
  • Reserved router/nats/agent names on managed scope
  • Optional docker compat hostnames

Inactive containers may return NXDOMAIN or policy denial depending on query type.

Per-container files (CRI create path)​

Non-host-network pods:

  1. resolv.conf. Nameserver = bridge gateway IP for workload scope
  2. /etc/hosts. User extraHosts plus baseline entries

Paths under Edgelet state dirs (see pkg/engine/edgelet/engine.go).

Forwarding​

Queries outside svc.bridge.local forward to upstreams parsed from the host /etc/resolv.conf, with backoff and health tracking (internal/dnsresolver/forwarding.go).

Persistence​

DNS workload snapshot: /var/lib/edgelet/dns/snapshot-v1.json (restore on startup).

Observability​

When containerEngine: edgelet, GET /v1/system/status includes DNS fields:

KeyMeaning
dnsStartedResolver running
dnsScopeManagedListening / dnsScopeManagedAddressManaged listener
dnsQueriesTotal, dnsSuccessTotal, dnsNXDomainTotal, dnsServFailTotalQuery outcomes
dnsForwardedTotal, dnsForwardErrTotal, dnsForwardingDegradedUpstream forwarding
dnsHealthDerived health (ok, degraded, stopped, ...)

CLI: edgelet system status (human or -o json).


Docker and Podman​

External engines do not start the embedded resolver. Discovery uses Docker networking primitives on the shared edgelet bridge.

Network selection​

All non-host workloads attach to network edgelet (pkg/docker/network.go). Application name does not select a different bridge. Scope is metadata-only.

Edgelet ensures the network exists at container create time.

Network DNS aliases​

Short names registered on the bridge endpoint (NetworkingConfig.EndpointsConfig):

dnsresolver.WorkloadBridgeNetworkAliases(application, name, isController)
WorkloadAliases (short)
General<application>.<name>
Control planeabove + edgelet.controller, controller.<namespace>

These resolve via Docker's embedded DNS on the edgelet network, not via svc.bridge.local unless the querying container uses FQDNs in /etc/hosts.

ExtraHosts (/etc/hosts)​

Docker path builds hostConfig.ExtraHosts:

  1. edgelet.default.svc.bridge.local:<hostIP>. Prepended unless user already mapped it (buildExtraHostsWithIoFog)
  2. router.default.svc.bridge.local:<routerIP>. When router IP known and workload is not the router
  3. nats.default.svc.bridge.local:<natsIP>. When NATS IP known
  4. User extraHosts from manifest (name:address or YAML struct)

Host-network mode: no ExtraHosts, no bridge network. NetworkMode: host.

Podman​

Podman uses the same docker-compatible client code paths (RuntimeEnginePodman in labels only).


Cross-engine parity rules​

  1. Same bridge name (edgelet) for all non-host workloads on docker/podman.
  2. Same alias function for docker/podman network aliases and embed resolver short names (application.name).
  3. Same reserved FQDN strings in ExtraHosts and embed resolver.
  4. Scope is label/env metadata. Not a separate bridge per scope on docker/podman.

Drift detection on docker compares expected network + alias policy against runtime inspect (see process manager reconcile).


Troubleshooting​

SymptomChecks
Name does not resolve (embed)edgelet system status → dnsStarted, dnsHealth; verify workload not host-network
Name does not resolve (docker)docker network inspect edgelet; container on network; aliases in inspect
Router/NATS unreachableSystem MS running; ExtraHosts populated; embed reserved records present
External name fails (embed)dnsForwardingDegraded; host /etc/resolv.conf upstreams
Control plane DNS wrongConfirm metadata.namespace / metadata.name; see FQDN table above

More: Troubleshooting.


Implementation map​

ComponentPackage / file
Embedded resolverinternal/dnsresolver/
CRI hooks (resolv, hosts)pkg/engine/edgelet/engine.go
Docker aliases + ExtraHostspkg/docker/container.go
Bridge network ensurepkg/docker/network.go, internal/network/
Control plane DNS upsertinternal/processmanager/controlplane_dns.go
Label-driven scopeinternal/workloadmeta/
Group 3See anything wrong with the document? Help us improve it!