
Vor nicht allzu langer Zeit haben wir Kubernetes 1.9 auf AWS mittels Kops gestartet. Gestern, während des sanften Rollouts neuer Traffic auf einem unserer größten Kubernetes-Cluster, begann ich ungewöhnliche DNS-Namensauflösungsfehler zu bemerken, die von unserer Anwendung protokolliert wurden.
Auf GitHub wurde schon lange darüber , daher habe ich beschlossen, mir das auch anzuschauen. Letztendlich stellte ich fest, dass dies in unserem Fall durch eine erhöhte Last auf kube-dns und dnsmasq. Am interessantesten und neu für mich war die Ursache für den signifikanten Anstieg des DNS-Anfragenverkehrs. Darüber und darüber, was man dagegen tun kann, handelt mein Post.
Die DNS-Auflösung innerhalb des Containers — wie in jedem Linux-System — wird durch die Konfigurationsdatei /etc/resolv.confbestimmt. Standardmäßig lautet die dnsPolicy dieses ClusterFirst, was bedeutet, dass jede DNS-Anfrage an dnsmasqumgeleitet wird, die in einem Pod kube-dns innerhalb des Clusters läuft, der wiederum die Anfrage an die Anwendung kube-dnsweiterleitet, wenn der Name mit dem Cluster-Suffix endet, oder ansonsten an einen DNS-Server höheren Niveaus.
Die Datei /etc/resolv.conf Innerhalb jedes Containers sieht die Standardkonfiguration so aus:
nameserver 100.64.0.10
search namespace.svc.cluster.local svc.cluster.local cluster.local
eu-west-1.compute.internal
options ndots:5Wie man sehen kann, gibt es hier drei Direktiven:
- Der Nameserver ist die IP des Dienstes
kube-dns - Es sind 4 lokale Suchdomains angegeben
search - Es gibt die Option
ndots:5
Ein interessanter Teil dieser Konfiguration ist, wie lokale Suchdomains und Einstellungen ndots:5 koexistieren. Um das zu verstehen, muss man sich ansehen, wie die DNS-Auflösung für unvollständige Namen funktioniert.
Was ist ein vollqualifizierter Name?
Ein vollqualifizierter Name ist ein Name, für den keine lokale Suche durchgeführt wird, und der Name wird während der Namensauflösung als absolut betrachtet. Nach Vereinbarung betrachtet die DNS-Software einen Namen als vollqualifiziert, wenn er mit einem Punkt (.) endet, und als nicht vollqualifiziert, wenn nicht. Das heißt, google.com. ist vollqualifiziert, während google.com es nicht ist.
Wie wird ein unvollständiger Name verarbeitet?
Wenn eine Anwendung sich mit einem Remote-Host verbindet, der im Namen angegeben ist, erfolgt die DNS-Namensauflösung normalerweise über einen Systemaufruf, z. B. getaddrinfo(). Wenn der Name jedoch unvollständig ist (nicht mit . endet), stellt sich die interessante Frage, ob der Systemaufruf zunächst versucht, den Namen als absolut aufzulösen oder zuerst durch die lokalen Suchdomains geht. Das hängt von der Option ndots.
ab. resolv.conf:
ndots:n
legt den Schwellenwert für die Anzahl der Punkte fest, die im Namen enthalten sein müssen, bevor eine erste absolute Abfrage durchgeführt wird. Der Standardwert für n beträgt 1, was bedeutet, dass, wenn der Name Punkte enthält, dieser zuerst als absoluter Name ausprobiert wird, bevor ihm Suchlisten-Elemente hinzugefügt werden.Das bedeutet, dass, wenn für ndots der Wert 5 festgelegt ist und der Name weniger als 5 Punkte enthält, der Systemaufruf versuchen wird, ihn nacheinander aufzulösen, indem er zunächst alle lokalen Suchdomains durchläuft und im Falle eines Misserfolgs schließlich versucht, ihn als absoluten Namen aufzulösen.
Warum kann ndots:5 die Leistung der Anwendung negativ beeinflussen?
Wie Sie sehen, wenn Ihre Anwendung viel externen Verkehr nutzt, wird für jede hergestellte TCP-Verbindung (oder genauer gesagt, für jeden aufgelösten Namen) es 5 DNS-Anfragen auslösen, bevor der Name korrekt aufgelöst wird, da es zuerst 4 lokale Suchdomains durchlaufen wird und am Ende eine Abfrage zur Auflösung des absoluten Namens abgibt.
Im folgenden Diagramm ist der Gesamtraum in unseren 3 kube-dns Modulen vor und nach der Umstellung mehrerer Hostnamen, die in unserer Anwendung konfiguriert sind, auf vollständig qualifizierte Namen dargestellt.

Im folgenden Diagramm ist die Verzögerung der Anwendung vor und nach der Umstellung mehrerer Hostnamen, die in unserer Anwendung konfiguriert sind, auf vollständige Namen dargestellt (die vertikale blaue Linie ist das Deployment):

Lösung #1 – Verwendung vollständiger Namen
Wenn Sie nur wenige statische externe Namen (d. h. in der Anwendungs-Konfiguration definiert), zu denen Sie eine große Anzahl an Verbindungen herstellen, ist es möglicherweise die einfachste Lösung, sie auf vollständig qualifizierte Namen umzustellen, indem Sie einfach . am Ende hinzufügen.
Dies ist keine endgültige Lösung, hilft aber schnell, auch wenn nicht perfekt, die Situation zu verbessern. Diesen Patch haben wir angewendet, um unser Problem zu lösen, dessen Ergebnisse in den obigen Screenshots gezeigt wurden.
Lösung #2 – Anpassung ndots in dnsConfig
In Kubernetes 1.9 wurde ein in Alpha-Modus eingeführtes Feature (Beta-Version v1.10), das eine bessere Steuerung der DNS-Parameter über die Eigenschaften des Pods in dnsConfig. Unter anderem ermöglicht es, den Wert ndots für einen bestimmten Pod zu konfigurieren, d. h.
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsConfig:
options:
- name: ndots
value: "1"Quellen
Lesen Sie auch andere Artikel in unserem Blog:
Quelle: habr.com
