Debugging latency jaringan dina Kubernetes

Debugging latency jaringan dina Kubernetes

Sababaraha taun ka pengker Kubernetes geus dibahas dina blog GitHub resmi. Ti saprak éta, éta parantos janten téknologi standar pikeun nyebarkeun jasa. Kubernetes ayeuna ngatur sabagéan ageung jasa internal sareng umum. Nalika klaster urang tumuwuh sareng syarat kinerja janten langkung ketat, urang mimiti perhatikeun yén sababaraha jasa dina Kubernetes sacara sporadis ngalaman latency anu henteu tiasa dijelaskeun ku beban aplikasi éta sorangan.

Intina, aplikasi ngalaman latency jaringan acak nepi ka 100ms atawa leuwih, hasilna timeouts atanapi retries. Jasa diperkirakeun tiasa ngabales pamundut langkung gancang ti 100ms. Tapi ieu teu mungkin lamun sambungan sorangan nyokot jadi loba waktu. Kapisah, urang niténan queries MySQL pisan gancang nu kedah nyandak milliseconds, sarta MySQL réngsé dina milliseconds, tapi tina sudut pandang aplikasi requesting urang, respon nyandak 100 mdet atawa leuwih.

Langsung janten écés yén masalahna ngan lumangsung nalika nyambungkeun ka titik Kubernetes, sanajan panggero datang ti luar Kubernetes. Cara panggampangna pikeun baranahan masalah nyaéta dina tés Vegeta, nu ngalir ti mana wae host internal, nguji layanan Kubernetes dina port husus, sarta sporadis ngadaptar latency tinggi. Dina tulisan ieu, urang bakal ningali kumaha urang tiasa ngalacak anu nyababkeun masalah ieu.

Ngaleungitkeun pajeulitna anu teu perlu dina ranté ngarah gagal

Ku reproducing conto sarua, urang hayang ngahususkeun fokus masalah jeung miceun lapisan perlu pajeulitna. Mimitina, aya loba teuing elemen dina aliran antara Vegeta jeung pods Kubernetes. Pikeun ngaidentipikasi masalah jaringan anu langkung jero, anjeun kedah ngaluarkeun sababaraha di antarana.

Debugging latency jaringan dina Kubernetes

Klién (Vegeta) nyiptakeun sambungan TCP sareng titik mana waé dina kluster. Kubernetes beroperasi salaku jaringan overlay (di luhureun jaringan puseur data aya) nu ngagunakeun IPIP, nyaeta, eta encapsulates pakét IP tina jaringan overlay jero pakét IP tina puseur data. Nalika nyambungkeun ka titik kahiji, tarjamahan alamat jaringan dilaksanakeun Tarjamahan Alamat Jaringan (NAT) stateful pikeun narjamahkeun alamat IP na port tina titik Kubernetes ka alamat IP na port dina jaringan overlay (husus, pod jeung aplikasi). Pikeun pakét asup, urutan sabalikna tina tindakan dilaksanakeun. Éta mangrupikeun sistem anu kompleks sareng seueur kaayaan sareng seueur elemen anu terus-terusan diropéa sareng dirobih nalika jasa disebarkeun sareng dipindahkeun.

Utiliti tcpdump dina tés Vegeta aya reureuh salila sasalaman TCP (antara SYN jeung SYN-ACK). Pikeun ngaleungitkeun pajeulitna anu teu perlu ieu, anjeun tiasa nganggo hping3 pikeun basajan "pings" kalawan pakét SYN. Urang pariksa lamun aya reureuh dina pakét respon, lajeng ngareset sambungan. Urang tiasa nyaring data pikeun ngan ukur ngalebetkeun pakét langkung ageung ti 100ms sareng kéngingkeun cara anu langkung gampang pikeun ngahasilkeun deui masalah tibatan uji lapisan jaringan 7 Vegeta. Ieu mangrupikeun titik "ping" Kubernetes nganggo TCP SYN / SYN-ACK dina jasa "port node" (30927) dina interval 10ms, disaring ku réspon anu paling laun:

theojulienne@shell ~ $ sudo hping3 172.16.47.27 -S -p 30927 -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'

len = 46 ip = 172.16.47.27 ttl = 59 DF id = 0 olahraga = 30927 bandéra = SA seq = 1485 meunang = 29200 rtt = 127.1 mdet

len = 46 ip = 172.16.47.27 ttl = 59 DF id = 0 olahraga = 30927 bandéra = SA seq = 1486 meunang = 29200 rtt = 117.0 mdet

len = 46 ip = 172.16.47.27 ttl = 59 DF id = 0 olahraga = 30927 bandéra = SA seq = 1487 meunang = 29200 rtt = 106.2 mdet

len = 46 ip = 172.16.47.27 ttl = 59 DF id = 0 olahraga = 30927 bandéra = SA seq = 1488 meunang = 29200 rtt = 104.1 mdet

len = 46 ip = 172.16.47.27 ttl = 59 DF id = 0 olahraga = 30927 bandéra = SA seq = 5024 meunang = 29200 rtt = 109.2 mdet

len = 46 ip = 172.16.47.27 ttl = 59 DF id = 0 olahraga = 30927 bandéra = SA seq = 5231 meunang = 29200 rtt = 109.2 mdet

Bisa langsung niténan heula. Ditilik ku nomer urutan sareng waktosna, jelas yén ieu sanés kamacetan sakali. Reureuh mindeng accumulates sarta ahirna diprosés.

Salajengna, urang hoyong terang komponén mana anu tiasa kalibet dina lumangsungna kamacetan. Panginten ieu mangrupikeun sababaraha ratusan aturan iptables di NAT? Atanapi aya masalah sareng tunneling IPIP dina jaringan? Salah sahiji cara pikeun nguji ieu nyaéta pikeun nguji unggal léngkah sistem ku cara ngaleungitkeunana. Naon anu lumangsung upami anjeun ngahapus logika NAT sareng firewall, ngan ukur nyésakeun bagian IPIP:

Debugging latency jaringan dina Kubernetes

Untungna, Linux Ubuntu ngagampangkeun aksés langsung kana lapisan overlay IP upami mesinna aya dina jaringan anu sami:

theojulienne@kube-node-client ~ $ sudo hping3 10.125.20.64 -S -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'

len = 40 ip = 10.125.20.64 ttl = 64 DF id = 0 olahraga = 0 bandéra = RA seq = 7346 meunang = 0 rtt = 127.3 mdet

len = 40 ip = 10.125.20.64 ttl = 64 DF id = 0 olahraga = 0 bandéra = RA seq = 7347 meunang = 0 rtt = 117.3 mdet

len = 40 ip = 10.125.20.64 ttl = 64 DF id = 0 olahraga = 0 bandéra = RA seq = 7348 meunang = 0 rtt = 107.2 mdet

Ditilik ku hasilna, masalahna masih tetep! Ieu henteu kalebet iptables sareng NAT. Janten masalahna nyaéta TCP? Hayu urang tingali kumaha ping ICMP biasa:

theojulienne@kube-node-client ~ $ sudo hping3 10.125.20.64 --icmp -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'

len=28 ip=10.125.20.64 ttl=64 id=42594 icmp_seq=104 rtt=110.0 ms

len=28 ip=10.125.20.64 ttl=64 id=49448 icmp_seq=4022 rtt=141.3 ms

len=28 ip=10.125.20.64 ttl=64 id=49449 icmp_seq=4023 rtt=131.3 ms

len=28 ip=10.125.20.64 ttl=64 id=49450 icmp_seq=4024 rtt=121.2 ms

len=28 ip=10.125.20.64 ttl=64 id=49451 icmp_seq=4025 rtt=111.2 ms

len=28 ip=10.125.20.64 ttl=64 id=49452 icmp_seq=4026 rtt=101.1 ms

len=28 ip=10.125.20.64 ttl=64 id=50023 icmp_seq=4343 rtt=126.8 ms

len=28 ip=10.125.20.64 ttl=64 id=50024 icmp_seq=4344 rtt=116.8 ms

len=28 ip=10.125.20.64 ttl=64 id=50025 icmp_seq=4345 rtt=106.8 ms

len=28 ip=10.125.20.64 ttl=64 id=59727 icmp_seq=9836 rtt=106.1 ms

Hasilna nunjukkeun yén masalahna henteu musna. Sugan ieu torowongan IPIP? Hayu urang saderhanakeun tés salajengna:

Debugging latency jaringan dina Kubernetes

Naha sadaya pakét dikirim antara dua host ieu?

theojulienne@kube-node-client ~ $ sudo hping3 172.16.47.27 --icmp -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'

len=46 ip=172.16.47.27 ttl=61 id=41127 icmp_seq=12564 rtt=140.9 ms

len=46 ip=172.16.47.27 ttl=61 id=41128 icmp_seq=12565 rtt=130.9 ms

len=46 ip=172.16.47.27 ttl=61 id=41129 icmp_seq=12566 rtt=120.8 ms

len=46 ip=172.16.47.27 ttl=61 id=41130 icmp_seq=12567 rtt=110.8 ms

len=46 ip=172.16.47.27 ttl=61 id=41131 icmp_seq=12568 rtt=100.7 ms

len=46 ip=172.16.47.27 ttl=61 id=9062 icmp_seq=31443 rtt=134.2 ms

len=46 ip=172.16.47.27 ttl=61 id=9063 icmp_seq=31444 rtt=124.2 ms

len=46 ip=172.16.47.27 ttl=61 id=9064 icmp_seq=31445 rtt=114.2 ms

len=46 ip=172.16.47.27 ttl=61 id=9065 icmp_seq=31446 rtt=104.2 ms

Kami parantos nyederhanakeun kaayaan kana dua titik Kubernetes anu saling ngirimkeun pakét, bahkan ping ICMP. Aranjeunna masih ningali latency lamun udagan host "goréng" (sabagian leuwih goreng ti batur).

Ayeuna patarosan anu terakhir: naha reureuh ngan ukur lumangsung dina server kube-node? Sareng naha éta lumangsung nalika kube-node mangrupikeun pangirim atanapi panampi? Kabeneran, ieu ogé rada gampang pikeun terang ku ngirim pakét ti host di luar Kubernetes, tapi kalayan panarima anu "dipikawanoh goréng" sami. Sakumaha anjeun tiasa tingali, masalahna henteu ngaleungit:

theojulienne@shell ~ $ sudo hping3 172.16.47.27 -p 9876 -S -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'

len = 46 ip = 172.16.47.27 ttl = 61 DF id = 0 olahraga = 9876 bandéra = RA seq = 312 meunang = 0 rtt = 108.5 mdet

len = 46 ip = 172.16.47.27 ttl = 61 DF id = 0 olahraga = 9876 bandéra = RA seq = 5903 meunang = 0 rtt = 119.4 mdet

len = 46 ip = 172.16.47.27 ttl = 61 DF id = 0 olahraga = 9876 bandéra = RA seq = 6227 meunang = 0 rtt = 139.9 mdet

len = 46 ip = 172.16.47.27 ttl = 61 DF id = 0 olahraga = 9876 bandéra = RA seq = 7929 meunang = 0 rtt = 131.2 mdet

Urang teras bakal ngajalankeun pamundut anu sami tina sumber kube-node sateuacana ka host éksternal (anu henteu kalebet host sumber sabab ping kalebet komponén RX sareng TX):

theojulienne@kube-node-client ~ $ sudo hping3 172.16.33.44 -p 9876 -S -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'
^C
--- 172.16.33.44 hping statistic ---
22352 packets transmitted, 22350 packets received, 1% packet loss
round-trip min/avg/max = 0.2/7.6/1010.6 ms

Ku examining latency pakét newak, kami meunang sababaraha émbaran tambahan. Husus, yén pangirim (handap) ningali seep ieu, tapi panarima (luhureun) henteu - tingali kolom Delta (dina detik):

Debugging latency jaringan dina Kubernetes

Sajaba ti éta, lamun nempo bédana dina urutan TCP na ICMP pakét (ku angka runtuyan) di sisi panarima, salawasna datangna pakét ICMP dina urutan anu sarua dimana aranjeunna dikirim, tapi kalawan timing béda. Dina waktu nu sarua, pakét TCP kadang interleave, sarta sababaraha di antarana nyangkut. Utamana, lamun nalungtik palabuhan tina pakét SYN, aranjeunna dina urutan di sisi pangirim, tapi teu di sisi panarima.

Aya bédana halus dina cara kartu jaringan server modern (sapertos anu aya di pusat data urang) ngolah pakét anu ngandung TCP atanapi ICMP. Nalika pakét datang, adaptor jaringan "hashes per sambungan", nyaéta, éta nyobian megatkeun sambungan kana antrian sarta ngirimkeun unggal antrian ka inti processor misah. Pikeun TCP, hash ieu kalebet alamat IP sumber sareng tujuan sareng port. Dina basa sejen, unggal sambungan geus hashed (berpotensi) béda. Pikeun ICMP, ngan ukur alamat IP anu hashed, sabab teu aya palabuhan.

Observasi anyar sejen: salila periode ieu urang tingali ICMP reureuh dina sagala komunikasi antara dua host, tapi TCP henteu. Ieu nyarioskeun ka urang yén panyababna kamungkinan aya hubunganana sareng hashing antrian RX: kamacetan ampir pasti dina ngolah pakét RX, sanés dina ngirim réspon.

Ieu ngaleungitkeun ngirim pakét tina daptar kamungkinan sabab. Urang ayeuna terang yén masalah ngolah pakét aya dina sisi nampi dina sababaraha server kube-node.

Ngartos ngolah pakét dina kernel Linux

Pikeun ngartos naha masalahna lumangsung dina panarima dina sababaraha server kube-node, hayu urang tingali kumaha kernel Linux ngolah pakét.

Balik ka palaksanaan tradisional pangbasajanna, kartu jaringan narima pakét jeung ngirim ngaganggu kernel Linux anu aya pakét anu kedah diolah. Kernel ngeureunkeun pagawéan sanés, ngarobih kontéks ka panangan interupsi, ngolah pakét, teras uih deui ka tugas ayeuna.

Debugging latency jaringan dina Kubernetes

Konteks switching ieu slow: latency bisa jadi teu geus noticeable dina kartu jaringan 10Mbps dina '90s, tapi dina kartu 10G modern kalawan throughput maksimum 15 juta pakét per detik, unggal inti server leutik dalapan inti bisa interrupted jutaan. kali per detik.

Dina raraga teu terus-terusan nanganan interrupts, sababaraha taun ka pengker Linux Ubuntu ditambahkeun NAPI: Network API nu sagala drivers modern ngagunakeun pikeun ngaronjatkeun kinerja di speeds tinggi. Dina speeds low kernel masih narima interrupts tina kartu jaringan dina cara heubeul. Sakali pakét cekap dugi anu ngaleuwihan ambang, kernel nganonaktipkeun interrupts sareng janten polling adaptor jaringan sareng nyandak pakét dina sakumpulan. Ngolah dilaksanakeun dina softirq, nyaéta, dina konteks interrupts software sanggeus nelepon sistem jeung hardware interrupts, nalika kernel (sabalikna tina spasi pamaké) geus ngajalankeun.

Debugging latency jaringan dina Kubernetes

Ieu leuwih gancang, tapi ngabalukarkeun masalah béda. Upami aya seueur teuing pakét, teras sadaya waktos nyéépkeun ngolah pakét tina kartu jaringan, sareng prosés rohangan pangguna henteu gaduh waktos pikeun ngosongkeun antrian ieu (maca tina sambungan TCP, jsb.). Pamustunganana antrian ngeusian sareng urang ngamimitian ngaragragkeun pakét. Dina usaha pikeun manggihan kasaimbangan, kernel nangtukeun anggaran pikeun jumlah maksimum pakét diolah dina konteks softirq. Sakali anggaran ieu ngaleuwihan, thread misah ieu awakened ksoftirqd (Anjeun bakal ningali salah sahijina dina ps per inti) nu handles softirqs ieu luar tina syscall normal / jalur interupsi. Utas ieu dijadwalkeun nganggo penjadwal prosés standar, anu nyobian ngalokasikeun sumber daya sacara adil.

Debugging latency jaringan dina Kubernetes

Saatos diajar kumaha kernel ngolah pakét, anjeun tiasa ningali yén aya kamungkinan kamacetan. Upami sauran softirq kirang sering ditampi, pakét kedah ngantosan sababaraha waktos kanggo diolah dina antrian RX dina kartu jaringan. Ieu bisa jadi alatan sababaraha pancén blocking inti processor, atawa hal sejenna anu nyegah inti ngajalankeun softirq.

Narrowing processing handap ka inti atawa métode

Telat Softirq ngan ukur perkiraan pikeun ayeuna. Tapi masuk akal, sareng urang terang yén urang ningali anu sami. Jadi lengkah saterusna nyaéta pikeun mastikeun téori ieu. Sareng upami éta dikonfirmasi, teras milarian alesan pikeun telat.

Hayu urang balik ka pakét slow kami:

len=46 ip=172.16.53.32 ttl=61 id=29573 icmp_seq=1953 rtt=99.3 ms

len=46 ip=172.16.53.32 ttl=61 id=29574 icmp_seq=1954 rtt=89.3 ms

len=46 ip=172.16.53.32 ttl=61 id=29575 icmp_seq=1955 rtt=79.2 ms

len=46 ip=172.16.53.32 ttl=61 id=29576 icmp_seq=1956 rtt=69.1 ms

len=46 ip=172.16.53.32 ttl=61 id=29577 icmp_seq=1957 rtt=59.1 ms

len=46 ip=172.16.53.32 ttl=61 id=29790 icmp_seq=2070 rtt=75.7 ms

len=46 ip=172.16.53.32 ttl=61 id=29791 icmp_seq=2071 rtt=65.6 ms

len=46 ip=172.16.53.32 ttl=61 id=29792 icmp_seq=2072 rtt=55.5 ms

Salaku dibahas saméméhna, pakét ICMP ieu hashed kana antrian RX NIC tunggal jeung diolah ku inti CPU tunggal. Lamun urang hoyong ngartos kumaha Linux Ubuntu jalan, éta mangpaat uninga dimana (dina CPU inti) jeung kumaha (softirq, ksoftirqd) bungkusan ieu diolah dina urutan pikeun ngalacak prosés.

Ayeuna waktosna ngagunakeun alat anu ngamungkinkeun anjeun ngawas kernel Linux sacara real waktos. Di dieu urang dipaké bcc. set alat ieu ngidinan Anjeun pikeun nulis program C leutik nu hook fungsi sawenang dina kernel jeung panyangga kajadian kana program Python pamaké-spasi nu bisa ngolah aranjeunna sarta mulangkeun hasilna ka anjeun. Hooks pikeun fungsi sawenang dina kernel mangrupakeun masalah kompléks, tapi utiliti dirancang pikeun kaamanan maksimum sarta dirancang pikeun lagu handap persis jenis masalah produksi nu teu gampang dihasilkeun dina lingkungan test atawa ngembangkeun.

Rencanana di dieu saderhana: urang terang yén kernel ngolah ping ICMP ieu, ku kituna urang bakal nempatkeun hook dina fungsi kernel. icmp_echo, nu narima hiji pakét pamundut gema ICMP asup tur initiates ngirim hiji respon gema ICMP. Urang tiasa ngaidentipikasi pakét ku cara ningkatkeun jumlah icmp_seq, anu nunjukkeun hping3 luhur.

kode naskah bcc Sigana pajeulit, tapi teu jadi pikasieuneun sakumaha sigana. Fungsi icmp_echo nepikeun struct sk_buff *skb: Ieu pakét kalawan "pamenta gema". Urang bisa ngalacak eta, tarik kaluar runtuyan echo.sequence (anu ngabandingkeun sareng icmp_seq ku hping3 выше), sareng kirimkeun ka rohangan pangguna. Éta ogé merenah pikeun moto ngaran / id prosés ayeuna. Di handap ieu hasil anu urang tingali langsung nalika kernel ngolah pakét:

TGID PID PROSES NGARAN ICMP_seq 0 0 Swapper/11 770 0 0 SwApper/11 771 0 0 Swapper/11 772 0 0 Swapper/11 773 0 0 Swapper/11 774 20041 20086 775 0 SWAPPER/ 0 11 776 0 swapper/0 11 777 0 spokes-laporan-s 0

Ieu kudu dicatet di dieu yén dina konteks softirq prosés nu nelepon sistem bakal némbongan salaku "prosés" lamun sabenerna éta kernel anu aman ngolah pakét dina konteks kernel.

Kalayan alat ieu urang tiasa ngahubungkeun prosés khusus sareng bungkusan khusus anu nunjukkeun reureuh tina hping3. Hayu urang nyieun basajan grep on newak ieu pikeun nilai tangtu icmp_seq. Pakét anu cocog sareng nilai icmp_seq di luhur kacatet sareng RTT anu kami titénan di luhur (dina kurung mangrupikeun nilai RTT anu dipiharep pikeun pakét anu kami disaring kusabab nilai RTT kirang ti 50 ms):

TGID PID PROSES NGARAN ICMP_SEQ ** RTT -- 10137 10436 cadvisor 1951 10137 10436 cadvisor 1952 76 76 ksoftirqd/11 1953 ** 99ms 76 76 ksoftir 11 1954 ksoftir 89 76 ** 76ms 11 1955 ksoftirqd/ 79 76 ** 76ms 11 1956 ksoftirqd/69 76 ** 76ms 11 1957 ksoftirqd/59 76 ** (76ms) 11 1958 ksoftirqd/49 76 ** (76ms) 11 1959 ksoftirqd 39 76 ksoftirqd (76ms) qd/ 11 1960 ** (29ms) 76 76 ksoftirqd/11 1961 ** (19ms) -- 76 76 cadvisor 11 1962 9 cadvisor 10137 10436 2068 ksoftirqd 10137 10436 ksoftirqd 2069 76 ksoftirqd 76 ** 11ms 2070 75 ksoftirqd/ 76 76 ** 11ms 2071 65 ksoftirqd/76 76 ** (11ms) 2072 55 ksoftirqd/76 76 ** (11ms) 2073 45 ksoftirqd/76 76 ** (11ms) 2074 ms (35ms) 76 ms ) 76 11 ksoftirqd/2075 25 ** (76ms)

Hasilna ngabejaan urang sababaraha hal. Anu mimiti, sadaya bungkusan ieu diolah ku kontéks ksoftirqd/11. Ieu ngandung harti yén pikeun pasangan tinangtu ieu mesin, pakét ICMP ieu hashed kana inti 11 dina tungtung panarima. Urang ogé ningali yén iraha waé aya macét, aya pakét anu diolah dina kontéks telepon sistem cadvisor. Satuluyna ksoftirqd nyokot alih tugas jeung prosés antrian akumulasi: persis jumlah pakét nu geus akumulasi sanggeus cadvisor.

Kanyataan yén geuwat saméméh éta salawasna jalan cadvisor, ngakibatkeun involvement na dina masalah. Ironisna, tujuanana cadvisor - "nganalisis pamakean sumberdaya sareng ciri kinerja wadah anu ngajalankeun" tinimbang nyababkeun masalah kinerja ieu.

Sapertos aspék wadah anu sanés, ieu mangrupikeun alat anu canggih pisan sareng tiasa diperkirakeun ngalaman masalah kinerja dina sababaraha kaayaan anu teu kaduga.

Naon anu dilakukeun ku cadvisor anu ngalambatkeun antrian pakét?

Urang ayeuna gaduh pamahaman anu saé kumaha kacilakaan éta, prosés naon anu nyababkeun, sareng CPU mana. Kami ningali yén kusabab meungpeuk keras, kernel Linux henteu gaduh waktos pikeun ngajadwalkeun ksoftirqd. Sareng urang ningali yén pakét diolah dina kontéks cadvisor. Éta logis pikeun nganggap éta cadvisor ngajalankeun syscall slow, nu satutasna sadaya pakét akumulasi dina waktos anu diolah:

Debugging latency jaringan dina Kubernetes

Ieu téori, tapi kumaha carana nguji éta? Anu tiasa urang laksanakeun nyaéta ngalacak inti CPU sapanjang prosés ieu, milarian titik dimana jumlah pakét langkung seueur anggaran sareng ksoftirqd disebut, teras tingali sakedik deui pikeun ningali naon anu leres-leres dijalankeun dina inti CPU sateuacan éta titik. . Ieu kawas x-raying CPU unggal sababaraha milliseconds. Éta bakal katingali sapertos kieu:

Debugging latency jaringan dina Kubernetes

Merenah, sadaya ieu tiasa dilakukeun ku alat anu tos aya. Salaku conto, catetan perf mariksa inti CPU anu dipasihkeun dina frékuénsi anu ditangtukeun sareng tiasa ngahasilkeun jadwal telepon ka sistem anu ngajalankeun, kalebet rohangan pangguna sareng kernel Linux. Anjeun tiasa nyandak catetan ieu sareng ngolahna nganggo garpu leutik program FlameGraph ti Brendan Gregg, nu preserves urutan renik tumpukan. Urang tiasa nyimpen jejak tumpukan garis tunggal unggal 1 mdet, teras nyorot sareng nyimpen sampel 100 milidetik sateuacan jejakna pencét ksoftirqd:

# record 999 times a second, or every 1ms with some offset so not to align exactly with timers
sudo perf record -C 11 -g -F 999
# take that recording and make a simpler stack trace.
sudo perf script 2>/dev/null | ./FlameGraph/stackcollapse-perf-ordered.pl | grep ksoftir -B 100

Ieu hasilna:

(сотни следов, которые выглядят похожими)

cadvisor;[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];entry_SYSCALL_64_after_swapgs;do_syscall_64;sys_read;vfs_read;seq_read;memcg_stat_show;mem_cgroup_nr_lru_pages;mem_cgroup_node_nr_lru_pages cadvisor;[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];entry_SYSCALL_64_after_swapgs;do_syscall_64;sys_read;vfs_read;seq_read;memcg_stat_show;mem_cgroup_nr_lru_pages;mem_cgroup_node_nr_lru_pages cadvisor;[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];entry_SYSCALL_64_after_swapgs;do_syscall_64;sys_read;vfs_read;seq_read;memcg_stat_show;mem_cgroup_iter cadvisor;[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];entry_SYSCALL_64_after_swapgs;do_syscall_64;sys_read;vfs_read;seq_read;memcg_stat_show;mem_cgroup_nr_lru_pages;mem_cgroup_node_nr_lru_pages cadvisor;[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];[cadvisor];entry_SYSCALL_64_after_swapgs;do_syscall_64;sys_read;vfs_read;seq_read;memcg_stat_show;mem_cgroup_nr_lru_pages;mem_cgroup_node_nr_lru_pages ksoftirqd/11;ret_from_fork;kthread;kthread;smpboot_thread_fn;smpboot_thread_fn;run_ksoftirqd;__do_softirq;net_rx_action;ixgbe_poll;ixgbe_clean_rx_irq;napi_gro_receive;netif_receive_skb_internal;inet_gro_receive;bond_handle_frame;__netif_receive_skb_core;ip_rcv_finish;ip_rcv;ip_forward_finish;ip_forward;ip_finish_output;nf_iterate;ip_output;ip_finish_output2;__dev_queue_xmit;dev_hard_start_xmit;ipip_tunnel_xmit;ip_tunnel_xmit;iptunnel_xmit;ip_local_out;dst_output;__ip_local_out;nf_hook_slow;nf_iterate;nf_conntrack_in;generic_packet;ipt_do_table;set_match_v4;ip_set_test;hash_net4_kadt;ixgbe_xmit_frame_ring;swiotlb_dma_mapping_error;hash_net4_test ksoftirqd/11;ret_from_fork;kthread;kthread;smpboot_thread_fn;smpboot_thread_fn;run_ksoftirqd;__do_softirq;net_rx_action;gro_cell_poll;napi_gro_receive;netif_receive_skb_internal;inet_gro_receive;__netif_receive_skb_core;ip_rcv_finish;ip_rcv;ip_forward_finish;ip_forward;ip_finish_output;nf_iterate;ip_output;ip_finish_output2;__dev_queue_xmit;dev_hard_start_xmit;dev_queue_xmit_nit;packet_rcv;tpacket_rcv;sch_direct_xmit;validate_xmit_skb_list;validate_xmit_skb;netif_skb_features;ixgbe_xmit_frame_ring;swiotlb_dma_mapping_error;__dev_queue_xmit;dev_hard_start_xmit;__bpf_prog_run;__bpf_prog_run

Aya loba hal di dieu, tapi hal utama anu urang manggihan pola "cadvisor saméméh ksoftirqd" nu urang nempo saméméhna dina tracer ICMP. Naon éta hartosna?

Unggal garis mangrupakeun ngambah CPU dina titik nu tangtu dina jangka waktu. Unggal panggero ka handap tumpukan dina garis dipisahkeun ku titik koma. Di tengah garis urang ningali syscall disebut: read(): .... ;do_syscall_64;sys_read; .... Janten cadvisor nyéépkeun seueur waktos dina telepon sistem read()patali jeung fungsi mem_cgroup_* (luhureun tumpukan panggero / tungtung garis).

Éta pikaresepeun pikeun ningali dina ngalacak telepon naon anu dibaca, janten hayu urang ngajalankeun strace sareng hayu urang tingali naon anu dilakukeun ku cadvisor sareng mendakan telepon sistem langkung panjang ti 100 ms:

theojulienne@kube-node-bad ~ $ sudo strace -p 10137 -T -ff 2>&1 | egrep '<0.[1-9]'
[pid 10436] <... futex resumed> ) = 0 <0.156784>
[pid 10432] <... futex resumed> ) = 0 <0.258285>
[pid 10137] <... futex resumed> ) = 0 <0.678382>
[pid 10384] <... futex resumed> ) = 0 <0.762328>
[pid 10436] <... read resumed> "cache 154234880nrss 507904nrss_h"..., 4096) = 658 <0.179438>
[pid 10384] <... futex resumed> ) = 0 <0.104614>
[pid 10436] <... futex resumed> ) = 0 <0.175936>
[pid 10436] <... read resumed> "cache 0nrss 0nrss_huge 0nmapped_"..., 4096) = 577 <0.228091>
[pid 10427] <... read resumed> "cache 0nrss 0nrss_huge 0nmapped_"..., 4096) = 577 <0.207334>
[pid 10411] <... epoll_ctl resumed> ) = 0 <0.118113>
[pid 10382] <... pselect6 resumed> ) = 0 (Timeout) <0.117717>
[pid 10436] <... read resumed> "cache 154234880nrss 507904nrss_h"..., 4096) = 660 <0.159891>
[pid 10417] <... futex resumed> ) = 0 <0.917495>
[pid 10436] <... futex resumed> ) = 0 <0.208172>
[pid 10417] <... futex resumed> ) = 0 <0.190763>
[pid 10417] <... read resumed> "cache 0nrss 0nrss_huge 0nmapped_"..., 4096) = 576 <0.154442>

Sakumaha anjeun tiasa nyangka, urang ningali telepon anu laun di dieu read(). Tina eusi operasi maca jeung konteks mem_cgroup eta jelas yén tantangan ieu read() tingal file memory.stat, nu nembongkeun pamakean memori sareng wates cgroup (téhnologi isolasi sumberdaya Docker). Alat cadvisor naroskeun file ieu pikeun kéngingkeun inpormasi pamakean sumberdaya pikeun wadahna. Hayu urang pariksa naha éta kernel atanapi cadvisor ngalakukeun hal anu teu kaduga:

theojulienne@kube-node-bad ~ $ time cat /sys/fs/cgroup/memory/memory.stat >/dev/null

nyata 0m0.153s
pamaké 0m0.000s
sys 0m0.152s
theojulienne@kube-node-bad ~ $

Ayeuna urang tiasa ngahasilkeun deui bug sareng ngartos yén kernel Linux nyanghareupan patologi.

Naha operasi macana lambat pisan?

Dina tahap ieu, leuwih gampang pikeun manggihan pesen ti pamaké séjén ngeunaan masalah sarupa. Salaku tétéla, dina tracker cadvisor bug ieu dilaporkeun salaku masalah pamakéan CPU kaleuleuwihan, Ieu ngan teu saurang noticed nu latency ogé acak reflected dina tumpukan jaringan. Ieu memang noticed nu cadvisor ieu consuming leuwih waktos CPU ti ekspektasi, tapi ieu teu dibikeun teuing pentingna, saprak server kami boga loba sumberdaya CPU, jadi masalah teu taliti diajarkeun.

Masalahna nyaeta cgroups tumut kana akun pamakéan memori dina namespace (wadah). Nalika sadaya prosés dina cgroup ieu kaluar, Docker ngaleupaskeun cgroup memori. Sanajan kitu, "memori" teu ngan prosés memori. Sanajan mémori prosés sorangan geus euweuh dipaké, nembongan yen kernel masih nangtukeun eusi sindangan, kayaning dentries na inodes (diréktori jeung file metadata), nu sindangan dina cgroup memori. Tina pedaran masalah:

zombie cgroups: cgroups nu teu boga prosés sarta geus dihapus, tapi masih boga memori disadiakeun (bisi kuring, ti cache dentry, tapi ogé bisa disadiakeun ti cache kaca atanapi tmpfs).

Cék kernel sadaya kaca dina cache nalika ngabebaskeun cgroup tiasa lambat pisan, ku kituna prosés puguh dipilih: antosan dugi ka halaman ieu dipénta deui, teras mupus cgroup nalika mémori diperyogikeun. Dugi ka titik ieu, cgroup masih dipertimbangkeun nalika ngumpulkeun statistik.

Tina sudut pandang pagelaran, aranjeunna ngorbankeun mémori pikeun pagelaran: nyepetkeun ngabersihkeun awal ku nyéépkeun mémori anu sindangan. Ieu sae. Nalika kernel ngagunakeun panungtungan memori sindangan, cgroup ahirna diberesihan, ku kituna teu bisa disebut "bocor". Hanjakal, palaksanaan husus tina mékanisme pilarian memory.stat dina versi kernel ieu (4.9), digabungkeun jeung jumlah badag memori dina server kami, hartina waktu nu diperlukeun leuwih lila pikeun mulangkeun data cache panganyarna na zombies cgroup jelas.

Tétéla yén sababaraha titik kami ngagaduhan seueur zombie cgroup anu maca sareng latency ngaleuwihan sadetik.

The workaround pikeun masalah cadvisor téh geuwat ngosongkeun dentries / inodes caches sakuliah sistem, nu langsung ngaleungitkeun latency baca ogé latency jaringan dina host, saprak clearing cache nu ngahurungkeun kaca cgroup zombie sindangan jeung frees aranjeunna teuing. Ieu sanes solusi, tapi confirms ngabalukarkeun masalah.

Tétéla yén dina versi kernel anyar (4.19+) kinerja panggero ningkat memory.stat, janten ngalih ka kernel ieu ngalereskeun masalah. Dina waktos anu sami, urang gaduh alat pikeun ngadeteksi titik-titik anu bermasalah dina klaster Kubernetes, sacara gracefully solokan sareng reboot. Kami nyisiran sadaya klaster, mendakan titik-titik kalayan latency anu cukup luhur sareng rebooted. Ieu masihan kami waktos pikeun ngapdet OS dina server sésana.

summing up

Kusabab bug ieu ngeureunkeun ngolah antrian RX NIC pikeun ratusan milidetik, éta sakaligus nyababkeun latency tinggi dina sambungan pondok sareng latency sambungan pertengahan, sapertos antara pamundut MySQL sareng pakét réspon.

Ngartos sareng ngajaga kinerja sistem anu paling dasar, sapertos Kubernetes, penting pisan pikeun kaandalan sareng kagancangan sadaya jasa dumasar kana éta. Unggal sistem anu anjeun jalankeun kauntungan tina perbaikan kinerja Kubernetes.

sumber: www.habr.com

Tambahkeun komentar