
Vor nicht allzu langer Zeit haben wir Kubernetes 1.9 auf AWS mit Kops gestartet. Gestern, während des sanften Rollouts des neuen Traffics auf einem unserer größten Kubernetes-Cluster, begann ich, ungewöhnliche DNS-Namensauflösungsfehler zu bemerken, die von unserer Anwendung protokolliert wurden.
Darüber wird schon seit einiger Zeit auf GitHub , daher wollte ich das auch genauer untersuchen. Letztendlich stellte ich fest, dass dies in unserem Fall durch eine erhöhte Last verursacht wurde kube-dns und dnsmasq. Am interessantesten und neu für mich war die Ursache des signifikanten Anstiegs der DNS-Anfragen. In meinem Beitrag erfährst du mehr darüber und was man dagegen tun kann.
Die DNS-Auflösung innerhalb eines Containers — wie in jedem Linux-System — wird durch die Konfigurationsdatei /etc/resolv.confbestimmt. Standardmäßig verwendet Kubernetes dnsPolicy dies ClusterFirst, was bedeutet, dass jede DNS-Anfrage an dnsmasqweitergeleitet wird, das in einem Pod läuft kube-dns innerhalb des Clusters, das wiederum die Anfrage an die Anwendung kube-dnsweiterleitet, wenn der Name mit dem Cluster-Suffix endet, oder andernfalls an einen übergeordneten DNS-Server.
Die Datei /etc/resolv.conf Innerhalb jedes Containers sieht das standardmäßig 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 Servername ist die IP des Dienstes
kube-dns - Es sind 4 lokale Suchdomänen angegeben
search - Es gibt eine Option
ndots:5
Ein interessanter Teil dieser Konfiguration ist, wie lokale Suchdomänen und Einstellungen ndots:5 zusammenarbeiten. Um dies 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 den Konventionen gilt ein DNS-Name 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 nicht vollqualifiziert ist.
Wie wird ein unvollständiger Name behandelt?
Wenn sich eine Anwendung mit einem Remote-Host verbindet, der im Namen angegeben ist, erfolgt die DNS-Namensauflösung normalerweise über einen Systemaufruf wie getaddrinfo(). Wenn jedoch der Name unvollständig ist (nicht auf . endet), stellt sich die interessante Frage, ob der Systemaufruf zuerst versucht, den Namen als absolut zu lösen, oder ob er zuerst die lokalen Suchdomänen durchläuft. Das hängt von der Option ab. ndots.
Aus dem Handbuch zu resolv.conf:
ndots:n
legt die Schwelle für die Anzahl der Punkte fest, die im Namen vorhanden sein müssen, bevor eine erste absolute Abfrage durchgeführt wird. Der Standardwert für n beträgt 1, was bedeutet, dass, wenn im Namen Punkte vorhanden sind, der Name zunächst als absoluter Name ausprobiert wird, bevor ihm Elemente aus der Suchliste 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 zuerst alle lokalen Suchdomänen durchläuft und, falls dies fehlschlägt, ihn schließlich als absoluten Namen auflösen wird.
Warum kann ndots:5 die Performance der Anwendung negativ beeinflussen?
Wie Sie wissen, erzeugt Ihre Anwendung, wenn sie viel externen Datenverkehr verwendet, für jede bestehende TCP-Verbindung (oder genauer gesagt, für jeden aufgelösten Namen) 5 DNS-Abfragen, bevor der Name korrekt aufgelöst wird, da sie zunächst durch 4 lokale Suchdomänen geht und schließlich eine Abfrage zur Auflösung des absoluten Namens ausgibt.
Die folgende Diagramm zeigt den Gesamtdatentransfer auf unseren 3 kube-dns Modulen vor und nach der Umstellung mehrerer Hostnamen, die in unserer Anwendung konfiguriert sind, auf vollständig qualifizierte Namen.

Die folgende Diagramm zeigt die Anwendungs-Latenz vor und nach der Umstellung mehrerer Hostnamen, die in unserer Anwendung konfiguriert sind, auf vollständige (die vertikale blaue Linie stellt das Deployment dar):

Lösung #1 – Verwendung von vollständig qualifizierten Namen
Wenn Sie nur wenige statische externe Namen haben (d. h. in der Konfiguration der Anwendung definiert), zu denen Sie zahlreiche Verbindungen herstellen, könnte die einfachste Lösung sein, diese auf vollständig qualifizierte Namen umzustellen, indem Sie einfach . am Ende hinzufügen.
Dies ist keine endgültige Lösung, hilft jedoch schnell, wenn auch nicht sauber, die Situation zu verbessern. Diese Anpassung haben wir angewendet, um unser Problem zu lösen, deren Ergebnisse oben in den Screenshots zu sehen sind.
Lösung #2 – Anpassung ndots in dnsConfig
In Kubernetes 1.9 wurde ein Funktionalität in Alpha eingeführt (Beta-Version v1.10), die es ermöglicht, die DNS-Einstellungen über die Pod-Eigenschaft besser zu steuern. dnsConfig. Unter anderem ermöglicht es die Anpassung des Wertes ndots für einen bestimmten Pod, 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
