CoreDNS ist einer der unbesungenen Helden in Kubernetes. Es ist in fast jedem Kubernetes Setup zu finden und verrichtet seine Aufgaben unbemerkt und zuverlässig. Auch in NETWAYS Managed Kubernetes® ist es zu finden.
Daher war ich vor kurzem im Rahmen der Certified Kubernetes Administrator Prüfung überrascht, plötzlich selbst mit CoreDNS interagieren zu müssen. Grund genug, dessen Rolle in Kubernetes einmal etwas genauer unter die Lupe zu nehmen!
Was ist CoreDNS?
CoreDNS beschreibt sich auf seiner Website als DNS Server, geschrieben in Go. Seine Flexibilität erlaubt den Einsatz in verschiedensten Umgebungen, unter Anderem in Kubernetes. Es bietet Service Discovery basierend auf etcd, Kubernetes und den DNS-Lösungen der großen Cloudprovider, und ist durch sein Pluginsystem schnell und flexibel.
Serverblocks
Die grundlegende Einteilung in verschiedene Routingblöcke bilden in CoreDNS sogenannte Server Blocks. Diese sehen wie folgt aus:
coredns.io:5300 {
file db.coredns.io
}
example.io:53 {
log
errors
file db.example.io
}
example.net:53 {
file db.example.net
}
.:53 {
kubernetes
forward . 8.8.8.8
log
errors
cache
}HCLFür jeden in einem Server Block definierten Port erstellt CoreDNS einen Server, der die eingehenden DNS-Abfragen der Konfiguration entsprechend an den passenden Server Block weiterreicht. Das folgende Schaubild visualisiert die Server Blocks aus dem Beispiel aus CoreDNS‘ Sicht.

Hat CoreDNS die eingehende DNS-Abfrage einem Server Block zugeordnet, übernehmen die im jeweiligen Serverblock definierten Plugins die weitere Verarbeitung der Abfragen.
Plugins in CoreDNS
Die Vielzahl an Plugins bildet die Basis des DNS-Servers: Sie werden zur Buildtime in das ausführbare Programm eingebaut und stellen jegliche Funktionalität bereit. In Version 1.12.2 besteht die Binary für macOS beispielsweise aus 55 Plugins:
$ coredns -version
CoreDNS-1.12.2
darwin/arm64, go1.24.4,
$ coredns -plugins | wc -l
55BashDiese Plugins werden gechained, also quasi in Reihe geschaltet. Die Reihenfolge wird hierbei zur Buildtime durch eine Datei namens plugin.cfg vorgegeben. Die Version für die offiziell veröffentlichten Binaries findet sich auf GitHub.
Daraus ergibt sich, dass bei Hinzunahme weiterer Plugins ein Neubau des Programms inklusive eventuell notwendiger Anpassungen in plugin.cfg nötig wird.
Verhalten von Plugins in CoreDNS
Die verschiedenen Plugins erfüllen unterschiedliche Rollen und verhalten sich je nach Situation unterschiedlich. Für jede von CoreDNS empfangene DNS-Abfrage kann ein Plugin eine dieser vier Reaktionen zeigen:
- Verarbeitung der Abfrage: Das Plugin verarbeitet die Abfrage, generiert die Antwort entsprechend der Funktion des Plugins, und sendet sie zurück an den Client.
- Ignorieren der Abfrage: Stellt ein Plugin fest, dass es nicht für eine Abfrage zuständig ist, kann es diese auch ignorieren. In diesem Fall geht die Abfrage an das nächste Plugin der Pluginchain. Ist die Abfrage am Ende der Pluginchain angekommen und wird weiterhin ignoriert, antwortet CoreDNS dem Client mit
SERVFAIL. - Verarbeitung der Abfrage mit Fallthrough: Grundsätzlich verhält sich das Plugin hier wie bei einer normalen Verarbeitung der Abfrage. Ist die durch das Plugin generierte Antwort allerdings nicht zufriedenstellend (z.B.
NXDOMAIN), kann die Abfrage auch hier an das nächste Plugin der Pluginchain weitergegeben werden. - Verarbeitung der Abfrage mit Hinweis: Nicht jedes Plugin ist dafür zuständig, eine Antwort auf eine Abfrage zu generieren. Ein Beispiel hierfür ist das prometheus Plugin, das Metriken für Prometheus generiert. Es inspiziert die eingehende Abfrage, gibt diese aber immer an das nächste Plugin der Pluginchain weiter.
Zusätzlich gibt es sogenannte Unregistered Plugins, die sich nicht mit DNS-Abfragen befassen, sondern das Verhalten von CoreDNS selbst beeinflussen: bind, root, health und ready.
Nach dieser Einführung in die Funktionsweise von CoreDNS ist es nun an der Zeit, sich CoreDNS im Kubernetes-Kontext einmal genauer anzuschauen.
CoreDNS in Kubernetes
Für die folgenden Betrachtungen und Experimente nutze ich KinD, eine standardisierte Möglichkeit, ein Kubernetes Cluster lokal auf Docker aufzusetzen. Wenn du den Beispielen folgen möchtest, musst du diese Tools also auch auf deiner lokalen Maschine installieren.
Cluster Setup
Zuerst muss natürlich ein Cluster aufgesetzt werden. Das geschieht durch einen einzelnen KinD-Befehl, gefolgt von 1-3 Minuten Wartezeit:
kind create cluster --name coredns-labBashIst das Cluster eingerichtet, kann man auch schon CoreDNS entdecken:
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-674b8bbfcf-rdq5v 1/1 Running 0 102s
coredns-674b8bbfcf-rr22p 1/1 Running 0 102s
etcd-coredns-lab-control-plane 1/1 Running 0 109s
kindnet-k9cb4 1/1 Running 0 102s
kube-apiserver-coredns-lab-control-plane 1/1 Running 0 109s
kube-controller-manager-coredns-lab-control-plane 1/1 Running 0 109s
kube-proxy-r6q84 1/1 Running 0 102s
kube-scheduler-coredns-lab-control-plane 1/1 Running 0 110sBashGut versteckt im kube-system Namespace verrichtet es neben anderen fundamentalen Workloads wie etcd, API-Server und Scheduler seinen Dienst. Doch welchen genau?
Um diese Frage zu beantworten, können wir uns die CoreDNS Konfiguration einmal genauer anschauen. In Kubernetes ist diese normalerweise als ConfigMap mit dem Namen coredns ebenfalls im Namespace kube-system hinterlegt.
Der CoreDNS Corefile in Kubernetes
kubectl get configmap -n kube-system coredns -o yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30 {
disable success cluster.local
disable denial cluster.local
}
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-09T14:38:11Z"
name: coredns
namespace: kube-system
resourceVersion: "226"
uid: b59a1656-04df-40bd-ae3c-b765dd184ba0BashUnter data in der Ausgabe finden wir einen einzigen Eintrag mit dem Namen Corefile, der die CoreDNS Konfiguration beinhaltet. Im Corefile sehen wir die Definition eines einzigen Serverblocks (.:53), der sämtlche Anfragen auf dem Standardport annimmt. Die definierten Plugins mit entsprechenden Aufgaben sind für die Verarbeitung der eingehenden DNS-Abfragen zuständig.
Die Plugins errors, health, ready, prometheus, cache, loop, reload und loadbalance sind hierbei hauptsächlich für die Konfiguration von CoreDNS selbst verantwortlich. Sie stellen zum Beispiel Health- und Readiness-Endpoints für die Abfrage durch Kubernetes bereit, erlauben das Loggen von Fehlermeldungen, oder ermöglichen das Neuladen von Konfiguration ohne Neustart von CoreDNS.
Der tatsächlich für DNS-Abfragen relevante Teil der CoreDNS-Konfiguration in Kubernetes ist – wer hätte es gedacht – das kubernetes Plugin.
Das kubernetes Plugin
Die Konfiguration des kubernetes Plugins innerhalb des catch-all Server Blocks ermöglicht die Auflösung von Service- und Podadressen in Kubernetes. Schauen wir uns diesen Teil des Corefiles also noch einmal genauer an.
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}BashDas Plugin ist so konfiguriert, dass es für DNS-Abfragen für die Domain cluster.local (das Standard-DNS-Suffix für Kubernetes Cluster) zuständig ist. Darüber hinaus versucht es, Reverse DNS-Abfragen für IPv4 (in-addr.arpa) und IPv6 (ip6.arpa) aufzulösen.
Im eigentlichen Konfigurationsblock des kubernetes Plugins sehen wir dann drei weitere Einstellungen:
pods insecure: Erlaubt Reverse DNS-Abfragen für sämtliche Pods, ohne Verifizierung, ob der gewünschte Pod tatsächlich existiert oder die IP anderweitig vergeben ist. Dieses Feature ist hauptsächlich als Rückwärtskompatibilität zu kube-dns gedacht. In der Praxis antwortet CoreDNS hierbei immer mit der in der Abfrage enthaltenen IP-Adresse:10.244.0.3.kube-system.pod.cluster.local IN A 10.244.0.3fallthrough in-addr.arpa ip6.arpa: Für den Fall, dass ein Pod eine Reverse DNS-Abfrage für Dienste außerhalb des Clusters vornehmen möchte, ist ein Fallthrough definiert. Die DNS-Abfrage geht in diesem Fall an das nächste Plugin der Plugin-Chain. Andernfalls würde daskubernetesPlugin mitNXDOMAINantworten.
Im Fall unseres Corefiles wäre das nächste Pluginforward, das einen Lookup anhand derresolv.confversuchen würde.ttl 30: Für erfolgte Abfragen wird die Time to Live auf 30 Sekunden gesetzt. Das ist ein guter Kompromiss aus sinnvollem Caching und kurzen Reaktionszeiten, sollten sich Services oder Pods ändern.
Darüber hinaus gibt es weitere Konfigurationsmöglichkeiten – beispielsweise könnte CoreDNS auch außerhalb eines Clusters laufen und sich via API-Endpoint für Namensauflösungen mit diesem verbinden. Auch die Eingrenzung der DNS-Auflösungen auf einzelne Objekte oder Namespaces ist möglich. Eine vollständige Liste der Konfigurationsmöglichkeiten findet sich in der Dokumentation des kubernetes Plugins.
Beispiel 1: Hinzufügen einer weiteren Cluster-Domain
Wie im letzten Absatz bereits erwähnt, ist das Standard-DNS-Suffix für Kubernetes Cluster cluster.local. Dieses lässt sich bei Clusterinstallation für viele Kubernetes Distributionen anpassen. Hat man das vergessen oder möchte aus anderen Gründen ein weiteres gültiges Suffix einführen, geht das ganz einfach durch Anpassung des Corefiles im Cluster.
Zuerst öffnen wir die ConfigMap mit dem Corefile im Editierungsmodus:
kubectl edit configmap -n kube-system corednsBashIm Anschluss fügen wir ein neues Suffix my.cluster zum kubernetes Block hinzu:
kubernetes my.cluster cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}BashDa das reload Plugin ebenfalls konfiguriert ist, sollte CoreDNS die Konfiguration automatisch neu laden. Der Reload wird geloggt, wir können also zuschauen, wann die neue Konfiguration greift:
kubectl logs -n kube-system deploy/coredns -f
Found 2 pods, using pod/coredns-674b8bbfcf-rdq5v
maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
.:53
[INFO] plugin/reload: Running configuration SHA512 = 1b226df79860026c6a52e67daa10d7f0d57ec5b023288ec00c5e05f93523c894564e15b91770d3a07ae1cfbe861d15b37d4a0027e69c546ab112970993a3b03b
CoreDNS-1.12.0
linux/arm64, go1.23.3, 51e11f1
[INFO] Reloading
[INFO] plugin/reload: Running configuration SHA512 = cba5a092f893ab79c6f781e049eefe86ec640a8826a0df31b100ec96f4e446c6be8b2c8c7f6aea6ddebb4228cd022a7aacbc93ef7a0d38082dca4bb9d308c6fe
[INFO] Reloading completeBashIst der Reload erfolgt, sollten wir in der Lage sein, bspw. die Kubernetes API jetzt auch unter kubernetes.default.svc.my.cluster auflösen zu können:
kubectl run test-pod --image nginx
kubectl exec -it test-pod -- curl -v https://kubernetes.default.svc.my.cluster
* Trying 10.96.0.1:443...
* Connected to kubernetes.default.svc.my.cluster (10.96.0.1) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
command terminated with exit code 60BashDie DNS-Abfrage funktioniert. Die IP des Kubernetes Services wird korrekt aufgelöst.
Beispiel 2: Beschränkung des DNS-Services auf einzelne Namespaces
Für das zweite Beispiel wollen wir die Auflösung von DNS-Abfragen im Cluster auf den Namespace default beschränken. Auf diese Weise kann bspw. der Service der Kubernetes API weiterhin aufgelöst werden, während Abfragen für Dienste in anderen Namespaces fehlschlagen.
Hierzu editieren wir erneut den Corefile von CoreDNS und fügen der Konfiguration des kubernetes Plugins einen namespaces Eintrag hinzu.
kubectl edit configmap -n kube-system corednsBashkubernetes my.cluster cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
namespaces default
}BashWir können erneut zuschauen, wie die Konfiguration von CoreDNS neu geladen wird:
kubectl logs -n kube-system deploy/coredns -fBashIm Anschluss können wir erneut mit unserem test-pod die Wirksamkeit der Konfiguration testen:
kubectl exec -it test-pod -- curl -v https://kubernetes.default.svc.my.cluster
* Trying 10.96.0.1:443...
* Connected to kubernetes.default.svc.my.cluster (10.96.0.1) port 443 (#0)
...
kubectl exec -it test-pod -- curl -v https://kube-dns.kube-system.svc.my.cluster
* Could not resolve host: kube-dns.kube-system.svc.my.cluster
* Closing connection 0
curl: (6) Could not resolve host: kube-dns.kube-system.svc.my.cluster
command terminated with exit code 6BashWie erwartet kann der kubernetes Service weiterhin aufgelöst werden, da er sich im Namespace default befindet. Der Service kube-dns im Namespace kube-system hingegen kann nun nicht mehr aufgelöst werden.
Fazit
CoreDNS verrichtet in nahezu jedem Kubernetes-Cluster seine Arbeit leise und zuverlässig. So zuverlässig, dass man es im Alltag oft kaum wahrnimmt. Doch gerade in dieser Unauffälligkeit liegt seine Stärke: Es bildet das Rückgrat für DNS-Auflösungen im Cluster und ermöglicht damit essenzielle Funktionen wie Service Discovery und Kommunikation zwischen Pods und Services.
Dieser Blogpost zeigt, dass sich ein genauer Blick auf CoreDNS lohnen kann. Nicht nur zur Vorbereitung auf Zertifizierungen wie den CKA, sondern vor allem, um das Verhalten des eigenen Clusters besser zu verstehen und gezielt zu optimieren. Egal ob zusätzliche Cluster-Domains, Einschränkungen auf bestimmte Namespaces oder das Tuning des DNS-Caches: CoreDNS bietet dank seines modularen Aufbaus und der Plugin-basierten Architektur eine beeindruckende Flexibilität.
Wenn du noch mehr rund um CoreDNS ausprobieren oder nachlesen möchtest, ist hier noch einmal der Link zur CoreDNS Dokumentation. Und wenn diese Ressourcen nicht ausreichen oder noch Fragen offen sind, stehen unsere MyEngineers® dir jederzeit mit Rat und Tat zur Seite.





0 Kommentare