CoreOS: tcpdump löst auf mysteriöse Weise Netzwerkprobleme (übermäßige Anzahl an verwendeten Sockets)

14

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/sockstatsehr 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 EAGAINAntworten auf recvmsgund dann ein Übergang zum Zurückkehren ENOBUFSvon 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, tcpdumpauf 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 tcpdumpmit dem -p/--no-promiscuous-modeFlag den Zähler für die verwendeten Sockets nicht löscht und die Maschine in einen verwendbaren Zustand zurückversetzt.
  • Running ifconfig eth0 txqueuelen 1001setzt 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 onstellt 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.

Steckdosen verwendet

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.

Update: Möglicher zugehöriger Incoming Kernel Patch?

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

Stephan Klein
quelle
Das offene Sockets ist ein resultierendes Problem, nicht das Stammproblem IMHO. Ich hatte dieses Verhalten auf einem Linux-System mit Macvlan-Geräten (mit eigenen Mac-Adressen) auf einem Bridge-Gerät. Durch das Setzen der Bridge auf promisc funktionierten die macvlan-Geräte. Ich kenne Coreos oder Azure nicht. Das Problem ist, dass eine darunter liegende Ebene nicht über die Mac-Adressen auf den oberen Ebenen informiert ist.
AndreasM
Danke für deinen Kommentar! Mir ist klar, dass eine hohe Anzahl von verwendeten Steckdosen nicht die Hauptursache ist. Ich klammere mich nur an die eine greifbare Sache, die ich als abnormal an der Maschine bezeichnen kann.
Stephan Klein
Hallo Stephan. Irgendwelche Neuigkeiten? Bitte melden 1) Ist WOL aktiviert? 2) Wird sysctl -w net.ipv4.route.flush = 1 aufgelöst? 3) Was ist der Arp-Cache in keinem Arbeitszustand? im Arbeitszustand?
Massimo

Antworten:

4

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:

  • Vermutlich hast du sowas schon probiert ss -aeund lsof -n?
  • Gibt es dmesgin diesem Fall etwas Interessantes zurück?
  • Verwenden Sie Iptables auf dem Server?
  • Wenn Sie den Promiscuous-Modus auf eine andere Weise als mit tcpdump (sagen wir, ip link set [interface] promisc on) einstellen , wird das Problem dann auch behoben?
  • Haben Sie nach verdächtigen Prozessen, Dateien oder anderen seltsamen Aktivitäten gesucht? Nur daran gedacht, dass vielleicht ein ungebetener Prozess in den Schatten lauert, die sich selbst verbergen, und verstummt, wenn der Promiscuous-Modus eingestellt ist?
  • Wenn Sie tcpdump im Hintergrund laufen lassen, wird dieses Problem erneut auftreten?

Ich hoffe das hilft.

Janne Pikkarainen
quelle
1
Danke für Ihre Antwort! Ich habe in der Tat die Ausgabe einiger der Befehle gesammelt, auf die Sie verweisen. Sie sind jetzt auch in der Frage verlinkt ( gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c ). Das Merkwürdige ist , dass get Weise weniger Steckdosen berichteten aus ss, lsofund netstatals von „Steckdosen verwendet“ in /proc/net/sockstat. Nur die Gesamtanzahl (die scheinbar nur aus dieser Datei gelesen wird) ist gleich. iptablesLä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.
Stephan Klein
Ich habe die Ausgabe von ss -aepizu 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.
Stephan Klein
dmesg / journalctl -kAusgabe hinzugefügt .
Stephan Klein
Ich habe überprüft, dass ip link set eth0 promisc onallein die Maschine nicht in einen verwendbaren Zustand zurückversetzt.
Stephan Klein
Hallo, hast du dir diese andere Frage auf dieser Seite angesehen? serverfault.com/questions/614453/… Es scheint, als ob Sie den xfrm4-Zielcache erschöpfen. Sie können es mit dieser Kernel-Einstellung erhöhen: 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.
Pedro Perez
0

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:

Wenn der Ringpuffer aufgrund von RX-Abschlussnachrichten fast voll ist, erreicht ein TX-Paket möglicherweise das "niedrige Wasserzeichen" und verursacht, dass die Warteschlange gestoppt wird. Wenn der TX-Abschluss vor dem Stoppen der Warteschlange eintrifft, wird der Weckvorgang möglicherweise nicht ausgeführt.

Dieser Patch verschiebt die Prüfung für das letzte ausstehende Paket, um sowohl EAGAIN- als auch Erfolgsfälle abzudecken, sodass die Warteschlange bei Bedarf zuverlässig aufgeweckt wird.

Zum späteren Nachschlagen lautet das diesbezügliche Commit https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f .

Stephan Klein
quelle