Oggi ho un mistero per te. Eseguiamo un piccolo cluster Elasticsearch a tre nodi basato su CoreOS (2023.5.0 / Linux 4.19.25-coreos) su Azure. Elasticsearch viene eseguito all'interno di un contenitore docker in modalità rete host. Dopo aver eseguito quasi completamente la manutenzione senza manutenzione per oltre un anno, abbiamo visto le macchine entrare in uno stato molto interessante.
Aggiornare
Questo problema è stato risolto da una correzione di un driver nel kernel di Linux . Vedi la risposta sotto.
Sintomi
Fondamentalmente, la rete tra la macchina interessata e gli altri due nodi muore. Tutti sono nella stessa rete virtuale e nella stessa sottorete e possono normalmente comunicare con tutti gli altri. Il nodo interessato può ancora essere raggiunto da altre sottoreti (posso collegarlo) e da una rete virtuale peered diversa. La macchina ha anche una connessione (molto discutibile) a Internet, ma la maggior parte delle richieste è appena scaduta.
Abbiamo osservato che su un nodo interessato, il numero di "socket utilizzati" riportato /proc/net/sockstat
è molto alto (~ 4,5 k anziché ~ 300 su un nodo sano). Il monitoraggio mostra che questo numero aumenta rapidamente dal momento in cui il nodo diventa non disponibile.
La cosa divertente è che non riusciamo a identificare l'origine di questi socket usati:
# 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
A parte questo, la macchina sembra a posto. Non ci sono processi sospetti in esecuzione, l'utilizzo della CPU è minimo e vi è abbondanza di memoria disponibile.
Il ping di una macchina virtuale "non raggiungibile" nella stessa sottorete comporta alcune EAGAIN
risposte recvmsg
e quindi il passaggio da per ENOBUFS
tornare indietro sendmsg
. output ping strace qui
Ho raccolto un output aggiuntivo (prima che fossero apportate eventuali modifiche al sistema) e l'ho pubblicato in questa sintesi: https://gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c
Analisi
Abbiamo provato a chiudere tutto ciò che possiamo pensare sul server, con elasticsearch il primo sospettato. Ma chiudere il contenitore elasticsearch non libera le prese usate. Stessa cosa per tutti i processi relativi a CoreOS (motore di aggiornamento, fabbro, ...) o anche l'intero runtime Docker o cose specifiche di Azure. Niente sembrava aiutare.
Ma ora è ancora più strano: abbiamo provato a correre tcpdump
sulla macchina per vedere cosa sta succedendo. Ed ecco: il problema si è risolto da solo, la connettività è stata ripristinata. La nostra teoria era che tcpdump fa una sorta di syscall che lo risolve. Abbiamo eseguito tcpdump con gdb e impostato punti di interruzione su tutti i syscall. Dopo aver attraversato un sacco di punti di interruzione, abbiamo finalmente scoperto che l'atto di impostare la modalità promisco sul socket di acquisizione (in particolare questa riga in libpcap ) è la cosa che reimposta il contatore dei socket utilizzati e ci riporta a uno stato normale.
Risultati aggiuntivi
- Abbiamo verificato che il funzionamento
tcpdump
con la-p/--no-promiscuous-mode
bandiera non cancella il contatore dei socket utilizzati e riporta la macchina in uno stato utilizzabile. - L'esecuzione
ifconfig eth0 txqueuelen 1001
reimposta il contatore dei socket utilizzati ma la connettività non viene ripristinata. - L'impostazione manuale della modalità promisc con
ip link set eth0 promisc on
inoltre non ripristina la connettività.net.ipv4.xfrm4_gc_thresh
è impostato su 32768 e aumentarlo leggermente non risolve il problema.
Siamo stati in contatto con Azure, che ne siamo così sconcertati quanto noi. Capisco che questo non è probabilmente il problema ma solo un sintomo. Ma è l'unica cosa tangibile che ho trovato finora. La mia speranza è che, comprendendo il sintomo, riesco ad avvicinarmi alla causa principale. Le interfacce di rete in Azure vengono eseguite con questo driver di rete .
Forse è colpa di CoreOS / Kernel?
Da un punto di vista temporale, i problemi sono iniziati l'11 / 2019/2019, ovvero il giorno in cui CoreOS si è auto-aggiornato all'ultima versione. Secondo le note di rilascio , questo aggiornamento conteneva un aggiornamento del kernel dalla 4.15.23 alla 4.19.25 . Sto ancora esaminando i log delle modifiche per vedere se qualcosa potrebbe essere un problema lì. Finora ho scoperto solo che il driver di rete hyperv ha ricevuto parecchi aggiornamenti negli ultimi mesi , e non tutti sembrano far parte del 4.19.25. Il patchset applicato da CoreOS alla 4.19.25 non è poi così impressionante , ma la patch che introduce un falso modulo nf_conntrack_ipv4 è nuova.
Aggiornamento: possibile correlata patch del kernel in arrivo?
Aiuto!
Finora, le domande che abbiamo sono le seguenti:
Che cosa potrebbe causare questa metrica "socket utilizzati" al razzo? Ho letto i sorgenti del kernel per questa metrica e sembra essere solo un contatore senza riferimento a che tipo di socket sono realmente o cosa li ha creati.
Perché il numero flatline a circa 4.5k? Quale limite lo causerebbe?
È cambiato qualcosa di significativo tra il kernel 4.14.96 e 4.19.25?
Perché la
setsockopt()
chiamata in libpcap reimposta lo stato?
Bug CoreOS correlato: https://github.com/coreos/bugs/issues/2572