Ychydig flynyddoedd yn ôl Kubernetes
Yn y bôn, mae cymwysiadau yn profi hwyrni rhwydwaith ar hap o hyd at 100ms neu fwy, gan arwain at seibiannau neu ailgeisiadau. Roedd disgwyl i wasanaethau allu ymateb i geisiadau yn gynt o lawer na 100ms. Ond mae hyn yn amhosibl os yw'r cysylltiad ei hun yn cymryd cymaint o amser. Ar wahân, gwelsom ymholiadau MySQL cyflym iawn a ddylai gymryd milieiliadau, a chwblhaodd MySQL mewn milieiliadau, ond o safbwynt y cais a oedd yn gofyn, cymerodd yr ymateb 100 ms neu fwy.
Daeth yn amlwg ar unwaith mai dim ond wrth gysylltu â nod Kubernetes y digwyddodd y broblem, hyd yn oed os daeth yr alwad o'r tu allan i Kubernetes. Y ffordd hawsaf o atgynhyrchu'r broblem yw mewn prawf
Dileu cymhlethdod diangen yn y gadwyn yn arwain at fethiant
Drwy atgynhyrchu'r un enghraifft, roeddem am gyfyngu ffocws y broblem a chael gwared ar haenau diangen o gymhlethdod. I ddechrau, roedd gormod o elfennau yn y llif rhwng Vegeta a'r codennau Kubernetes. I nodi problem ddyfnach rhwydwaith, mae angen i chi ddiystyru rhai ohonynt.
Mae'r cleient (Vegeta) yn creu cysylltiad TCP ag unrhyw nod yn y clwstwr. Mae Kubernetes yn gweithredu fel rhwydwaith troshaen (ar ben y rhwydwaith canolfan ddata presennol) sy'n defnyddio
Cyfleustodau tcpdump
yn y prawf Vegeta mae oedi yn ystod ysgwyd llaw TCP (rhwng SYN a SYN-ACK). I gael gwared ar y cymhlethdod diangen hwn, gallwch chi ei ddefnyddio hping3
am “pings” syml gyda phecynnau SYN. Rydym yn gwirio a oes oedi yn y pecyn ymateb, ac yna ailosod y cysylltiad. Gallwn hidlo'r data i gynnwys pecynnau mwy na 100ms yn unig a chael ffordd haws o atgynhyrchu'r broblem na phrawf haen 7 rhwydwaith llawn Vegeta. Dyma “pings” nod Kubernetes gan ddefnyddio TCP SYN/SYN-ACK ar y gwasanaeth “node port” (30927) ar gyfnodau o 10ms, wedi'i hidlo gan yr ymatebion arafaf:
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 sport=30927 flags=SA seq=1485 win=29200 rtt=127.1 ms
len=46 ip=172.16.47.27 ttl=59 DF id=0 sport=30927 flags=SA seq=1486 win=29200 rtt=117.0 ms
len=46 ip=172.16.47.27 ttl=59 DF id=0 sport=30927 flags=SA seq=1487 win=29200 rtt=106.2 ms
len=46 ip=172.16.47.27 ttl=59 DF id=0 sport=30927 flags=SA seq=1488 win=29200 rtt=104.1 ms
len=46 ip=172.16.47.27 ttl=59 DF id=0 sport=30927 flags=SA seq=5024 win=29200 rtt=109.2 ms
len=46 ip=172.16.47.27 ttl=59 DF id=0 sport=30927 flags=SA seq=5231 win=29200 rtt=109.2 ms
Yn gallu gwneud yr arsylwad cyntaf ar unwaith. A barnu yn ôl y dilyniant rhifau ac amseriadau, mae'n amlwg nad yw'r rhain yn dagfeydd un-amser. Mae'r oedi yn aml yn cronni ac yn cael ei brosesu yn y pen draw.
Nesaf, rydym am ddarganfod pa gydrannau a allai fod yn gysylltiedig â thagfeydd. Efallai mai dyma rai o'r cannoedd o reolau iptables yn NAT? Neu a oes unrhyw broblemau gyda thwnelu IPIP ar y rhwydwaith? Un ffordd o wirio hyn yw profi pob cam o'r system trwy ei ddileu. Beth sy'n digwydd os ydych chi'n tynnu NAT a rhesymeg wal dân, gan adael y rhan IPIP yn unig:
Yn ffodus, mae Linux yn ei gwneud hi'n hawdd cyrchu'r haen troshaen IP yn uniongyrchol os yw'r peiriant ar yr un rhwydwaith:
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 sport=0 flags=RA seq=7346 win=0 rtt=127.3 ms
len=40 ip=10.125.20.64 ttl=64 DF id=0 sport=0 flags=RA seq=7347 win=0 rtt=117.3 ms
len=40 ip=10.125.20.64 ttl=64 DF id=0 sport=0 flags=RA seq=7348 win=0 rtt=107.2 ms
A barnu yn ôl y canlyniadau, mae'r broblem yn parhau! Nid yw hyn yn cynnwys iptables a NAT. Felly y broblem yw TCP? Gadewch i ni weld sut mae ping ICMP rheolaidd yn mynd:
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
Mae'r canlyniadau'n dangos nad yw'r broblem wedi diflannu. Efallai mai twnnel IPIP yw hwn? Gadewch i ni symleiddio'r prawf ymhellach:
A anfonir pob pecyn rhwng y ddau westeiwr hyn?
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
Rydym wedi symleiddio'r sefyllfa i ddau nod Kubernetes anfon unrhyw becyn at ei gilydd, hyd yn oed ping ICMP. Maent yn dal i weld hwyrni os yw'r gwesteiwr targed yn "ddrwg" (rhai yn waeth nag eraill).
Nawr y cwestiwn olaf: pam mai dim ond ar weinyddion kube-node y mae'r oedi yn digwydd? Ac a yw'n digwydd pan mai kube-node yw'r anfonwr neu'r derbynnydd? Yn ffodus, mae hyn hefyd yn eithaf hawdd ei ddarganfod trwy anfon pecyn gan westeiwr y tu allan i Kubernetes, ond gyda'r un derbynnydd “drwg hysbys”. Fel y gwelwch, nid yw'r broblem wedi diflannu:
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 sport=9876 flags=RA seq=312 win=0 rtt=108.5 ms
len=46 ip=172.16.47.27 ttl=61 DF id=0 sport=9876 flags=RA seq=5903 win=0 rtt=119.4 ms
len=46 ip=172.16.47.27 ttl=61 DF id=0 sport=9876 flags=RA seq=6227 win=0 rtt=139.9 ms
len=46 ip=172.16.47.27 ttl=61 DF id=0 sport=9876 flags=RA seq=7929 win=0 rtt=131.2 ms
Yna byddwn yn rhedeg yr un ceisiadau o'r ffynhonnell kube-node blaenorol i'r gwesteiwr allanol (sy'n eithrio'r gwesteiwr ffynhonnell gan fod y ping yn cynnwys cydran RX a 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
Trwy archwilio cipio pecynnau hwyrni, cawsom rywfaint o wybodaeth ychwanegol. Yn benodol, bod yr anfonwr (gwaelod) yn gweld y terfyn amser hwn, ond nid yw'r derbynnydd (uchaf) - gweler y golofn Delta (mewn eiliadau):
Yn ogystal, os edrychwch ar y gwahaniaeth yn nhrefn pecynnau TCP ac ICMP (yn ôl rhifau dilyniant) ar ochr y derbynnydd, mae pecynnau ICMP bob amser yn cyrraedd yn yr un dilyniant ag y cawsant eu hanfon, ond gydag amseriad gwahanol. Ar yr un pryd, mae pecynnau TCP weithiau'n rhyngddalennog, ac mae rhai ohonyn nhw'n mynd yn sownd. Yn benodol, os edrychwch ar borthladdoedd pecynnau SYN, maent mewn trefn ar ochr yr anfonwr, ond nid ar ochr y derbynnydd.
Mae gwahaniaeth cynnil o ran sut
Sylw newydd arall: yn ystod y cyfnod hwn gwelwn oedi ICMP ar bob cyfathrebiad rhwng dau westeiwr, ond nid yw TCP yn gwneud hynny. Mae hyn yn dweud wrthym fod yr achos yn debygol o fod yn gysylltiedig â stwnsio ciw RX: mae'r tagfeydd bron yn sicr wrth brosesu pecynnau RX, nid wrth anfon ymatebion.
Mae hyn yn dileu anfon pecynnau o'r rhestr o achosion posibl. Rydym bellach yn gwybod bod y broblem prosesu pecynnau ar yr ochr dderbyn ar rai gweinyddwyr kube-nod.
Deall prosesu pecynnau yn y cnewyllyn Linux
I ddeall pam mae'r broblem yn digwydd yn y derbynnydd ar rai gweinyddwyr nod kube, gadewch i ni edrych ar sut mae cnewyllyn Linux yn prosesu pecynnau.
Gan ddychwelyd i'r gweithredu traddodiadol symlaf, mae'r cerdyn rhwydwaith yn derbyn y pecyn ac yn ei anfon
Mae'r newid cyd-destun hwn yn araf: efallai na fyddai hwyrni wedi bod yn amlwg ar gardiau rhwydwaith 10Mbps yn y 90au, ond ar gardiau 10G modern gydag uchafswm trwybwn o 15 miliwn o becynnau yr eiliad, gellir torri miliynau ar bob craidd o weinydd wyth craidd bach. o weithiau yr eiliad.
Er mwyn peidio â thrin ymyriadau yn gyson, flynyddoedd lawer yn ôl ychwanegodd Linux
Mae hyn yn llawer cyflymach, ond mae'n achosi problem wahanol. Os oes gormod o becynnau, yna treulir yr holl amser yn prosesu pecynnau o'r cerdyn rhwydwaith, ac nid oes gan brosesau gofod defnyddwyr amser i wagio'r ciwiau hyn mewn gwirionedd (darllen o gysylltiadau TCP, ac ati). Yn y pen draw mae'r ciwiau'n llenwi ac rydyn ni'n dechrau gollwng pecynnau. Mewn ymgais i ddod o hyd i falans, mae'r cnewyllyn yn gosod cyllideb ar gyfer uchafswm nifer y pecynnau a brosesir yng nghyd-destun softirq. Unwaith y rhagorir ar y gyllideb hon, deffroir llinyn ar wahân ksoftirqd
(fe welwch un ohonyn nhw yn ps
fesul craidd) sy'n trin y softirqs hyn y tu allan i'r llwybr syscall/ymyrraeth arferol. Mae'r edefyn hwn wedi'i amserlennu gan ddefnyddio'r trefnydd proses safonol, sy'n ceisio dyrannu adnoddau'n deg.
Ar ôl astudio sut mae'r cnewyllyn yn prosesu pecynnau, gallwch weld bod yna debygolrwydd penodol o dagfeydd. Os derbynnir galwadau softirq yn llai aml, bydd yn rhaid i becynnau aros am beth amser i gael eu prosesu yn y ciw RX ar y cerdyn rhwydwaith. Gall hyn fod oherwydd bod rhywfaint o dasg yn rhwystro craidd y prosesydd, neu fod rhywbeth arall yn atal y craidd rhag rhedeg softirq.
Culhau'r prosesu i lawr i'r craidd neu'r dull
Dim ond dyfalu am y tro yw oedi Softirq. Ond mae'n gwneud synnwyr, ac rydyn ni'n gwybod ein bod ni'n gweld rhywbeth tebyg iawn. Felly y cam nesaf yw cadarnhau'r ddamcaniaeth hon. Ac os caiff ei gadarnhau, yna darganfyddwch y rheswm dros yr oedi.
Gadewch i ni ddychwelyd at ein pecynnau araf:
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
Fel y trafodwyd yn gynharach, mae'r pecynnau ICMP hyn yn cael eu stwnsio i mewn i un ciw RX NIC a'u prosesu gan un craidd CPU. Os ydym am ddeall sut mae Linux yn gweithio, mae'n ddefnyddiol gwybod ble (ar ba graidd CPU) a sut (softirq, ksoftirqd) y caiff y pecynnau hyn eu prosesu er mwyn olrhain y broses.
Nawr mae'n bryd defnyddio offer sy'n eich galluogi i fonitro'r cnewyllyn Linux mewn amser real. Yma rydym yn defnyddio
Mae'r cynllun yma yn syml: rydym yn gwybod bod y cnewyllyn yn prosesu'r pings ICMP hyn, felly byddwn yn rhoi bachyn ar swyddogaeth y cnewyllyn hping3
uwch.
Cod icmp_echo
trosglwyddiadau struct sk_buff *skb
: Mae hwn yn becyn gyda "cais adlais". Gallwn ei olrhain, tynnu'r dilyniant allan echo.sequence
(sy'n cymharu â icmp_seq
gan hping3 выше
), a'i anfon i ofod defnyddiwr. Mae hefyd yn gyfleus i ddal enw/ID y broses gyfredol. Isod mae'r canlyniadau a welwn yn uniongyrchol tra bod y cnewyllyn yn prosesu pecynnau:
ENW PROSES PID TGID 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 pro swapper/775 0 0 11 swapper/776 0 0 11 swapper per/777 0 0 11 swapper/778 4512 4542 779 spokes-report-s XNUMX
Dylid nodi yma yn y cyd-destun softirq
bydd prosesau a wnaeth alwadau system yn ymddangos fel "prosesau" pan mewn gwirionedd y cnewyllyn sy'n prosesu pecynnau'n ddiogel yng nghyd-destun y cnewyllyn.
Gyda'r offeryn hwn gallwn gysylltu prosesau penodol â phecynnau penodol sy'n dangos oedi o hping3
. Gadewch i ni ei wneud yn syml grep
ar y cipio hwn ar gyfer gwerthoedd penodol icmp_seq
. Nodwyd pecynnau sy'n cyfateb i'r gwerthoedd icmp_seq uchod ynghyd â'u RTT a welsom uchod (mewn cromfachau mae'r gwerthoedd RTT disgwyliedig ar gyfer pecynnau y gwnaethom eu hidlo allan oherwydd gwerthoedd RTT llai na 50 ms):
ENW PROSES PID TGID ICMP_SEQ ** RTT -- 10137 10436 cadvisor 1951 10137 10436 cadvisor 1952 76 76 ksoftirqd/11 1953 ** 99ms 76 76 ksoftirqd/11 1954 ksoftirqd/89 76 ksoftirqd/76 11 ksoftirqd/1955 79 ksoftirqd/76 76 ksoftirqd/11 1956 ** 69ms 76 76 ksoftirqd/11 1957 ** 59ms 76 76 ksoftirqd/11 1958 ** 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 ksoftirqd/2068 10137 ksoftirqd/10436 d/2069 / 76 76 ** (11ms) 2070 75 ksoftirqd/76 76 ** (11ms) -- 2071 65 cadvisor 76 76 11 cadvisor 2072 55 76 ksoftirqd/76 11 2073 ksoftirqd/45 76 76 11 ksoftirqd/2074 35 76 ksoftirqd/76 11 2075 ksoftirqd/25 76 76 ksoftirqd/11 2076 15 ms. 76ms 76 11 ksoftirqd/ 2077 5 ** XNUMXms XNUMX XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXms) XNUMX XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXms) XNUMX XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXmsXNUMX) XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXms) XNUMX XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXmsXNUMX) XNUMX XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXmsXNUMX) XNUMX XNUMX XNUMX ms ) XNUMX XNUMX ksoftirqd/XNUMX XNUMX ** (XNUMXms)
Mae'r canlyniadau'n dweud sawl peth wrthym. Yn gyntaf, mae'r holl becynnau hyn yn cael eu prosesu gan y cyd-destun ksoftirqd/11
. Mae hyn yn golygu, ar gyfer y pâr penodol hwn o beiriannau, bod pecynnau ICMP wedi'u stwnsio i graidd 11 ar y pen derbyn. Rydym hefyd yn gweld, pryd bynnag y bydd jam, bod pecynnau sy'n cael eu prosesu yng nghyd-destun yr alwad system cadvisor
... Yna ksoftirqd
yn cymryd drosodd y dasg ac yn prosesu'r ciw cronedig: union nifer y pecynnau sydd wedi cronni ar ôl hynny cadvisor
.
Mae'r ffaith bod yn union cyn ei fod bob amser yn gweithio cadvisor
, yn awgrymu ei ran yn y broblem. Yn eironig, y pwrpas
Yn yr un modd ag agweddau eraill ar gynwysyddion, mae'r rhain i gyd yn offer hynod ddatblygedig a gellir disgwyl iddynt brofi problemau perfformiad o dan rai amgylchiadau nas rhagwelwyd.
Beth mae cadvisor yn ei wneud sy'n arafu'r ciw paced?
Bellach mae gennym ddealltwriaeth eithaf da o sut mae'r ddamwain yn digwydd, pa broses sy'n ei achosi, ac ar ba CPU. Gwelwn, oherwydd blocio caled, nad oes gan y cnewyllyn Linux amser i amserlennu ksoftirqd
. A gwelwn fod pecynnau'n cael eu prosesu yn eu cyd-destun cadvisor
. Mae'n rhesymegol tybio hynny cadvisor
yn lansio syscall araf, ac ar ôl hynny mae'r holl becynnau a gronnwyd ar y pryd yn cael eu prosesu:
Theori yw hon, ond sut i'w phrofi? Yr hyn y gallwn ei wneud yw olrhain craidd y CPU trwy gydol y broses hon, darganfyddwch y pwynt lle mae nifer y pecynnau yn mynd dros y gyllideb a gelwir ksoftirqd, ac yna edrychwch ychydig ymhellach yn ôl i weld beth yn union oedd yn rhedeg ar y craidd CPU ychydig cyn y pwynt hwnnw . Mae fel pelydr-x y CPU bob ychydig milieiliadau. Bydd yn edrych rhywbeth fel hyn:
Yn gyfleus, gellir gwneud hyn i gyd gyda'r offer presennol. Er enghraifft, 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
Dyma'r canlyniadau:
(сотни следов, которые выглядят похожими)
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
Mae yna lawer o bethau yma, ond y prif beth yw ein bod ni'n dod o hyd i'r patrwm “cadvisor before ksoftirqd” a welsom yn gynharach yn y tracer ICMP. Beth mae'n ei olygu?
Mae pob llinell yn olrhain CPU ar adeg benodol. Mae pob galwad i lawr y pentwr ar linell yn cael ei wahanu gan hanner colon. Yng nghanol y llinellau gwelwn y syscall yn cael ei alw: read(): .... ;do_syscall_64;sys_read; ...
. Felly mae cadvisor yn treulio llawer o amser ar yr alwad system read()
gysylltiedig â swyddogaethau mem_cgroup_*
(pen y pentwr galwadau/diwedd y llinell).
Mae'n anghyfleus gweld mewn galwad olrhain beth yn union sy'n cael ei ddarllen, felly gadewch i ni redeg strace
a gadewch i ni weld beth mae cadvisor yn ei wneud a dod o hyd i alwadau system sy'n hirach na 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>
Fel y gallech ddisgwyl, rydym yn gweld galwadau araf yma read()
. O gynnwys gweithrediadau darllen a chyd-destun mem_cgroup
mae'n amlwg bod yr heriau hyn read()
cyfeiriwch at y ffeil memory.stat
, sy'n dangos defnydd cof a chyfyngiadau cgroup (technoleg ynysu adnoddau Docker). Mae'r offeryn cadvisor yn cwestiynu'r ffeil hon i gael gwybodaeth am ddefnydd adnoddau ar gyfer cynwysyddion. Gadewch i ni wirio a yw'r cnewyllyn neu'r cynghorydd yn gwneud rhywbeth annisgwyl:
theojulienne@kube-node-bad ~ $ time cat /sys/fs/cgroup/memory/memory.stat >/dev/null
real 0m0.153s
user 0m0.000s
sys 0m0.152s
theojulienne@kube-node-bad ~ $
Nawr gallwn atgynhyrchu'r nam a deall bod cnewyllyn Linux yn wynebu patholeg.
Pam mae'r llawdriniaeth darllen mor araf?
Ar y cam hwn, mae'n llawer haws dod o hyd i negeseuon gan ddefnyddwyr eraill am broblemau tebyg. Fel y digwyddodd, yn y traciwr cadvisor adroddwyd bod y byg hwn
Y broblem yw bod cgroups yn ystyried defnydd cof o fewn y gofod enw (cynhwysydd). Pan fydd yr holl brosesau yn yr allanfa cgroup hwn, mae Docker yn rhyddhau'r cgroup cof. Fodd bynnag, nid cof proses yn unig yw "cof". Er nad yw'r cof proses ei hun yn cael ei ddefnyddio mwyach, mae'n ymddangos bod y cnewyllyn yn dal i aseinio cynnwys wedi'i storio, megis dannedd gosod ac inodes (metadata cyfeiriadur a ffeil), sy'n cael eu storio yn y cgroup cof. O'r disgrifiad o'r broblem:
cgroups zombie: cgroups nad oes ganddynt unrhyw brosesau ac sydd wedi'u dileu, ond sy'n dal i gael cof wedi'i ddyrannu (yn fy achos i, o'r storfa ddeintyddol, ond gellir ei ddyrannu hefyd o storfa'r dudalen neu tmpfs).
Gall gwiriad y cnewyllyn o'r holl dudalennau yn y storfa wrth ryddhau cgroup fod yn araf iawn, felly dewisir y broses ddiog: arhoswch nes gofynnir am y tudalennau hyn eto, ac yna cliriwch y cgroup o'r diwedd pan fydd gwir angen y cof. Hyd at y pwynt hwn, mae cgroup yn dal i gael ei ystyried wrth gasglu ystadegau.
O safbwynt perfformiad, fe wnaethant aberthu cof ar gyfer perfformiad: gan gyflymu'r glanhau cychwynnol trwy adael rhywfaint o gof wedi'i storio ar ôl. Mae hyn yn iawn. Pan fydd y cnewyllyn yn defnyddio'r olaf o'r cof wedi'i storio, caiff y cgroup ei glirio yn y pen draw, felly ni ellir ei alw'n "gollyngiad". Yn anffodus, mae gweithrediad penodol y mecanwaith chwilio memory.stat
yn y fersiwn cnewyllyn hwn (4.9), ynghyd â'r swm enfawr o gof ar ein gweinyddwyr, yn golygu ei bod yn cymryd llawer mwy o amser i adfer y data cached diweddaraf a chlirio zombies cgroup.
Mae'n ymddangos bod gan rai o'n nodau gymaint o zombies cgroup nes bod y darlleniad a'r hwyrni yn fwy nag eiliad.
Y datrysiad ar gyfer problem cadvisor yw rhyddhau celciau dannedd gosod / inod ar unwaith ledled y system, sy'n dileu hwyrni darllen yn ogystal â hwyrni rhwydwaith ar y gwesteiwr, gan fod clirio'r storfa'n troi'r tudalennau cgroup zombie sydd wedi'u storio ymlaen ac yn eu rhyddhau hefyd. Nid yw hyn yn ateb, ond mae'n cadarnhau achos y broblem.
Daeth i'r amlwg bod perfformiad galwadau wedi gwella mewn fersiynau cnewyllyn mwy newydd (4.19+). memory.stat
, felly roedd newid i'r cnewyllyn hwn yn datrys y broblem. Ar yr un pryd, roedd gennym offer i ganfod nodau problemus mewn clystyrau Kubernetes, eu draenio'n osgeiddig a'u hailgychwyn. Fe wnaethon ni gribo'r holl glystyrau, dod o hyd i nodau â hwyrni digon uchel a'u hailgychwyn. Rhoddodd hyn amser i ni ddiweddaru'r OS ar weddill y gweinyddwyr.
Crynhoi
Oherwydd bod y nam hwn wedi atal prosesu ciw RX NIC am gannoedd o filieiliadau, roedd ar yr un pryd yn achosi hwyrni uchel ar gysylltiadau byr a hwyrni cysylltiad canol, megis rhwng ceisiadau MySQL a phecynnau ymateb.
Mae deall a chynnal perfformiad y systemau mwyaf sylfaenol, fel Kubernetes, yn hanfodol i ddibynadwyedd a chyflymder yr holl wasanaethau sy'n seiliedig arnynt. Mae pob system rydych chi'n ei rhedeg yn elwa o welliannau perfformiad Kubernetes.
Ffynhonnell: hab.com