Oft möchte man aus Kubernetes heraus auf einen eigenen, meist internen DNS-Server zugreifen. In Unternehmen könnte dies beispielsweise ein zentraler Datenbankserver sein. Vor allem zu Testzwecken kann das hilfreich sein. Aber auch im heimischen Umfeld bringen All-in-one-Router wie die Fritz! Box ihren eigenen DNS-Server mit. Soll von Kubernetes heraus ein solcher DNS-Name aufgelöst werden, geht das mit k3s aktuell leider noch schief.
Hart kodierter Cloudflare-DNS
Das Problem liegt in der CoreDNS-Konfiguration: Hier wurde ein DNS-Server von Cloudflare (1.1.1.1) hart kodiert hinterlegt. Dort landen alle Anfragen, die lokal vom Cluster nicht aufgelöst werden können. Der im Host gesetzte Upstream-DNS wird somit auch nicht automatisch gesetzt. Man kann die ConfigMap wie folgt einsehen:
kubectl get cm coredns -o yaml
Wie leicht zu erkennen ist, wird der Upstream mit der Zeile proxy . 1.1.1.1 angegeben:
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
proxy . 1.1.1.1
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
Eigenen DNS-Server einfügen
Um dies zu ändern, kann man entweder die ConfigMap direkt bearbeiten
kubectl edit cm coredns
Da ich den Workaround mit Ansible automatisieren wollte, habe ich die Konfiguration exportiert, mit sed den DNS-Server ersetzt und anschließend wieder importiert:
kubectl get cm -n kube-system coredns -o yaml | sed "s/proxy . 1.1.1.1/proxy . 192.168.0.19/g" > coredns-fixed.yml
kubectl apply -f coredns-fixed.yml
In diesem Beispiel wird der DNS-Server 192.168.0.19 eingefügt.
Offizieller Fix in Aussicht
Das Problem ist mittlerweile seit einigen Wochen bekannt. Vor wenigen Tagen wurde der Release-Candidate v0.3.0-rc3 veröffentlicht. Er ermöglicht es, den DNS-Server zu konfigurieren. Wahlweise per –resolv-conf Argument oder K3S_RESOLV_CONF Umgebungsvariable. Als Fallback dient der Google DNS-Server (8.8.8.8).