Conditional DNS forwarding,
the Kubernetes way.
Define DNS forwarding routes as Kubernetes resources. ZoneRoute renders them for CoreDNS and publishes them into a single ConfigMap key — without taking ownership of your CoreDNS deployment.
apiVersion: dns.mihnk.org/v1alpha1
kind: ZoneRoute
metadata:
name: corporate
spec:
zones:
- company.local
upstreams:
- address: 10.10.10.53
- address: 10.10.10.54
port: 5353Why ZoneRoute
Declarative Kubernetes API
A ZoneRoute names the zones and an ordered list of upstream resolvers. The API server validates addresses and rejects duplicate zones before the controller ever sees the object.
Deterministic rendering
The same set of routes always renders the same bytes, in the same order, whatever order the objects arrive in.
Deterministic ownership
When two routes claim one zone, the older one wins, and equal timestamps fall back to name order. The loser is told which route owns the zone and why.
Zones CoreDNS already serves are left alone
A zone already served by the Corefile or another *.server file is not taken over. Parent and child zones are separate claims, so company.local and eu.company.local can belong to different routes.
Least-privilege controller
The controller may patch exactly one ConfigMap. It cannot create ConfigMaps, cannot touch the Corefile, and has no access to Secrets, Pods or Deployments.
How it works
ZoneRoute writes one key. CoreDNS picks it up through an import the administrator establishes once, and nothing else in the cluster changes.
- ZoneRoutea Kubernetes resource
- Controllerresolves conflicts, renders the fragment
- kube-system/coredns-customdata["zoneroute.server"]
- CoreDNSimports custom/*.server
- Upstream resolveranswers for the zone
ZoneRoute owns
- Watches ZoneRoute resources
- Reads kube-system/coredns
- Reads and watches kube-system/coredns-custom
- Writes only data["zoneroute.server"]
- Does not create coredns-custom
- Does not edit the Corefile
- Does not edit the CoreDNS Deployment
- Does not verify that upstreams are reachable
You own
- The CoreDNS Deployment
- The Corefile integration
- The lifecycle of coredns-custom
- Every other key in coredns-custom
- Network connectivity to the upstream resolvers
Built to be boring in production
What the repository verifies before a release is cut. Nothing here is aspirational.
- Functional end-to-end tests against real CoreDNS on Kubernetes, on every pull request
- Multi-replica CoreDNS convergence
- Least-privilege RBAC verified in-cluster
- Deterministic rendering, independent of input order
- Controller restart and idempotency coverage
- linux/amd64 and linux/arm64 images
- Installation manifest pinned to the image digest
- SBOM and build provenance attached to every release
Quick start
kubectl apply -f https://github.com/mihnk/zoneroute/releases/latest/download/install.yamlThat installs the CRD, the namespace, the RBAC and the controller. CoreDNS wiring is a separate, one-time step — the controller never edits CoreDNS itself. SeeCoreDNS wiring, thenInstallation for the rest.
Accepted and Published
- Accepted
- The route is logically accepted: valid, not reserved, and in conflict with nothing.
- Published
- The fragment was written to the integration point and the expected import was found in the Corefile.
Published=True does not mean DNS is proven healthy end to end. It does not prove CoreDNS reloaded, that the mount is healthy, or that an upstream answers. Those are verified by asking DNS — see Troubleshooting.
Compatibility
Kubernetes 1.31 or newer, for the CEL IP library the CRD validates addresses with. CoreDNS 1.7.0 or newer, for the reload plugin that notices changes in imported files.
| Environment | Status | Why |
|---|---|---|
| kind and kubeadm-style CoreDNS | Validated | exercised by the end-to-end suite on every pull request |
| AKS | Design-compatible | the published layout satisfies the contract; not validated here |
| Gardener | Design-compatible | the published layout satisfies the contract; not validated here |
| EKS with the managed add-on | Unverified | the add-on owns the Corefile and the Deployment |
| GKE with kube-dns | Unsupported | no CoreDNS, so there is no integration point |
Validated means the repository contains a repeatable check. Design-compatiblemeans the platform's published CoreDNS layout appears to satisfy the contract, but nothing here verifies it. Unverified and unsupported mean what they say.
Read the documentation
Installation, the CoreDNS integration contract, and a reason-by-reason troubleshooting guide.