Veröffentlicht am

Kubernetes DNS fehlgeschlagen: CoreDNS, ndots

Teilen:
Authors

Kubernetes DNS fehlgeschlagen: CoreDNS, ndots, Policy

TL;DR

Funktioniert kubectl, und Pods laufen, aber ein Name löst sich nicht auf, liegt es fast nie am Anwendungs-Image. Zuerst, ob CoreDNS selbst läuft, und was der Pod als Resolver hat:

kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl exec POD -c CONTAINER -- cat /etc/resolv.conf

nameserver muss das ClusterIP von kube-dns im Namespace kube-system sein. search enthält den Namespace und svc.cluster.local. ndots:5 sorgt dafür, dass kurze Namen zuerst mit diesen Suffixen probiert werden. Die Pod-Status, wenn der Prozess gar nicht startet: Pod startet nicht.

CoreDNS ist der Resolver

Zwei Replicas, beide Running. Einer auf CrashLoop, und jeder zweite Lookup scheitert, weil der Service beide Pods trifft. Dann ist das DNS-Problem ein CrashLoopBackOff von CoreDNS. Logs dieses Pods lesen, nicht die der Anwendung.

kubectl get svc kube-dns -n kube-system
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50

Das ClusterIP aus dem Service und der nameserver in resolv.conf müssen übereinstimmen. Tun sie das nicht, hat etwas die resolv.conf des Pods überschrieben (dnsPolicy oder ein eigenes dnsConfig). Default dnsPolicy: ClusterFirst ist das Richtige für Workloads, die Cluster-Namen brauchen.

Name zu lang, ndots, Suchliste

Ein Service api im Namespace prod heißt vollständig api.prod.svc.cluster.local. Aus einem Pod in prod reicht api. Aus einem anderen Namespace reicht api.prod.

ndots:5 bedeutet: ein Name mit weniger als fünf Punkten wird zuerst an jeden Search-Suffix gehängt. api.example.com hat nur zwei Punkte, also fragt der Pod zuerst api.example.com.prod.svc.cluster.local und erst danach den eigentlichen Namen. Das ist korrekt und langsam, und es scheitert laut, wenn CoreDNS die internen Versuche mit SERVFAIL beantwortet statt mit NXDOMAIN. Ein FQDN mit abschließendem Punkt (api.example.com.) überspringt die Suchliste.

Interne Namen ohne Namespace sind der häufigere Fehler: die Anwendung ruft http://api:8080 und liegt nicht in dem Namespace, in dem api existiert. Der Fix ist der qualifizierte Name, nicht ein zweites CoreDNS.

NetworkPolicy schluckt UDP 53

Default-deny im Namespace blockt Egress, inklusive DNS. Der Pod startet, der Lookup hängt oder liefert connection timed out. TCP 53 allein reicht nicht. CoreDNS spricht UDP.

Eine Egress-Regel muss UDP und TCP Port 53 zum Namespace kube-system oder zum ClusterIP von kube-dns erlauben. Wer nur den eigenen Service freigibt, hat eine Anwendung, die gesund wirkt und keinen Namen auflöst. Dieselbe Policy erklärt einen Pod, der auf ContainerCreating durch ist und danach nichts erreicht.

Prüfen aus einem Debug-Pod im selben Namespace:

kubectl exec POD -- nslookup kubernetes.default.svc.cluster.local

kubernetes.default muss immer auflösen, solange CoreDNS gesund ist und die Policy es durchlässt. Scheitert schon dieser Name, ist die Anwendung nicht der Ort der Reparatur.

Quellen

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen