Introduction
ExternalDNS closes the gap between Kubernetes and DNS: instead of hand-editing zone files every time a Service or Ingress changes, the controller watches the API server and reconciles records with whichever DNS provider you run. It supports dozens of providers — Route 53, Cloudflare, Google Cloud DNS, Azure DNS, PowerDNS, RFC 2136 — through a single CRD-free interface.
What ExternalDNS Does
- Creates, updates, and deletes DNS records from Ingress, Service, and CRD objects
- Uses TXT ownership records so multiple clusters can share a zone safely
- Supports 40+ DNS providers via a pluggable backend interface
- Reconciles on a configurable interval (default 60s) with a
--onceCI mode - Integrates with cert-manager and Gateway API for end-to-end HTTPS automation
Architecture Overview
ExternalDNS is a single Go controller that subscribes to Kubernetes source events, builds a desired-state graph from annotations, and diffs it against what the provider has. Each provider implements Records(), ApplyChanges(), and AdjustEndpoints() — so adding Hetzner DNS or a private UltraDNS backend is a matter of a few hundred lines of Go. The TXT registry layer stores owner=cluster-x metadata on each record to prevent cross-cluster interference.
Self-Hosting & Configuration
provider=aws|google|cloudflare|azure|...selects the backenddomainFiltersrestrict which zones the controller will touchpolicy=sync|upsert-onlycontrols deletion behavior; default upsert-only is safesttxtOwnerIdtags records so multiple clusters can coexist in one zone- IAM credentials via IRSA (EKS), Workload Identity (GKE), or service principals (AKS)
Key Features
- First-class support for Ingress, Service type=LoadBalancer, and Gateway API HTTPRoute
- CRDs:
DNSEndpointlets any operator publish records without modifying source objects - Cloudflare proxy mode toggle via annotation
- Multi-target records (geo, weighted) where the provider supports them
- Metrics endpoint exposing reconcile counts, errors, and zone sizes
Comparison with Similar Tools
- cert-manager — complementary; cert-manager issues certs, ExternalDNS points DNS at them
- route53-kubernetes (deprecated) — AWS-only predecessor; superseded by ExternalDNS
- Terraform DNS modules — static, not reactive to cluster changes
- ingress-nginx annotations — no DNS automation built in
- Knative Net — includes its own DNS integration but tied to serverless
FAQ
Q: Can I scope it to one namespace?
A: Yes — --namespace flag restricts which sources the controller watches.
Q: What happens if two clusters manage the same record?
A: With unique txtOwnerId values each cluster only touches records it owns. Without them, they fight.
Q: Does it support wildcards?
A: Yes via external-dns.alpha.kubernetes.io/hostname: "*.foo.example.com" (provider-dependent).
Q: Is there a dry-run mode?
A: Set dryRun=true and the controller logs intended changes without applying them.