Omejitve procesorja in agresivno dušenje v Kubernetesu

Opomba. prevod: Ta osupljiva zgodovina Omia – evropskega potovalnega agregatorja – bralce popelje od osnovne teorije do fascinantnih praktičnih zapletenosti konfiguracije Kubernetes. Poznavanje takšnih primerov pomaga ne le razširiti vaša obzorja, ampak tudi preprečiti nepomembne težave.

Omejitve procesorja in agresivno dušenje v Kubernetesu

Se vam je že kdaj zgodilo, da se je aplikacija obtičala na mestu, se nehala odzivati ​​na zdravstvene preglede in niste mogli ugotoviti, zakaj? Ena od možnih razlag je povezana z omejitvami kvote virov procesorja. O tem bomo govorili v tem članku.

TL; DR:
Močno priporočamo, da onemogočite omejitve procesorja v Kubernetesu (ali onemogočite kvote CFS v Kubeletu), če uporabljate različico jedra Linuxa z napako kvote CFS. V jedru je na voljo resno in dobro znan hrošč, ki povzroči čezmerno dušenje in zamude
.

V Omiju celotno infrastrukturo upravlja Kubernetes. Vse naše delovne obremenitve s stanjem in brez stanja se izvajajo izključno v Kubernetesu (uporabljamo Google Kubernetes Engine). V zadnjih šestih mesecih smo začeli opazovati naključne upočasnitve. Aplikacije zamrznejo ali se prenehajo odzivati ​​na preglede zdravja, izgubijo povezavo z omrežjem itd. To vedenje nas je dolgo časa begalo in končno smo se odločili, da bomo težavo vzeli resno.

Povzetek članka:

  • Nekaj ​​besed o vsebnikih in Kubernetesu;
  • Kako se izvajajo zahteve in omejitve procesorja;
  • Kako deluje omejitev procesorja v večjedrnih okoljih;
  • Kako slediti dušenju procesorja;
  • Rešitev problema in nianse.

Nekaj ​​besed o vsebnikih in Kubernetesu

Kubernetes je v bistvu sodoben standard v svetu infrastrukture. Njegova glavna naloga je orkestracija kontejnerjev.

Zabojniki

V preteklosti smo morali ustvarjati artefakte, kot so Java JAR/WAR, Python Eggs ali izvršljive datoteke za izvajanje na strežnikih. Vendar pa je bilo za njihovo delovanje potrebno dodatno delo: namestitev izvajalnega okolja (Java/Python), namestitev potrebnih datotek na prava mesta, zagotavljanje združljivosti z določeno različico operacijskega sistema itd. Z drugimi besedami, posebno pozornost je bilo treba nameniti upravljanju konfiguracije (ki je bil pogosto vir sporov med razvijalci in sistemskimi skrbniki).

Kontejnerji so spremenili vse. Zdaj je artefakt slika vsebnika. Predstavimo ga lahko kot nekakšno razširjeno izvedljivo datoteko, ki ne vsebuje samo programa, temveč tudi popolno izvajalno okolje (Java/Python/...), pa tudi potrebne datoteke/pakete, vnaprej nameščene in pripravljene za teči. Vsebnike je mogoče razmestiti in izvajati na različnih strežnikih brez dodatnih korakov.

Poleg tega vsebniki delujejo v lastnem okolju peskovnika. Imajo svoj navidezni omrežni adapter, svoj datotečni sistem z omejenim dostopom, svojo hierarhijo procesov, svoje omejitve CPU in pomnilnika itd. Vse to je implementirano zahvaljujoč posebnemu podsistemu jedra Linuxa - imenskim prostorom.

Kubernetes

Kot smo že omenili, je Kubernetes vsebniški orkestrator. Deluje takole: daš mu nabor strojev in nato rečeš: "Hej, Kubernetes, zaženimo deset primerkov mojega vsebnika z 2 procesorjema in 3 GB pomnilnika vsak, in jih pustimo delovati!" Kubernetes bo poskrbel za ostalo. Poiskal bo proste kapacitete, zagnal vsebnike in jih po potrebi znova zagnal, uvedel posodobitve pri spreminjanju različic itd. V bistvu vam Kubernetes omogoča, da abstrahirate strojno komponento in naredi široko paleto sistemov, primernih za uvajanje in izvajanje aplikacij.

Omejitve procesorja in agresivno dušenje v Kubernetesu
Kubernetes z vidika laika

Kaj so zahteve in omejitve v Kubernetesu

V redu, obravnavali smo kontejnerje in Kubernetes. Vemo tudi, da je lahko na istem stroju več vsebnikov.

Analogijo lahko potegnemo s skupnim stanovanjem. Prostoren prostor (stroji/agregati) se vzame in odda več najemnikom (kontejnerji). Kubernetes deluje kot nepremičninski posrednik. Postavlja se vprašanje, kako najemnike obvarovati pred medsebojnimi konflikti? Kaj pa, če se eden od njih, recimo, odloči, da si bo za polovico dneva izposodil kopalnico?

Tu pridejo v poštev zahteve in omejitve. procesor Zahteva potreben izključno za namene načrtovanja. To je nekaj podobnega "seznamu želja" vsebnika in se uporablja za izbiro najprimernejšega vozlišča. Hkrati CPU Meja lahko primerjamo z najemno pogodbo - takoj ko izberemo enoto za kontejner, se ne more preseči postavljene meje. In tu nastane problem...

Kako so zahteve in omejitve implementirane v Kubernetes

Kubernetes uporablja mehanizem za dušenje (preskakovanje taktnih ciklov), ki je vgrajen v jedro za izvajanje omejitev procesorja. Če aplikacija preseže omejitev, je omogočeno dušenje (tj. prejme manj ciklov procesorja). Zahteve in omejitve za pomnilnik so organizirane drugače, zato jih je lažje zaznati. Če želite to narediti, samo preverite stanje zadnjega ponovnega zagona sklopa: ali je »OOMkilled«. Dušenje procesorja ni tako preprosto, saj K8s omogoča meritve samo glede na uporabo, ne pa glede na skupine c.

Zahteva CPU

Omejitve procesorja in agresivno dušenje v Kubernetesu
Kako se izvaja zahteva CPE

Za poenostavitev si oglejmo postopek na primeru stroja s 4-jedrnim procesorjem.

K8s uporablja mehanizem nadzorne skupine (cgroups) za nadzor dodeljevanja virov (pomnilnik in procesor). Zanj je na voljo hierarhični model: otrok podeduje omejitve nadrejene skupine. Podrobnosti o distribuciji so shranjene v virtualnem datotečnem sistemu (/sys/fs/cgroup). V primeru procesorja je to /sys/fs/cgroup/cpu,cpuacct/*.

K8s uporablja datoteko cpu.share za dodelitev virov procesorja. V našem primeru dobi korenska cgroup 4096 deležev virov CPU - 100 % razpoložljive moči procesorja (1 jedro = 1024; to je fiksna vrednost). Korenska skupina sorazmerno porazdeli sredstva glede na deleže potomcev, registriranih v cpu.share, oni pa storijo enako s svojimi potomci itd. Na tipičnem vozlišču Kubernetes ima korenska cgroup tri otroke: system.slice, user.slice и kubepods. Prvi dve podskupini se uporabljata za porazdelitev virov med kritičnimi sistemskimi obremenitvami in uporabniškimi programi zunaj K8s. Zadnji - kubepods — ustvaril Kubernetes za distribucijo virov med pods.

Zgornji diagram kaže, da sta prva in druga podskupina prejeli vsaka 1024 deležev, pri čemer je dodeljena podskupina kuberpod 4096 delnice Kako je to mogoče: navsezadnje ima korenska skupina dostop samo do 4096 deležev, vsota deležev njenih potomcev pa bistveno presega to številko (6144)? Bistvo je, da je vrednost logično smiselna, zato jo razporejevalnik Linuxa (CFS) uporablja za sorazmerno dodeljevanje virov CPU. V našem primeru prejemata prvi dve skupini 680 realnih delnic (16,6 % od 4096), preostanek pa prejme kubepod 2736 delnice V primeru izpadov prvi dve skupini ne bosta porabili dodeljenih sredstev.

Na srečo ima razporejevalnik mehanizem za preprečevanje zapravljanja neuporabljenih virov CPU. Prenese »nedejavno« zmogljivost v globalni bazen, iz katerega se razdeli skupinam, ki potrebujejo dodatno moč procesorja (prenos poteka v serijah, da se izognemo izgubam pri zaokroževanju). Podobna metoda se uporablja za vse potomce potomcev.

Ta mehanizem zagotavlja pravično porazdelitev moči procesorja in zagotavlja, da noben proces ne »ukrade« virov drugim.

Omejitev procesorja

Kljub dejstvu, da so konfiguracije omejitev in zahtev v K8 videti podobne, je njihova izvedba radikalno drugačna: to najbolj zavajajoče in najmanj dokumentiran del.

K8s se vključi mehanizem kvot CFS za izvajanje omejitev. Njihove nastavitve so določene v datotekah cfs_period_us и cfs_quota_us v imeniku cgroup (tam se nahaja tudi datoteka cpu.share).

Za razliko od cpu.share, kvota temelji na časovno obdobje, in ne na razpoložljivo moč procesorja. cfs_period_us določa trajanje obdobja (epohe) - vedno je 100000 μs (100 ms). Obstaja možnost, da to vrednost spremenite v K8s, vendar je za zdaj na voljo samo v različici alpha. Razporejevalnik uporablja epoho za ponovni zagon uporabljenih kvot. Druga datoteka cfs_quota_us, določa razpoložljivi čas (kvoto) v vsaki epohi. Upoštevajte, da je podana tudi v mikrosekundah. Kvota lahko preseže dolžino epohe; z drugimi besedami, lahko je večji od 100 ms.

Oglejmo si dva scenarija na 16-jedrnih strojih (najpogostejši tip računalnika, ki ga imamo pri Omio):

Omejitve procesorja in agresivno dušenje v Kubernetesu
1. scenarij: 2 niti in omejitev 200 ms. Brez dušenja

Omejitve procesorja in agresivno dušenje v Kubernetesu
2. scenarij: 10 niti in omejitev 200 ms. Dušenje se začne po 20 ms, dostop do virov procesorja se nadaljuje po nadaljnjih 80 ms

Recimo, da omejitev procesorja nastavite na 2 jedrca; Kubernetes bo to vrednost prevedel v 200 ms. To pomeni, da lahko vsebnik uporabi največ 200 ms CPU časa brez dušenja.

In tu se začne zabava. Kot je navedeno zgoraj, je razpoložljiva kvota 200 ms. Če delate vzporedno deset niti na 12-jedrnem računalniku (glejte ilustracijo za scenarij 2), medtem ko so vsi drugi sklopi v mirovanju, bo kvota izčrpana v samo 20 ms (ker je 10 * 20 ms = 200 ms) in vse niti tega sklopa bodo obvisele » (plin) za naslednjih 80 ms. Že omenjeno napaka v razporejevalniku, zaradi česar prihaja do prevelikega dušenja in kontejner ne more izpolniti niti obstoječe kvote.

Kako oceniti dušenje v strokih?

Preprosto se prijavite v pod in izvedite cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods — skupno število obdobij načrtovalca;
  • nr_throttled — število dušenih obdobij v sestavi nr_periods;
  • throttled_time — kumulativni dušilni čas v nanosekundah.

Omejitve procesorja in agresivno dušenje v Kubernetesu

Kaj se pravzaprav dogaja?

Posledično dobimo visoko dušenje v vseh aplikacijah. Včasih je notri enkrat in pol močnejši od izračunanega!

To vodi do različnih napak - napake pri preverjanju pripravljenosti, zamrznitve vsebnika, prekinitve omrežne povezave, časovne omejitve pri servisnih klicih. To na koncu povzroči povečano zakasnitev in višje stopnje napak.

Odločitev in posledice

Tukaj je vse preprosto. Opustili smo omejitve procesorja in začeli posodabljati jedro OS v gručah na najnovejšo različico, v kateri je bila napaka odpravljena. Število napak (HTTP 5xx) v naših storitvah se je takoj močno zmanjšalo:

Napake HTTP 5xx

Omejitve procesorja in agresivno dušenje v Kubernetesu
Napake HTTP 5xx za eno kritično storitev

Odzivni čas p95

Omejitve procesorja in agresivno dušenje v Kubernetesu
Zakasnitev zahteve za kritično storitev, 95. percentil

Stroški operacije

Omejitve procesorja in agresivno dušenje v Kubernetesu
Število porabljenih ur primerov

Kaj je ulov?

Kot je navedeno na začetku članka:

Analogijo lahko potegnemo s skupnim stanovanjem ... Kubernetes deluje kot nepremičninar. Toda kako najemnike obvarovati pred medsebojnimi konflikti? Kaj pa, če se eden od njih, recimo, odloči, da si bo za polovico dneva izposodil kopalnico?

Tukaj je ulov. En nepreviden vsebnik lahko požre vse razpoložljive vire procesorja na stroju. Če imate sklad pametnih aplikacij (na primer JVM, Go, Node VM so pravilno konfigurirani), potem to ni problem: v takšnih pogojih lahko delate dolgo časa. Če pa so aplikacije slabo optimizirane ali sploh niso optimizirane (FROM java:latest), lahko situacija uide izpod nadzora. Pri Omio imamo avtomatizirane osnovne datoteke Dockerfiles z ustreznimi privzetimi nastavitvami za glavni jezikovni sklad, tako da te težave ni bilo.

Priporočamo spremljanje metrik UPORABA (uporaba, nasičenost in napake), zamude API-ja in stopnje napak. Poskrbite, da bodo rezultati izpolnili pričakovanja.

reference

To je naša zgodba. Naslednji materiali so zelo pomagali razumeti, kaj se dogaja:

Poročila o napakah Kubernetes:

Ali ste v svoji praksi naleteli na podobne težave ali imate izkušnje v zvezi z dušenjem v kontejnerskih proizvodnih okoljih? Delite svojo zgodbo v komentarjih!

PS od prevajalca

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar