CoreOS: tcpdump secara misterius memecahkan masalah jaringan (jumlah soket yang digunakan berlebihan)


14

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/sockstatsangat 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 EAGAINrespons recvmsgdan kemudian beralih untuk ENOBUFSkembali 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 tcpdumpmesin 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 tcpdumpdengan -p/--no-promiscuous-modebendera tidak menghapus penghitung soket yang digunakan dan mengembalikan mesin ke status yang dapat digunakan.
  • Menjalankan ifconfig eth0 txqueuelen 1001reset soket yang digunakan penghitung tetapi konektivitas tidak dipulihkan.
  • Mengatur mode promisc secara manual ip link set eth0 promisc onjuga tidak mengembalikan konektivitas.
    • net.ipv4.xfrm4_gc_thresh diatur ke 32768 dan meningkatkannya sedikit tidak menyelesaikan masalah.

soket yang digunakan

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.

Perbarui: Kemungkinan patch kernel yang masuk terkait?

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


Soket terbuka adalah masalah yang timbul, bukan masalah akar IMHO. Saya memiliki perilaku ini pada sistem linux dengan perangkat macvlan (dengan alamat mac mereka sendiri) pada perangkat jembatan. Mengatur bridge ke promisc membuat perangkat macvlan berfungsi. Saya tidak tahu coreo atau biru. Masalahnya adalah bahwa lapisan yang mendasarinya tidak tahu tentang alamat mac di tingkat atas.
AndreasM

Terima kasih atas komentarmu! Saya menyadari bahwa sejumlah besar soket yang digunakan bukan penyebab utama, saya hanya berpegang teguh pada satu hal nyata yang dapat saya identifikasikan sebagai abnormal pada mesin.
Stephan Klein

Hai Stephan. Ada berita? tolong laporkan 1) apakah WOL diaktifkan? 2) apakah sysctl -w net.ipv4.route.flush = 1 menyelesaikan? 3) apa cache arp tanpa kondisi kerja? di negara kerja?
Massimo

Jawaban:


4

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:

  • Mungkin Anda sudah mencoba sesuatu seperti ss -aedan lsof -n?
  • Apakah dmesgmengembalikan sesuatu yang menarik ketika ini terjadi?
  • Apakah Anda menggunakan iptables di server?
  • Jika Anda mengatur mode promiscuous menggunakan cara lain selain tcpdump (katakanlah ip link set [interface] promisc on), apakah ini juga memperbaiki masalah?
  • Sudahkah Anda memeriksa proses mencurigakan, file, atau aktivitas aneh lainnya? Hanya berpikir bahwa mungkin beberapa proses jahat tanpa diundang bersembunyi di bayang-bayang menyembunyikan dirinya sendiri, dan menjadi diam setiap kali mode bebas diatur?
  • Jika Anda membiarkan latar belakang tcpdump berjalan, apakah masalah ini akan kembali?

Saya harap ini membantu.


1
Terimakasih atas balasan anda! Saya memang telah mengumpulkan output dari beberapa perintah yang Anda referensi. Mereka sekarang juga ditautkan dalam pertanyaan ( gist.github.com/privatwolke/e7e2e7eb0272787765f5d3726f37107c ). Yang aneh adalah bahwa mendapatkan soket jauh lebih sedikit dilaporkan ss, lsofdan netstatdari "soket digunakan" di /proc/net/sockstat. Hanya jumlah total (yang tampaknya hanya dibaca dari file itu) yang sama. iptablesberjalan tetapi tidak memiliki aturan khusus (lihat intisari), saya belum mencoba mengatur mode promiscous sendiri atau menjalankan tcpdump terus menerus. Akan melakukannya lain kali.
Stephan Klein

Saya telah menambahkan output ss -aepike koleksi keluaran saya: gist.github.com/privatwolke/… - Sedihnya dmesg tidak mengembalikan apa pun saat ini terjadi. Bahkan, entri terbaru sebelum insiden berusia 5 hari.
Stephan Klein

dmesg / journalctl -kOutput ditambahkan .
Stephan Klein

Saya telah memverifikasi itu ip link set eth0 promisc onsaja tidak mengembalikan mesin ke kondisi yang dapat digunakan.
Stephan Klein

Halo, Apakah Anda sudah melihat pertanyaan lain di situs ini? serverfault.com/questions/614453/... Tampaknya menyiratkan Anda mungkin menghabiskan cache dest xfrm4. Anda dapat meningkatkannya dengan pengaturan kernel ini: 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.
Pedro Perez

0

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:

Ketika buffer cincin hampir penuh karena pesan RX selesai, paket TX dapat mencapai "tanda air rendah" dan menyebabkan antrian berhenti. Jika TX selesai lebih awal dari antrian berhenti, bangun mungkin terlewatkan.

Patch ini memindahkan pemeriksaan untuk paket tertunda terakhir yang mencakup EAGAIN dan kasus sukses, sehingga antrian akan terbangun dengan andal bila diperlukan.

Untuk referensi di masa mendatang, komit yang memperbaiki ini adalah https://github.com/torvalds/linux/commit/6d9cfab853ca60b2f77b5e4c40443216988cba1f .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.