Saya punya misteri untuk Anda hari ini. Kami menjalankan kecil, tiga simpul cluster Elasticsearch berdasarkan CoreOS (2023.5.0 / Linux 4.19.25-coreos) di Azure. Elasticsearch dijalankan di dalam wadah buruh pelabuhan dalam mode jaringan host. Setelah menjalankan hampir sepenuhnya bebas perawatan selama lebih dari setahun kami telah melihat mesin masuk ke keadaan yang sangat menarik.
Memperbarui
Masalah ini diselesaikan dengan perbaikan ke driver di kernel Linux . Lihat jawaban di bawah ini.
Gejala
Pada dasarnya, jaringan antara mesin yang terpengaruh dan dua node lainnya mati. Semua berada di jaringan virtual yang sama dan subnet yang sama dan secara usus dapat berkomunikasi dengan sumpah lainnya. Node yang terpengaruh masih dapat dijangkau dari subnet lain (saya dapat ssh ke dalamnya) dan dari jaringan virtual yang diintip berbeda. Mesin ini juga memiliki koneksi (sangat jerawatan) ke Internet, tetapi sebagian besar permintaan hanya time out.
Kami telah mengamati bahwa pada simpul yang terpengaruh, jumlah "soket yang digunakan" yang dilaporkan /proc/net/sockstat
sangat tinggi (~ 4.5k, bukan ~ 300 pada simpul sehat). Pemantauan menunjukkan bahwa jumlah ini dengan cepat naik dari saat simpul tidak tersedia.
Yang menyenangkan adalah kita tidak bisa mengidentifikasi sumber soket yang digunakan ini:
# 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
Selain itu, mesin itu tampaknya baik-baik saja. Tidak ada proses mencurigakan yang berjalan, penggunaan CPU minimal dan ada banyak memori yang tersedia.
Mem-ping VM yang "tidak terjangkau" di subnet yang sama menghasilkan beberapa EAGAIN
respons recvmsg
dan kemudian beralih untuk ENOBUFS
kembali sendmsg
. strace ping output di sini
Saya telah mengumpulkan beberapa output tambahan (sebelum modifikasi pada sistem dilakukan) dan mempostingnya di intisari ini: https://gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c
Analisis
Kami telah mencoba mematikan semua yang dapat kami pikirkan di server, dengan elasticsearch menjadi tersangka pertama. Tetapi mematikan wadah elasticsearch tidak membebaskan soket yang digunakan. Hal yang sama untuk semua proses terkait CoreOS (mesin pembaruan, locksmithd, ...) atau bahkan seluruh runtime Docker atau hal-hal khusus Azure. Tampaknya tidak ada yang membantu.
Tapi sekarang semakin aneh: Kami berusaha untuk menjalankan tcpdump
mesin untuk melihat apa yang sedang terjadi. Dan lihat: Masalah terselesaikan dengan sendirinya, konektivitas dipulihkan. Teori kami adalah bahwa tcpdump melakukan semacam syscall yang menyelesaikannya. Kami menjalankan tcpdump dengan gdb dan mengatur breakpoint pada semua syscalls. Setelah melangkah melalui banyak breakpoint, kami akhirnya menemukan bahwa tindakan pengaturan mode promiscous pada soket penangkap (khususnya baris ini di libpcap ) adalah hal yang mengatur ulang soket penghitung yang digunakan dan mengembalikan kita ke keadaan normal.
Temuan tambahan
- Kami telah memverifikasi bahwa menjalankan
tcpdump
dengan-p/--no-promiscuous-mode
bendera tidak menghapus penghitung soket yang digunakan dan mengembalikan mesin ke status yang dapat digunakan. - Menjalankan
ifconfig eth0 txqueuelen 1001
reset soket yang digunakan penghitung tetapi konektivitas tidak dipulihkan. - Mengatur mode promisc secara manual
ip link set eth0 promisc on
juga tidak mengembalikan konektivitas.net.ipv4.xfrm4_gc_thresh
diatur ke 32768 dan meningkatkannya sedikit tidak menyelesaikan masalah.
Kami telah melakukan kontak dengan Azure yang sama bingungnya dengan kami. Saya mengerti bahwa ini kemungkinan bukan masalah tetapi hanya gejala. Tapi itu satu-satunya hal nyata yang saya temukan sejauh ini. Harapan saya adalah bahwa dengan memahami gejalanya saya bisa lebih dekat ke akar permasalahan. Antarmuka jaringan di Azure dijalankan dengan driver jaringan ini .
Mungkin CoreOS / Kernel yang harus disalahkan?
Dari sudut pandang timeline, masalah dimulai pada 2019-03-11 yang merupakan hari di mana CoreOS diperbarui secara otomatis ke versi terbaru. Menurut catatan rilis , pembaruan ini berisi pembaruan kernel dari 4.15.23 hingga 4.19.25 . Saya masih melalui changelogs untuk melihat apakah ada masalah di sana. Sejauh ini saya hanya menemukan bahwa driver jaringan hyperv telah menerima beberapa pembaruan dalam beberapa bulan terakhir , tidak semuanya tampaknya menjadi bagian dari 4.19.25. Patchset yang diterapkan CoreOS pada 4.19.25 tidak begitu mengesankan , tetapi patch yang memperkenalkan modul nf_conntrack_ipv4 palsu adalah baru.
Tolong!
Sejauh ini, pertanyaan yang kami miliki adalah sebagai berikut:
Apa yang menyebabkan metrik "soket bekas" ini meroket? Saya telah membaca sumber kernel untuk metrik ini dan tampaknya hanya sebuah counter tanpa referensi ke jenis soket yang sebenarnya atau apa yang menciptakannya.
Mengapa angka flatline sekitar 4,5k? Batas mana yang menyebabkan hal ini?
Apakah ada perubahan signifikan antara kernel 4.14.96 dan 4.19.25?
Mengapa
setsockopt()
panggilan di libpcap mengatur ulang keadaan?
Bug CoreOS Terkait: https://github.com/coreos/bugs/issues/2572
sumber
Jawaban:
Pertama-tama, terima kasih atas pertanyaan yang ditulis dengan sangat baik!
Karena level detail yang Anda jelaskan sangat tinggi dan Anda sudah berada di level gdb, saya berasumsi jawaban saya tidak akan banyak berguna bagi Anda. Pokoknya, inilah yang coba:
ss -ae
danlsof -n
?dmesg
mengembalikan sesuatu yang menarik ketika ini terjadi?ip link set [interface] promisc on
), apakah ini juga memperbaiki masalah?Saya harap ini membantu.
sumber
ss
,lsof
dannetstat
dari "soket digunakan" di/proc/net/sockstat
. Hanya jumlah total (yang tampaknya hanya dibaca dari file itu) yang sama.iptables
berjalan tetapi tidak memiliki aturan khusus (lihat intisari), saya belum mencoba mengatur mode promiscous sendiri atau menjalankan tcpdump terus menerus. Akan melakukannya lain kali.ss -aepi
ke koleksi keluaran saya: gist.github.com/privatwolke/… - Sedihnya dmesg tidak mengembalikan apa pun saat ini terjadi. Bahkan, entri terbaru sebelum insiden berusia 5 hari.dmesg / journalctl -k
Output ditambahkan .ip link set eth0 promisc on
saja tidak mengembalikan mesin ke kondisi yang dapat digunakan.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.
Sejauh yang saya tahu ini terkait dengan IPsec, yang sepertinya Anda juga tidak menjalankannya di sini.Ini disebabkan oleh bug pada driver hv_netsvc di kernel Linux. Kami dapat menyelesaikan ini dengan pengembang Microsoft dan berhasil mendapatkan perbaikan diterapkan di hulu.
Saya akan mengutip pesan komit di sini karena meringkas masalah dengan cukup baik:
Untuk referensi di masa mendatang, komit yang memperbaiki ini adalah https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f .
sumber