
Ante biennium, Kubernetes in diario officiali GitHub. Ex eo tempore, technologia norma ad officia disponenda facta est. Kubernetes nunc partem magnam officiorum nostrorum internorum et publicorum potentia praebet. Cum greges nostri creverint et requisita perfunctionis severiora facta sint, problemata latentiae sporadica in quibusdam officiis Kubernetes fundatis animadvertimus quae onere applicationis explicari non possunt.
Applicationes, ut ita dicam, moram in reti usque ad 100 ms vel plus fortuitam patiuntur, quae ad intervalla temporis vel conatus iteratos ducit. Expectatum est officia petitionibus multo celerius quam 100 ms respondere posse. Sed hoc fieri non potest si ipsa conexio tantum temporis requirit. Speciatim, interrogationes MySQL celerrimas observavimus quae millisecunda capere debuissent, et MySQL quidem millisecundis respondit, sed ex prospectu applicationis petentis, responsum 100 ms vel plus sumpsit.
Statim apparuit problema solum oriri cum nodo Kubernetes coniungimur, etiamsi vocatio extra Kubernetes venisset. Facillima via ad problema reproducendum est per experimentum. , quod ex quolibet hospite interno currit, servitium Kubernetes in portu specifico probat, et interdum latentiam magnam notat. In hoc articulo, considerabimus quomodo causam huius problematis indagare potuimus.
Removendo complexitatem inutilem e catena defectuum
Eodem exemplo repetendo, problema restringere et superfluas complexitatis stratas removere voluimus. Initio, fluxus inter Vegetam et Kubernetes pods nimis multa elementa continebat. Ut altius problema retiaculi cognosceremus, nonnulla ex eis eliminare debuimus.

Cliens (Vegeta) nexum TCP ad quemlibet nodum in grege creat. Kubernetes operatur ut rete superpositum (super rete centri datorum exsistente) quod utitur... , id est, fasciculos IP retiaculi superpositi intra fasciculos IP centri datorum includit. Post coniunctionem cum primo nodo, translatio inscriptionis retiariae perficitur. Conversio Inscriptionum Retiariarum (NAT) est methodus ad inscriptionem IP et portum nodi Kubernetes convertendum ad inscriptionem IP et portum in reti superposita (praesertim, in "pod" ubi applicationem manet). Fasciculi advenientes processum inversum subeunt. Hoc est systema complexum cum magno numero statuum et multis elementis quae perpetuo renovantur et modificantur dum officia disponuntur et moventur.
utilitas tcpdump In experimento Vegeta, mora est inter communicationem TCP (inter SYN et SYN-ACK). Ad hanc complexitatem inutilem removendam, uti potes... hping3 Pro simplicibus impulsionibus cum fasciculis SYN, moram in fasciculo responso inspicimus et deinde nexum reponimus. Data filtrare possumus ut solum fasciculos longiores quam 100 ms includamus, quod modum simpliciorem praebet ad problema reproducendum quam plena probatio retialis Strati 7 in Vegeta. Hic sunt impulsiones nodi Kubernetes utens TCP SYN/SYN-ACK in "portu nodi" servitii (30927) cum intervallo 10 ms, filtratae a responsis lentissimis:
theojulienne@shell ~ $ sudo hping3 172.16.47.27 -S -p 30927 -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'
longitudo=46 ip=172.16.47.27 ttl=59 DF id=0 ludus=30927 vexilla=SA seq=1485 victoria=29200 rtt=127.1 ms
longitudo=46 ip=172.16.47.27 ttl=59 DF id=0 ludus=30927 vexilla=SA seq=1486 victoria=29200 rtt=117.0 ms
longitudo=46 ip=172.16.47.27 ttl=59 DF id=0 ludus=30927 vexilla=SA seq=1487 victoria=29200 rtt=106.2 ms
longitudo=46 ip=172.16.47.27 ttl=59 DF id=0 ludus=30927 vexilla=SA seq=1488 victoria=29200 rtt=104.1 ms
longitudo=46 ip=172.16.47.27 ttl=59 DF id=0 ludus=30927 vexilla=SA seq=5024 victoria=29200 rtt=109.2 ms
longitudo=46 ip=172.16.47.27 ttl=59 DF id=0 ludus=30927 vexilla=SA seq=5231 victoria=29200 rtt=109.2 ms
Prima observatio statim fieri potest. Numeri seriei et tempora ostendunt has non esse impedimenta semel tantum occurrentia. Mora saepe accumulatur et tandem solvitur.
Deinde, determinare volumus quae partes congestionem causare possint. Num una ex centum regulis iptables in NAT esse potest? An quaedam problemata cum cuniculo IPIP in reti? Una via ad hoc verificandum est unumquemque gradum in systemate eliminare. Quid fit si NAT et logicam muri ignis removemus, sola parte IPIP relicta?

Feliciter, Linux facilem reddit accessum ad stratum IP directe si machina in eadem rete est:
theojulienne@kube-node-client ~ $ sudo hping3 10.125.20.64 -S -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'
longitudo=40 ip=10.125.20.64 ttl=64 DF id=0 ludus=0 vexilla=RA seq=7346 victoria=0 rtt=127.3 ms
longitudo=40 ip=10.125.20.64 ttl=64 DF id=0 ludus=0 vexilla=RA seq=7347 victoria=0 rtt=117.3 ms
longitudo=40 ip=10.125.20.64 ttl=64 DF id=0 ludus=0 vexilla=RA seq=7348 victoria=0 rtt=107.2 ms
Iudicando ex eventibus, problema adhuc perseverat! Hoc iptables et NAT excludit. Ergo, problema estne TCP? Videamus quomodo ping ICMP ordinarius operatur:
theojulienne@kube-node-client ~ $ sudo hping3 10.125.20.64 --icmp -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'
longitudo=28 ip=10.125.20.64 ttl=64 id=42594 icmp_seq=104 rtt=110.0 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=49448 icmp_seq=4022 rtt=141.3 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=49449 icmp_seq=4023 rtt=131.3 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=49450 icmp_seq=4024 rtt=121.2 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=49451 icmp_seq=4025 rtt=111.2 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=49452 icmp_seq=4026 rtt=101.1 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=50023 icmp_seq=4343 rtt=126.8 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=50024 icmp_seq=4344 rtt=116.8 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=50025 icmp_seq=4345 rtt=106.8 ms
longitudo=28 ip=10.125.20.64 ttl=64 id=59727 icmp_seq=9836 rtt=106.1 ms
Resultata ostendunt problema perseverare. Fortasse cuniculus IPIP est? Simplicem faciamus experimentum etiam magis:

Omnesne fasciculi inter hos duos hospites mittuntur?
theojulienne@kube-node-client ~ $ sudo hping3 172.16.47.27 --icmp -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'
longitudo=46 ip=172.16.47.27 ttl=61 id=41127 icmp_seq=12564 rtt=140.9 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=41128 icmp_seq=12565 rtt=130.9 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=41129 icmp_seq=12566 rtt=120.8 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=41130 icmp_seq=12567 rtt=110.8 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=41131 icmp_seq=12568 rtt=100.7 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=9062 icmp_seq=31443 rtt=134.2 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=9063 icmp_seq=31444 rtt=124.2 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=9064 icmp_seq=31445 rtt=114.2 ms
longitudo=46 ip=172.16.47.27 ttl=61 id=9065 icmp_seq=31446 rtt=104.2 ms
Rem ad duos nodos Kubernetes simplificavimus qui inter se quemvis fasciculum, etiam signum ICMP, mittent. Latentiam adhuc vident si hospes destinatus "malus" est (quidam peior quam alii).
Nunc quaestio ultima: cur mora tantum in servitoribus kube-node accidit? Et utrum accidit cum kube-node mittens an recipiens est? Feliciter, hoc etiam satis facile est intellegere mittendo fasciculum ab hospite extra Kubernetes, sed cum eodem recipiente "noto malo". Ut videre possumus, problema perseverat:
theojulienne@shell ~ $ sudo hping3 172.16.47.27 -p 9876 -S -i u10000 | egrep --line-buffered 'rtt=[0-9]{3}.'
longitudo=46 ip=172.16.47.27 ttl=61 DF id=0 ludus=9876 vexilla=RA seq=312 victoria=0 rtt=108.5 ms
longitudo=46 ip=172.16.47.27 ttl=61 DF id=0 ludus=9876 vexilla=RA seq=5903 victoria=0 rtt=119.4 ms
longitudo=46 ip=172.16.47.27 ttl=61 DF id=0 ludus=9876 vexilla=RA seq=6227 victoria=0 rtt=139.9 ms
longitudo=46 ip=172.16.47.27 ttl=61 DF id=0 ludus=9876 vexilla=RA seq=7929 victoria=0 rtt=131.2 ms
Deinde easdem petitiones a nodo-kube fonte priori ad hospitem externum (quod hospitem fontem excludit, cum ping et componentem RX et TX includat) exsequimur:
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
Examinando fasciculos captos cum dilationibus, nonnullas informationes addidimus. Speciatim, didicimus mittentem (infra) hoc tempus exspectationis videre, recipientem autem (summum) non videre—vide columnam Delta (in secundis):
Praeterea, si discrimen in ordine fasciculorum TCP et ICMP (secundum numeros seriei) apud recipientes inspicimus, videmus fasciculos ICMP semper eodem ordine quo missi sunt advenire, sed temporibus diversis. Interea, fasciculi TCP interdum intertexti sunt, et quidam haerent. Praesertim, si portus fasciculorum SYN examinamus, videmus eos in ordine esse apud mittentes, sed non apud recipientes.
Subtilis differentia est in quomodo Servientes moderni (sicut illi in centro datorum nostro) fasciculos TCP vel ICMP continentes tractant. Cum fasciculus advenit, adaptator retialis "eum per connexionem dividit," id est, conatur connexiones in ordines dividere et unumquodque ordinem ad nucleum processoris separatum mittere. Pro TCP, hoc dividitur et inscriptiones IP fontis et destinationis et portas. Aliis verbis, quaeque connexio dividitur (potentialiter) aliter. Pro ICMP, solae inscriptiones IP dividiuntur, cum nullae portae sint.
Alia nova observatio: hoc tempore, moras ICMP in omnibus communicationibus inter duos computatores videmus, dum TCP non videt. Hoc suggerit causam verisimiliter ad hashing filae RX pertinere: congestio fere certe in processu fasciculorum RX, non in mittendo responsis, oritur.
Hoc missionem fasciculorum ex indice causarum possibilium eliminat. Nunc scimus quaestionem tractationis fasciculorum in parte receptionis nonnullorum servorum kube-node esse.
Intellegendo processum fasciculorum in nucleo Linux
Ut intellegamus cur problema in receptore in quibusdam servitoribus kube-node oriatur, inspiciamus quomodo nucleus Linux fasciculos tractat.
Ad simplicissimam exsecutionem traditionalem revertentes, charta retialis fasciculum accipit et mittit. Nucleus Linux scit fasciculum esse qui tractandus est. Nucleus alia opera sistit, contextum ad tractatorem interruptionis commutat, fasciculum tractat, deinde ad sua officia currentia redit.

Haec mutatio contextus tarda est: mora fortasse in NIC 10Mbps annis 90 imperceptibilis fuisset, sed in hodiernis chartis 10G, cum maxima capacitate transmissionis 15 millionum fasciculorum per secundum, quisque nucleus parvi servi octo nucleorum millies per secundum interrumpi potest.
Ne interruptiones perpetuo tractandae essent, multis abhinc annis Linux addidit API retialis quam omnes rectores moderni ad celeritates magnas emendandas adhibent. Celeritates parvas, nucleus adhuc interruptiones a scheda retiali modo antiquo accipit. Cum satis fasciculorum numerus advenit ut limen excedat, nucleus interruptiones inactivat et loco eius adaptatorem retialem interrogare et fasciculos in frustulis accipere incipit. Processus in softirqs perficitur, id est, in post invocationes systematis et interruptiones apparati, cum nucleus (contra spatium usoris) iam currit.

Hoc multo celerius est, sed aliud problema inducit. Si nimis multi fasciculi sunt, omne tempus fasciculos ex scheda retiaria tractando consumitur, et processus spatii usoris tempus non habent ad has filas revera evacuandas (legendo ex conexionibus TCP, etc.). Tandem filae implentur, et fasciculos abicere incipimus. Aequilibrium invenire conans, nucleus numerum maximum fasciculorum in contextu softirq tractatorum constituit. Hoc numero superato, filum separatum excitatur. ksoftirqd (unum eorum videbis in ps (per nucleum) quod has "softirqs" extra viam normalem syscall/interruptionis tractat. Hoc filum ordinatur utens ordinatore processuum consueto, qui opes iuste distribuere conatur.

Examinando quomodo nucleus fasciculos tractat, videre possumus certam esse potentiam congestionis. Si softirqs minus frequenter accipiuntur, fasciculi aliquamdiu in ordine RX in scheda retiali exspectare debebunt antequam tractentur. Hoc fieri potest ob officium quod nucleum processoris obstruit, vel aliquid aliud quod nucleum impedit quominus softirqs executet.
Restrictio processus ad nucleum vel methodum
Morae Softirq in praesenti coniectura tantum sunt. Sed rationi consentaneum est, et scimus nos aliquid simile videre. Ergo gradus proximus est hanc theoriam confirmare. Et si confirmata est, causam morarum invenire.
Ad fasciculos nostros lentos revertamur:
len=46 ip=172.16.53.32 ttl=61 id=29573 icmp_seq=1953 rtt=99.3 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29574 icmp_seq=1954 rtt=89.3 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29575 icmp_seq=1955 rtt=79.2 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29576 icmp_seq=1956 rtt=69.1 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29577 icmp_seq=1957 rtt=59.1 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29790 icmp_seq=2070 rtt=75.7 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29791 icmp_seq=2071 rtt=65.6 ms
longitudo=46 ip=172.16.53.32 ttl=61 id=29792 icmp_seq=2072 rtt=55.5 ms
Ut ante dictum est, hae fasciculae ICMP in singulam seriem receptorum NIC (NIC RX) digeruntur et ab uno nucleo CPU (CPU) tractantur. Si operationem Linux intellegere volumus, utile est scire ubi (in quo nucleo CPU) et quomodo (softirq, ksoftirqd) hae fasciculae tractantur ad processum indagandum.
Nunc tempus est instrumentis utendi quae te sinunt nucleum Linux in tempore reali monitorare. Hic usi sumus... Hoc instrumentarium tibi permittit scribere parva programmata C quae functiones nuclei arbitrarias et eventa memoriae conservandi programmati Python in spatio usoris coniungunt, quod eas tractare et exitum reddere potest. Functiones nuclei arbitrarias coniungere complexum est, sed utilitas ad maximam securitatem designata est et ad problemata productionis indaganda quae difficulter in ambitu probationis vel progressionis reproducuntur.
Consilium hic simplex est: scimus nucleum has ICMP mutationes tractare, ergo functioni nuclei coniungimur. , quae fasciculum ICMP "echo request" recipit et "echo response" ICMP mittendum incipit. Fasciculum numero icmp_seq crescente agnoscere possumus, qui ostendit... hping3 altius.
Code Videtur complicatum, sed non tam terribile est quam videtur. Functio icmp_echo importat struct sk_buff *skbHic est fasciculus petitionis echo. Eum investigare et seriem extrahere possumus. echo.sequence (quod comparatur cum icmp_seq ex hping3 выше), et ad spatium usoris mitte. Etiam utile est nomen/identificationem processus currentis capere. Infra sunt eventus quos directe videmus dum fasciculi nuclei tractantur:
TGID PID NOMEN PROCESSUS 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 Prometheus 775 0 0 swapper/11 776 0 0 swapper/11 777 0 0 swapper/11 778 4512 4542 spokes-relationes-779
Hic notandum est, in contextu softirq Processus qui invocationes systematis fecerunt ut "processus" apparebunt, quamquam re vera nucleus est qui fasciculos tuto in contextu nuclei tractat.
Hoc instrumento processus specificos cum fasciculis specificis qui latentiam ostendunt coniungere possumus. hping3Simplicius fiat. grep in hac captura pro certis valoribus icmp_seqFasciculi valores icmp_seq supra scriptos congruentes una cum suis RTT, quos supra observavimus, notati sunt (in parenthesibus valores RTT exspectati fasciculorum quos propter valores RTT minores quam 50 ms exclusimus):
TGID PID PROCESS NAME ICMP_SEQ ** RTT -- 10137 10436 cadvisor 1951 10137 10436 cadvisor 1952 76 76 softirqd/11 1953 ** 99ms 76 76 ksoftirqd/11 1954 ** 89ms 76 76 (49ms) 76 76 ksoftirqd/11 1959 ** (39ms) 76 76 ksoftirqd/11 1960 ** (29ms) 76 76 ksoftirqd/11 1961 ** (19ms) 76 76 ksoftirqd/11 1962 ** (9ms) -- 10137 10436 cadvisor 2068 10137 10436 cadvisor 2069 76 76 ksoftirqd/ (45ms) 76 76 ksoftirqd/11 2074** (35ms) 76 76 ksoftirqd/11 2075 ** (25ms) 76 76 ksoftirqd/11 2076 ** (15ms) 76 76 ksoftirqd/11 2077 ** (5ms)
Resultata plura nobis indicant. Primo, haec omnia fascicula contextum tractant. ksoftirqd/11Hoc significat pro hoc pari machinarum, fasciculos ICMP in nucleo undecimo ad finem recipientem hashed esse. Videmus etiam in unoquoque puncto congestionis fasciculos in contextu vocationis systematis tractari. cadvisor... tum ksoftirqd munus suscipit et seriem accumulatas tractat: exacte numerum fasciculorum qui accumulati sunt post cadvisor.
Quod statim ante hoc semper operatur cadvisor... implicationem eius in problemate implicat. Ironia rerum, propositum — "usum opum et proprietates perfunctionis receptaculorum currentium analysare" potius quam hanc quaestionem perfunctionis causare.
Sicut in aliis partibus operationis receptaculorum, haec omnia instrumenta perquam provecta sunt, et omnino fieri potest ut difficultates perfunctionis sub quibusdam condicionibus improvisis exspectari possint.
Quid agit cadvisor quod ordinem fasciculorum tardat?
Nunc satis bene intellegimus quomodo ruina fiat, quis processus eam efficiat, et in quo CPU. Videmus propter clausuram duram, nucleum Linux ruinam tempore disponere non posse. ksoftirqdEt videmus fasciculos in contextu tractari. cadvisorLogicum est assumere cadvisor invocationem systematis tardam incipit, post quam omnes fasciculi eo tempore accumulati tractantur:

Haec est theoria, sed quomodo eam probare possumus? Quod facere possumus est actionem nuclei CPU per totum hunc processum observare, punctum invenire ubi summa fasciculorum exceditur et ksoftirqd vocatur, deinde paulo antea inspicere ut videamus quidnam in nucleo CPU paulo ante illud momentum currebat. Simile est radiographiam CPU singulis paucis millisecundis capere. Aliquid simile huic videretur:

Commodum est haec omnia instrumentis iam exstantibus fieri posse. Exempli gratia, Nucleum CPU datum frequentia definita inspicit et indicem vocationum systematis currentis generare potest, spatium usoris et nucleum Linux comprehendens. Hic index per parvam furcam programmatis tractari potest. Solutio Brendani Gregg, quae ordinem vestigiorum acervi servat, nobis permittit vestigia acervi unius lineae singulis ms servare, deinde exemplum centum millisecundis antequam vestigium attingit extrahere et servare. 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
Hic eventus sunt:
(сотни следов, которые выглядят похожими)
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
Multa hic geruntur, sed res principalis est ut exemplar "cadvisor ante ksoftirqd" quod antea in ICMP indagatore vidimus inveniamus. Quid hoc sibi vult?
Quaeque linea est vestigium CPU tempore definito. Quaeque invocatio per acervum intra lineam puncto semicolon separatur. In medio linearum, videmus invocationem "syscall" invocatam: read(): .... ;do_syscall_64;sys_read; ...Ergo, cadvisor multum temporis in vocatione systematis consumit. read(), ad functiones pertinens mem_cgroup_* (summum acervi vocationum/finis lineae).
Non commodum est videre quidnam exacte in vestigio vocationis legatur, ergo curramus strace et inspiciamus quid cadvisor faciat et inveniamus invocationes systematis longiores quam 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>
Ut quis exspectare possit, hic vocationes tardas videmus. read()Ex contentis operationum lectionis et contextu mem_cgroup manifestum est has difficultates read() ad limam pertinere memory.stat, quae usum memoriae et limites cgroup ostendit (technologia isolationis opum in Docker). Instrumentum cadvisor hunc fasciculum interrogat ut informationem de usu opum pro receptaculis obtineat. Inspiciamus num nucleus an cadvisor aliquid inexpectatum faciat:
theojulienne@kube-node-bad ~ $ time cat /sys/fs/cgroup/memory/memory.stat >/dev/null
verum 0m0.153s
usor 0m0.000s
sys 0m0.152s
theojulienne@kube-node-bad ~ $
Nunc vitium reproducere et intellegere possumus nucleum Linux pathologiam experiri.
Cur tam tarda est operatio legendi?
Hoc tempore, multo facilius est invenire alios usores qui similia problemata nuntiant. Ut apparet, hoc vitium in indice problematum cadvisor nuntiatum est ut... Nemo modo animadvertit latentiam etiam temere in acervo retiario reflecti. Verum erat cadvisor plus temporis CPU quam expectatum consumere, sed non multum cogitatum est, cum nostri servi multas opes CPU habeant, itaque res non diligenter investigata est.
Problema est quod greges moderandi (cgroups) usum memoriae intra spatium nominum (continens) rationem habent. Cum omnes processus in dato cgroup terminantur, Docker cgroup memoriae liberat. Attamen haec "memoria" non solum memoria processus est. Dum ipsa memoria processus non iam in usu est, apparet nucleum etiam contenta celata, ut dentries et inodes (metadata directorii et fasciculorum), assignare, quae in cgroup memoriae celantur. Ex descriptione problematis:
Greges moderandi zombifiti: greges moderandi qui nullos processus in se habent et remoti sunt, sed memoria adhuc assignata est (in meo casu, ex memoria celata dentry, sed etiam ex memoria celata paginarum vel tmpfs assignari potest).
Reprobatio paginarum repositarum a nucleo factarum, cum cgroup liberatur, lenta esse potest, itaque processus piger eligitur: exspecta dum hae paginae iterum petantur, deinde, cum memoria revera requiritur, cgroup tandem liberatur. Usque ad hunc punctum, cgroup adhuc in collectione statisticarum includitur.
Quod ad efficaciam attinet, memoriam pro efficacia commutaverunt: purgationem initialem accelerantes, memoria reposita relicta. Hoc normale est. Cum nucleus ultimam partem memoriae repositae utitur, cgroup tandem purgatur, itaque "effluxus" dici non potest. Infeliciter, implementatio specifica mechanismi investigationis... memory.stat In hac versione nuclei (4.9), cum ingenti memoriae copia in servitoribus nostris coniuncta, multo diutius requiritur ad recentissima data reposita restituenda et cgroups inaequales purgandos.
Evenit ut nonnulli nodi nostri tot "cgroup zombies" habuerint ut lectio et mora secundum excederent.
Solutio ad problema cadvisoris est statim liberare cellas dentries/inodes per totum systema. Hoc statim tollit moram lectionis, necnon moram retis in computatro, cum purgatio cellae paginas cgroup zombies repositas implicat, quae etiam liberantur. Haec solutio non est, sed causam problematis confirmat.
Evenit ut in recentioribus versionibus nuclei (4.19+) efficacitas vocationis emendata sit. memory.stat, ergo mutatio ad hunc nucleum problema solutum est. Simul, instrumenta habuimus ad nodos problematicos in gregibus Kubernetes detegendos, eos eleganter exhauriendos, et eos initiandos. Omnes greges perscrutati sumus, nodos cum satis alta latentia invenimus, et eos initiavimus. Hoc nobis tempus dedit ad systema operandi in reliquis servitoribus renovandum.
quoquo
Quia hoc vitium processum ordinis RX NIC per centena millisecunda impedivit, et latentiam magnam in conexionibus brevibus et latentiam in medio nexu, ut inter interrogationes MySQL et fasciculos responsorum, effecit.
Intellectus et conservatio efficaciae systematum fundamentalium, velut Kubernetes, maximi momenti est ad firmitatem et celeritatem omnium ministeriorum in eis currentium. Meliorationes efficaciae Kubernetes omnibus systematibus in eo currentibus prosunt.
Source: www.habr.com
