Ich habe heute ein Rätsel für dich. Wir führen einen kleinen Elasticsearch-Cluster mit drei Knoten auf Basis von CoreOS (2023.5.0 / Linux 4.19.25-coreos) unter Azure aus. Elasticsearch wird in einem Docker-Container im Host-Netzwerkmodus ausgeführt. Nachdem wir über ein Jahr lang nahezu wartungsfrei gelaufen sind, sind die Maschinen in einen sehr interessanten Zustand übergegangen.
Aktualisieren
Dieses Problem wurde durch eine Korrektur eines Treibers im Linux-Kernel behoben . Siehe Antwort unten.
Symptome
Grundsätzlich wird die Netzwerkverbindung zwischen der betroffenen Maschine und den beiden anderen Knoten unterbrochen. Alle befinden sich im selben virtuellen Netzwerk und im selben Subnetz und können in der Regel untereinander kommunizieren. Der betroffene Knoten kann weiterhin von anderen Subnetzen (in die ich ssh kann) und von einem anderen virtuellen Peer-Netzwerk aus erreicht werden. Die Maschine hat auch (sehr fleckige) Verbindung zum Internet, aber die meisten Anfragen haben nur eine Auszeit.
Wir haben festgestellt, dass auf einem betroffenen Knoten die Anzahl der von gemeldeten "verwendeten Sockets" /proc/net/sockstat
sehr hoch ist (~ 4,5 k statt ~ 300 auf einem fehlerfreien Knoten). Die Überwachung zeigt, dass diese Anzahl von dem Moment an, an dem der Knoten nicht mehr verfügbar ist, schnell ansteigt.
Das Schöne ist, dass wir die Quelle dieser verwendeten Sockel nicht zu identifizieren scheinen:
# cat /proc/net/sockstat
sockets: used 4566
TCP: inuse 2 orphan 0 tw 2 alloc 98 mem 4
UDP: inuse 1 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
# cat /proc/net/sockstat6
TCP6: inuse 98
UDP6: inuse 1
UDPLITE6: inuse 0
RAW6: inuse 1
FRAG6: inuse 0 memory 0
Davon abgesehen scheint die Maschine in Ordnung zu sein. Es werden keine verdächtigen Prozesse ausgeführt, die CPU-Auslastung ist minimal und es steht ausreichend Speicher zur Verfügung.
Das Pingen einer "nicht erreichbaren" VM im selben Subnetz hat zur Folge, dass ein paar EAGAIN
Antworten auf recvmsg
und dann ein Übergang zum Zurückkehren ENOBUFS
von erfolgen sendmsg
. Hier wird die Ping-Ausgabe gestrafft
Ich habe einige zusätzliche Ausgaben gesammelt (bevor irgendwelche Änderungen am System vorgenommen wurden) und in dieser Übersicht veröffentlicht: https://gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c
Analyse
Wir haben versucht, alles, was uns auf dem Server einfällt, herunterzufahren, wobei elasticsearch der erste Verdächtige ist. Durch das Herunterfahren des elasticsearch-Containers werden die verbrauchten Steckdosen jedoch nicht freigegeben. Das Gleiche gilt für alle CoreOS-bezogenen Prozesse (Update-Engine, Schlosser, ...) oder sogar für die gesamte Docker-Laufzeit oder für Azure-spezifische Dinge. Nichts schien zu helfen.
Aber jetzt wird es noch seltsamer: Wir haben versucht, tcpdump
auf der Maschine zu rennen, um zu sehen, was los ist. Und siehe da: Das Problem hat sich von selbst gelöst, die Konnektivität wurde wiederhergestellt. Unsere Theorie war, dass tcpdump einen Systemaufruf ausführt, der das Problem löst. Wir haben tcpdump mit gdb ausgeführt und bei allen Systemaufrufen Haltepunkte gesetzt. Nachdem wir eine Menge von Haltepunkten durchlaufen hatten, stellten wir schließlich fest, dass das Setzen des Promiscous-Modus für den Capturing-Socket (speziell diese Zeile in libpcap ) den Zähler der verwendeten Sockets zurücksetzt und uns in einen normalen Zustand versetzt.
Zusätzliche Erkenntnisse
- Wir haben überprüft, dass das Ausführen
tcpdump
mit dem-p/--no-promiscuous-mode
Flag den Zähler für die verwendeten Sockets nicht löscht und die Maschine in einen verwendbaren Zustand zurückversetzt. - Running
ifconfig eth0 txqueuelen 1001
setzt den Zähler der verwendeten Sockets zurück, die Konnektivität wird jedoch nicht wiederhergestellt. - Das manuelle Einstellen des Promisc-Modus mit
ip link set eth0 promisc on
stellt die Konnektivität nicht wieder her.net.ipv4.xfrm4_gc_thresh
ist auf 32768 eingestellt und ein geringfügiges Erhöhen behebt das Problem nicht.
Wir sind mit Azure in Kontakt getreten, die ebenso verblüfft sind wie wir. Ich verstehe, dass dies wahrscheinlich nicht das Problem ist, sondern nur ein Symptom. Aber es ist das einzige Greifbare, das ich bisher gefunden habe. Meine Hoffnung ist, dass ich durch das Verstehen des Symptoms näher an die Grundursache herankomme. Die Netzwerkschnittstellen in Azure werden mit diesem Netzwerktreiber ausgeführt .
Vielleicht ist CoreOS / Kernel schuld?
Aus zeitlicher Sicht begannen die Probleme am 11.03.2019, dem Tag, an dem CoreOS automatisch auf die neueste Version aktualisiert wurde. Dieses Update enthielt laut Release Notes ein Kernel-Update von 4.15.23 auf 4.19.25 . Ich gehe immer noch die Änderungsprotokolle durch, um zu sehen, ob dort irgendetwas ein Problem sein könnte. Bisher habe ich nur festgestellt, dass der Hyperv-Netzwerktreiber in den letzten Monaten einige Updates erhalten hat , von denen anscheinend nicht alle Teil von 4.19.25 sind. Das Patchset, das CoreOS auf 4.19.25 angewendet hat, ist nicht so beeindruckend , aber das Patch, das ein falsches nf_conntrack_ipv4-Modul einführt, ist neu.
Hilfe!
Bisher haben wir folgende Fragen:
Was könnte dazu führen, dass diese "Sockets used" -Metrik explodiert? Ich habe die Kernel-Quellen für diese Metrik durchgelesen und es scheint nur ein Zähler zu sein, der keinen Hinweis darauf gibt, welche Art von Sockets dies tatsächlich sind oder was sie hervorgebracht hat.
Warum hat die Nummer Flatline bei ca. 4,5k? Welches Limit würde das verursachen?
Hat sich zwischen Kernel 4.14.96 und 4.19.25 etwas Bedeutendes geändert?
Warum setzt der
setsockopt()
Aufruf in libpcap den Zustand zurück?
Verwandte CoreOS-Fehler: https://github.com/coreos/bugs/issues/2572
quelle
Antworten:
Zunächst einmal vielen Dank für die sehr gut geschriebene Frage!
Da der von Ihnen beschriebene Detaillierungsgrad sehr hoch ist und Sie sich bereits auf GDB-Ebene befinden, nehme ich an, dass meine Antwort für Sie keinen großen Nutzen haben wird. Wie auch immer, hier ist ein Versuch:
ss -ae
undlsof -n
?dmesg
in diesem Fall etwas Interessantes zurück?ip link set [interface] promisc on
) einstellen , wird das Problem dann auch behoben?Ich hoffe das hilft.
quelle
ss
,lsof
undnetstat
als von „Steckdosen verwendet“ in/proc/net/sockstat
. Nur die Gesamtanzahl (die scheinbar nur aus dieser Datei gelesen wird) ist gleich.iptables
Läuft, hat aber keine speziellen Regeln (siehe Übersicht). Ich habe nicht versucht, den Promiscous-Modus selbst einzustellen oder tcpdump kontinuierlich auszuführen. Werde das nächste Mal machen.ss -aepi
zu meiner Ausgabesammlung hinzugefügt : gist.github.com/privatwolke/… - Leider gibt dmesg in diesem Fall genau nichts zurück. Tatsächlich ist der letzte Eintrag vor dem Vorfall 5 Tage alt.dmesg / journalctl -k
Ausgabe hinzugefügt .ip link set eth0 promisc on
allein die Maschine nicht in einen verwendbaren Zustand zurückversetzt.xfrm4_gc_thresh - INTEGER
The threshold at which we will start garbage collecting for IPv4
destination cache entries. At twice this value the system will
refuse new allocations.
Soweit ich das beurteilen kann, hängt es mit IPsec zusammen, das hier aber auch nicht zu laufen scheint.Dies wurde durch einen Fehler im hv_netsvc-Treiber im Linux-Kernel verursacht. Wir konnten dieses Problem mit einem Microsoft-Entwickler lösen und haben es geschafft, das Update im Upstream anzuwenden.
Ich zitiere die Commit-Nachricht hier, da sie das Problem recht gut zusammenfasst:
Zum späteren Nachschlagen lautet das diesbezügliche Commit https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f .
quelle