Protsessori piirangud ja agressiivne piiramine Kubernetesis

Märge. tõlge: See Euroopa reiside koondaja Omio silmiavav ajalugu viib lugejad põhiteooriast Kubernetese konfiguratsiooni põnevate praktiliste keerukuse juurde. Selliste juhtumite tundmine ei aita mitte ainult silmaringi laiendada, vaid ka ennetada mittetriviaalseid probleeme.

Protsessori piirangud ja agressiivne piiramine Kubernetesis

Kas teil on kunagi juhtunud, et mõni rakendus on paigal kinni jäänud, lõpetanud tervisekontrollile reageerimise ega ole aru saanud, miks? Üks võimalik seletus on seotud protsessori ressursikvoodi piirangutega. Sellest me selles artiklis räägime.

TL; DR:
Soovitame tungivalt keelata Kubernetes CPU piirangud (või Kubeletis CFS-kvoodid keelata), kui kasutate CFS-i kvoodiveaga Linuxi tuuma versiooni. Tuumas on saadaval tõsine ja hästi tuntud viga, mis põhjustab liigset pidurdamist ja viivitusi
.

Omios kogu taristut haldab Kubernetes. Kõik meie olekuga ja olekuta töökoormused töötavad ainult Kubernetesis (kasutame Google Kubernetes Engine'i). Viimase kuue kuu jooksul hakkasime jälgima juhuslikke aeglustusi. Rakendused hanguvad või lõpetavad tervisekontrollidele reageerimise, kaotavad võrguühenduse jne. Selline käitumine valmistas meile pikka aega hämmingut ja lõpuks otsustasime probleemi tõsiselt võtta.

Artikli kokkuvõte:

  • Paar sõna konteinerite ja Kubernetese kohta;
  • Kuidas CPU päringuid ja piiranguid rakendatakse;
  • Kuidas CPU limiit töötab mitmetuumalistes keskkondades;
  • Kuidas jälgida protsessori drosselit;
  • Probleemi lahendus ja nüansid.

Paar sõna konteinerite ja Kubernetese kohta

Kubernetes on sisuliselt kaasaegne standard infrastruktuurimaailmas. Selle põhiülesanne on konteinerite orkestreerimine.

Konteinerid

Varem pidime serverites töötamiseks looma artefakte, nagu Java JAR-id/WAR-id, Python Eggs või käivitatavad failid. Nende funktsioneerimiseks tuli aga teha lisatööd: installeerida käituskeskkond (Java/Python), paigutada vajalikud failid õigetesse kohtadesse, tagada ühilduvus operatsioonisüsteemi konkreetse versiooniga jne. Teisisõnu, konfiguratsioonihaldusele (mis tekitas sageli arendajate ja süsteemiadministraatorite vahel vaidlusi) tuli pöörata suurt tähelepanu.

Konteinerid muutsid kõike. Nüüd on artefakt konteineri kujutis. Seda saab kujutada teatud tüüpi laiendatud täitmisfailina, mis sisaldab lisaks programmile ka täisväärtuslikku täitmiskeskkonda (Java/Python/...), samuti vajalikke faile/pakette, mis on eelinstallitud ja kasutamiseks valmis. jooksma. Konteinereid saab juurutada ja kasutada erinevates serverites ilma täiendavate sammudeta.

Lisaks tegutsevad konteinerid oma liivakastikeskkonnas. Neil on oma virtuaalne võrguadapter, oma piiratud juurdepääsuga failisüsteem, oma protsesside hierarhia, oma piirangud protsessorile ja mälule jne. Kõik see on teostatud tänu Linuxi tuuma erilisele alamsüsteemile - nimeruumidele.

Kubernetes

Nagu varem öeldud, on Kubernetes konteinerite orkestreerija. See toimib järgmiselt: annate talle hulga masinaid ja ütlete siis: "Hei, Kubernetes, käivitame kümme minu konteineri eksemplari, millest igaüks on 2 protsessori ja 3 GB mäluga, ja jätkake neid töös!" Ülejäänu eest hoolitseb Kubernetes. See leiab vaba võimsuse, käivitab konteinerid ja vajadusel taaskäivitab, käivitab versiooni vahetamisel värskenduse jne. Põhimõtteliselt võimaldab Kubernetes teil riistvarakomponendist lahti võtta ja teeb laias valikus süsteeme sobivaks rakenduste juurutamiseks ja käitamiseks.

Protsessori piirangud ja agressiivne piiramine Kubernetesis
Kubernetes võhiku vaatevinklist

Mis on Kubernetes taotlused ja piirangud

Olgu, me katsime konteinerid ja Kubernetes. Teame ka, et samal masinal võib olla mitu konteinerit.

Analoogia võib tuua kommunaalkorteriga. Võetakse avar pind (masinad/agregaadid) ja antakse üürile mitmele üürnikule (konteinerid). Kubernetes tegutseb kinnisvaramaaklerina. Tekib küsimus, kuidas hoida üürnikke omavaheliste konfliktide eest? Mis saab siis, kui üks neist otsustab näiteks pooleks päevaks vannituppa laenata?

Siin tulevad mängu taotlused ja piirangud. Protsessor Küsi vaja ainult planeerimise eesmärgil. See on midagi konteineri soovinimekirja sarnast ja seda kasutatakse sobivaima sõlme valimiseks. Samal ajal CPU piir võib võrrelda rendilepinguga - niipea, kui valime konteineri jaoks ühiku, on ei saa ületada kehtestatud piire. Ja siit tekibki probleem...

Kuidas taotlusi ja piiranguid Kubernetesis rakendatakse

Kubernetes kasutab protsessori piirangute rakendamiseks kernelisse sisseehitatud drosselmehhanismi (kellatsüklite vahelejätmine). Kui rakendus ületab limiidi, lubatakse drossel (st see võtab vastu vähem CPU tsükleid). Mälu päringud ja piirangud on korraldatud erinevalt, nii et neid on lihtsam tuvastada. Selleks kontrollige lihtsalt podi viimast taaskäivitamise olekut: kas see on "OOMKilled". Protsessori reguleerimine pole nii lihtne, kuna K8s teeb mõõdikud kättesaadavaks ainult kasutuse, mitte c-rühmade järgi.

CPU taotlus

Protsessori piirangud ja agressiivne piiramine Kubernetesis
Kuidas protsessori taotlust rakendatakse

Lihtsuse huvides vaatame protsessi, kasutades näiteks 4-tuumalise CPU-ga masinat.

K8s kasutab ressursside (mälu ja protsessori) jaotamise kontrollimiseks kontrollrühma mehhanismi (cgroups). Selle jaoks on saadaval hierarhiline mudel: laps pärib vanemrühma piirid. Levitamise üksikasjad salvestatakse virtuaalsesse failisüsteemi (/sys/fs/cgroup). Protsessori puhul on see nii /sys/fs/cgroup/cpu,cpuacct/*.

K8s kasutab faili cpu.share protsessori ressursside eraldamiseks. Meie puhul saab juur-cgroup 4096 protsessori ressurssi - 100% saadaolevast protsessori võimsusest (1 tuum = 1024; see on fikseeritud väärtus). Juurerühm jaotab ressursse proportsionaalselt sõltuvalt registreeritud järeltulijate osakaaludest cpu.share, ja nemad omakorda teevad sama oma järglastega jne. Tüüpilises Kubernetese sõlmes on juur-c-rühmal kolm last: system.slice, user.slice и kubepods. Kaht esimest alamrühma kasutatakse ressursside jaotamiseks kriitiliste süsteemikoormuste ja kasutajaprogrammide vahel väljaspool K8-sid. Viimane - kubepods - loodud Kubernetesi poolt ressursside jaotamiseks kaunade vahel.

Ülaltoodud diagramm näitab, et esimene ja teine ​​alarühm said kumbki 1024 aktsiad, eraldades kuberpodi alamrühma 4096 aktsiad Kuidas see võimalik on: juurrühmal on ju juurdepääs ainult 4096 aktsiad ja tema järglaste aktsiate summa ületab oluliselt seda arvu (6144)? Asi on selles, et väärtus on loogiline, nii et Linuxi planeerija (CFS) kasutab seda protsessori ressursside proportsionaalseks eraldamiseks. Meie puhul saavad kaks esimest rühma 680 reaalaktsiaid (16,6% 4096-st) ja kubepod saab ülejäänud osa 2736 aktsiad Seisaku korral ei kasuta kaks esimest rühma eraldatud ressursse.

Õnneks on planeerijal olemas mehhanism, mis väldib kasutamata protsessoriressursside raiskamist. See edastab "tühioleku" võimsuse globaalsesse kogumisse, kust see jaotatakse rühmadele, kes vajavad täiendavat protsessori võimsust (ülekanne toimub partiidena, et vältida ümardamiskadu). Sarnast meetodit rakendatakse kõigi järglaste järeltulijate puhul.

See mehhanism tagab protsessori võimsuse õiglase jaotuse ja selle, et ükski protsess ei "varastaks" teistelt ressursse.

CPU limiit

Hoolimata asjaolust, et piirangute ja päringute konfiguratsioonid K8-des näevad välja sarnased, on nende rakendamine radikaalselt erinev: see kõige eksitavam ja kõige vähem dokumenteeritud osa.

K8s osaleb CFS-kvoodi mehhanism piiranguid rakendada. Nende seaded on määratud failides cfs_period_us и cfs_quota_us kataloogis cgroup (seal asub ka fail cpu.share).

Erinevalt cpu.share, põhineb kvoot ajavahemik, mitte saadaoleval protsessori võimsusel. cfs_period_us määrab perioodi (epohhi) kestuse - see on alati 100000 μs (100 ms). K8s on seda väärtust võimalik muuta, kuid see on praegu saadaval ainult alfaversioonis. Planeerija kasutab epohhi kasutatud kvootide taaskäivitamiseks. Teine fail cfs_quota_us, määrab igal ajajärgul saadaoleva aja (kvoodi). Pange tähele, et see on määratud ka mikrosekundites. Kvoot võib ületada ajastu pikkust; teisisõnu, see võib olla pikem kui 100 ms.

Vaatame kahte stsenaariumi 16-tuumaliste masinate puhul (kõige levinum arvutitüüp, mis meil Omios on):

Protsessori piirangud ja agressiivne piiramine Kubernetesis
1. stsenaarium: 2 lõime ja 200 ms piirang. Ei mingit drosselit

Protsessori piirangud ja agressiivne piiramine Kubernetesis
2. stsenaarium: 10 lõime ja 200 ms piirang. Piiramine algab 20 ms pärast, juurdepääs protsessori ressurssidele jätkub veel 80 ms pärast

Oletame, et määrate CPU piiranguks 2 tuumad; Kubernetes tõlgib selle väärtuse 200 ms-ks. See tähendab, et konteiner saab kasutada maksimaalselt 200 ms CPU aega ilma piiranguta.

Ja siit algab lõbu. Nagu eespool mainitud, on saadaolev kvoot 200 ms. Kui töötate paralleelselt kümme niidid 12-tuumalises masinas (vt 2. stsenaariumi illustratsiooni), kui kõik teised podid on jõude, ammendub kvoot vaid 20 ms pärast (kuna 10 * 20 ms = 200 ms) ja kõik selle podi lõimed jäävad rippuma » (gaas) järgmise 80 ms jooksul. Juba mainitud planeerija viga, mille tõttu tekib liigne drossel ja konteiner ei suuda isegi olemasolevat kvooti täita.

Kuidas hinnata drosselit kaunades?

Lihtsalt logige podisse sisse ja käivitage cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods — ajakava perioodide koguarv;
  • nr_throttled — pidurdatud perioodide arv kompositsioonis nr_periods;
  • throttled_time — kumulatiivne drosselaeg nanosekundites.

Protsessori piirangud ja agressiivne piiramine Kubernetesis

Mis tegelikult toimub?

Selle tulemusel saavutame kõigis rakendustes kõrge drosseli. Mõnikord on ta sees poolteist korda tugevam kui arvutatud!

See toob kaasa erinevaid tõrkeid – valmisoleku kontrollimise tõrked, konteineri külmumised, võrguühenduse katkestused, teeninduskõnede ajalõpud. Selle tulemuseks on lõpuks suurenenud latentsusaeg ja suurem veamäär.

Otsus ja tagajärjed

Siin on kõik lihtne. Loobusime protsessori piirangutest ja alustasime klastrite kaupa OS-i tuuma värskendamist uusimale versioonile, milles viga parandati. Vigade arv (HTTP 5xx) meie teenustes langes kohe oluliselt:

HTTP 5xx vead

Protsessori piirangud ja agressiivne piiramine Kubernetesis
HTTP 5xx vead ühe kriitilise teenuse jaoks

Reageerimisaeg lk 95

Protsessori piirangud ja agressiivne piiramine Kubernetesis
Kriitilise teenusepäringu latentsus, 95. protsentiil

Tegevuskulud

Protsessori piirangud ja agressiivne piiramine Kubernetesis
Näidiste kulutatud tundide arv

Mis on saak?

Nagu artikli alguses öeldud:

Analoogia võib tuua kommunaalkorteriga... Kubernetes tegutseb maaklerina. Kuidas aga hoida üürnikke omavaheliste konfliktide eest? Mis saab siis, kui üks neist otsustab näiteks pooleks päevaks vannituppa laenata?

Siin on saak. Üks hooletu konteiner võib ära süüa kõik masinas olevad CPU ressursid. Kui teil on nutikas rakenduste pinu (näiteks JVM, Go, Node VM on õigesti konfigureeritud), pole see probleem: sellistes tingimustes saate töötada pikka aega. Aga kui rakendused on halvasti optimeeritud või pole üldse optimeeritud (FROM java:latest), võib olukord kontrolli alt väljuda. Meil on Omios automatiseeritud põhilised Docker-failid, millel on suuremate keelevirna jaoks piisavad vaikeseaded, nii et seda probleemi ei olnud.

Soovitame mõõdikuid jälgida KASUTADA (kasutus, küllastus ja vead), API viivitused ja veamäärad. Veenduge, et tulemused vastavad ootustele.

Viited

See on meie lugu. Järgmised materjalid aitasid toimuvat mõista:

Kubernetese veaaruanded:

Kas olete oma praktikas sarnaste probleemidega kokku puutunud või teil on kogemusi konteinerites tootmiskeskkondade drosseliga seotud? Jaga oma lugu kommentaarides!

PS tõlkijalt

Loe ka meie blogist:

Allikas: www.habr.com

Lisa kommentaar