CPU-limoj kaj agresema estrangilo en Kubernetes

Notu. transl.: Ĉi tiu okulfrapa historio de Omio—eŭropa vojaĝagregator—prenas legantojn de baza teorio ĝis la fascinaj praktikaj komplikaĵoj de Kubernetes-agordo. Konatiĝo kun tiaj kazoj helpas ne nur plilarĝigi viajn horizontojn, sed ankaŭ malhelpi ne-trivialajn problemojn.

CPU-limoj kaj agresema estrangilo en Kubernetes

Ĉu vi iam havis aplikaĵon blokita en loko, ĉesas respondi al sankontroloj, kaj ne povis eltrovi kial? Unu ebla klarigo rilatas al CPU-rimeda kvotlimoj. Jen pri kio ni parolos en ĉi tiu artikolo.

TL; DR:
Ni forte rekomendas malŝalti CPU-limojn en Kubernetes (aŭ malŝalti CFS-kvotojn en Kubelet) se vi uzas version de la Linukso-kerno kun CFS-kvocimo. En la kerno disponeblas seriozaj kaj bone konata cimo, kiu kondukas al troa strolling kaj prokrastoj
.

En Omio la tuta infrastrukturo estas administrita de Kubernetes. Ĉiuj niaj ŝtataj kaj sennaciaj laborŝarĝoj funkcias ekskluzive sur Kubernetes (ni uzas Google Kubernetes Engine). En la lastaj ses monatoj, ni komencis observi hazardajn malrapidiĝojn. Aplikoj frostiĝas aŭ ĉesas respondi al sankontroloj, perdas konekton al la reto, ktp. Ĉi tiu konduto konfuzigis nin dum longa tempo, kaj finfine ni decidis preni la problemon serioze.

Resumo de la artikolo:

  • Kelkaj vortoj pri ujoj kaj Kubernetes;
  • Kiel CPU-petoj kaj limoj estas efektivigitaj;
  • Kiel CPU-limo funkcias en plurkernaj medioj;
  • Kiel spuri CPU-strango;
  • Problemsolvo kaj nuancoj.

Kelkajn vortojn pri ujoj kaj Kubernetes

Kubernetes estas esence la moderna normo en la infrastruktura mondo. Ĝia ĉefa tasko estas kontenera orkestrado.

Ujoj

En la pasinteco, ni devis krei artefaktojn kiel Java JARs/WARs, Python Eggs, aŭ ekzekuteblaj por funkcii en serviloj. Tamen, por ke ili funkciu, aldona laboro devis esti farita: instali la rultempan medion (Java/Python), meti la necesajn dosierojn en la ĝustaj lokoj, certigi kongruecon kun specifa versio de la operaciumo, ktp. Alivorte, zorgema atento devis esti pagita al agorda administrado (kiu ofte estis fonto de disputo inter programistoj kaj sistemadministrantoj).

Ujoj ŝanĝis ĉion. Nun la artefakto estas ujo-bildo. Ĝi povas esti reprezentita kiel speco de plilongigita rulebla dosiero enhavanta ne nur la programon, sed ankaŭ plentaŭgan ekzekutmedion (Java/Python/...), same kiel la necesajn dosierojn/pakaĵojn, antaŭinstalitajn kaj pretajn por kuri. Ujoj povas esti deplojitaj kaj funkciitaj sur malsamaj serviloj sen aldonaj paŝoj.

Krome, ujoj funkcias en sia propra sablokesto-medio. Ili havas sian propran virtualan retan adaptilon, sian propran dosiersistemon kun limigita aliro, sian propran hierarkion de procezoj, siajn proprajn limojn pri CPU kaj memoro, ktp. Ĉio ĉi estas efektivigita danke al speciala subsistemo de la Linukso-kerno - nomspacoj.

Kubernetoj

Kiel dirite antaŭe, Kubernetes estas ujo orkestranto. Ĝi funkcias jene: vi donas al ĝi aron da maŝinoj, kaj poste diras: "He, Kubernetes, ni lanĉu dek ekzemplojn de mia ujo kun 2 procesoroj kaj 3 GB da memoro ĉiu, kaj tenu ilin funkcii!" Kubernetes prizorgos la reston. Ĝi trovos senpagan kapaciton, lanĉos ujojn kaj rekomencos ilin se necese, lanĉos ĝisdatigon kiam ŝanĝas versiojn, ktp. Esence, Kubernetes permesas vin abstrakti la aparataron kaj faras ampleksan varion de sistemoj taŭgaj por disfaldi kaj ruli aplikaĵojn.

CPU-limoj kaj agresema estrangilo en Kubernetes
Kubernetes el la vidpunkto de laiko

Kio estas petoj kaj limoj en Kubernetes

Bone, ni kovris ujojn kaj Kubernetes. Ni ankaŭ scias, ke pluraj ujoj povas loĝi sur la sama maŝino.

Analogio povas esti desegnita kun komunuma apartamento. Ampleksa loko (maŝinoj/unuoj) estas prenita kaj luita al pluraj luantoj (ujoj). Kubernetes agas kiel dom-makleristo. La demando ŝprucas, kiel konservi luantojn de konfliktoj unu kun la alia? Kio se unu el ili, ekzemple, decidas prunti la banĉambron por duono de la tago?

Ĉi tie eniras petoj kaj limoj. CPU peto bezonata nur por planado. Ĉi tio estas io kiel "dezirlisto" de la ujo, kaj ĝi estas uzata por elekti la plej taŭgan nodon. Samtempe la CPU limo povas esti komparita al lukontrakto - tuj kiam ni elektas unuon por la ujo, la ne povas iri preter establitaj limoj. Kaj ĉi tie aperas la problemo...

Kiel petoj kaj limoj estas efektivigitaj en Kubernetes

Kubernetes uzas streĉan mekanismon (saltante horloĝciklojn) konstruitan en la kernon por efektivigi CPU-limojn. Se aplikaĵo superas la limon, strekado estas ebligita (t.e. ĝi ricevas malpli da CPU-cikloj). Petoj kaj limoj por memoro estas organizitaj malsame, do ili estas pli facile detekteblaj. Por fari tion, simple kontrolu la lastan rekomencan staton de la pod: ĉu ĝi estas "OOMKilled". CPU-strango ne estas tiel simpla, ĉar K8s nur disponigas metrikojn per uzado, ne per cgrupoj.

CPU-Peto

CPU-limoj kaj agresema estrangilo en Kubernetes
Kiel CPU-peto estas efektivigita

Por simpleco, ni rigardu la procezon uzante maŝinon kun 4-kerna CPU kiel ekzemplo.

K8s uzas kontrolgrupan mekanismon (cgroups) por kontroli la asignon de resursoj (memoro kaj procesoro). Hierarkia modelo disponeblas por ĝi: la infano heredas la limojn de la gepatra grupo. La distribuaj detaloj estas konservitaj en virtuala dosiersistemo (/sys/fs/cgroup). En la kazo de procesoro ĉi tio estas /sys/fs/cgroup/cpu,cpuacct/*.

K8s uzas dosieron cpu.share por asigni procesorajn rimedojn. En nia kazo, la radiko cgroup ricevas 4096 partojn de CPU-resursoj - 100% de la disponebla procesoro-potenco (1 kerno = 1024; ĉi tio estas fiksa valoro). La radikgrupo distribuas resursojn proporcie depende de la akcioj de posteuloj registritaj en cpu.share, kaj ili, siavice, faras la samon kun siaj posteuloj, ktp. Sur tipa Kubernetes-nodo, la radika cgrupo havas tri infanojn: system.slice, user.slice и kubepods. La unuaj du subgrupoj kutimas distribui resursojn inter kritikaj sistemŝarĝoj kaj uzantprogramoj ekster K8s. La lasta - kubepods — kreita de Kubernetes por distribui rimedojn inter podoj.

La supra diagramo montras, ke la unua kaj dua subgrupoj ricevis ĉiun 1024 akcioj, kun la kuberpod subgrupo asignita 4096 akcioj Kiel tio eblas: post ĉio, la radika grupo havas aliron nur al 4096 akcioj, kaj la sumo de la akcioj de ŝiaj posteuloj signife superas ĉi tiun nombron (6144)? La punkto estas, ke la valoro havas logikan sencon, do la Linukso-planilo (CFS) uzas ĝin por proporcie asigni CPU-resursojn. En nia kazo, la unuaj du grupoj ricevas 680 realaj akcioj (16,6% de 4096), kaj kubepod ricevas la ceterajn 2736 akcioj En kazo de malfunkcio, la unuaj du grupoj ne uzos la asignitajn rimedojn.

Feliĉe, la planilo havas mekanismon por eviti malŝpari neuzatajn CPU-resursojn. Ĝi transdonas "senfunkcian" kapaciton al tutmonda naĝejo, de kiu ĝi estas distribuita al grupoj kiuj bezonas plian procesoran potencon (la translokigo okazas en aroj por eviti rondigajn perdojn). Simila metodo estas aplikata al ĉiuj posteuloj de posteuloj.

Ĉi tiu mekanismo certigas justan distribuadon de procesoro-potenco kaj certigas, ke neniu procezo "ŝtelas" resursojn de aliaj.

CPU-Limo

Malgraŭ la fakto, ke la agordoj de limoj kaj petoj en K8s aspektas similaj, ilia efektivigo estas radikale malsama: ĉi tio plej misgvida kaj la malplej dokumentita parto.

K8s engaĝiĝas CFS-kvota mekanismo efektivigi limojn. Iliaj agordoj estas specifitaj en dosieroj cfs_period_us и cfs_quota_us en la dosierujo cgroup (la dosiero ankaŭ troviĝas tie cpu.share).

Kontraste cpu.share, la kvoto baziĝas sur tempoperiodo, kaj ne sur la disponebla procesoro-potenco. cfs_period_us precizigas la daŭron de la periodo (epoko) - ĝi estas ĉiam 100000 μs (100 ms). Estas eblo ŝanĝi ĉi tiun valoron en K8s, sed ĝi estas nur disponebla en alfa nuntempe. La planisto uzas la epokon por rekomenci uzitajn kvotojn. Dua dosiero cfs_quota_us, precizigas la disponeblan tempon (kvoto) en ĉiu epoko. Notu ke ĝi ankaŭ estas specifita en mikrosekundoj. La kvoto povas superi la epoklongon; alivorte, ĝi povas esti pli granda ol 100 ms.

Ni rigardu du scenarojn sur 16-kernaj maŝinoj (la plej ofta speco de komputilo, kiun ni havas ĉe Omio):

CPU-limoj kaj agresema estrangilo en Kubernetes
Scenaro 1: 2 fadenoj kaj 200 ms limo. Neniu strango

CPU-limoj kaj agresema estrangilo en Kubernetes
Scenaro 2: 10 fadenoj kaj 200 ms limo. Ŝrolado komenciĝas post 20 ms, aliro al procesoraj rimedoj estas rekomencita post pliaj 80 ms

Ni diru, ke vi fiksas la CPU-limon al 2 kernoj; Kubernetes tradukos ĉi tiun valoron al 200 ms. Ĉi tio signifas, ke la ujo povas uzi maksimume 200ms da CPU-tempo sen streĉado.

Kaj ĉi tie komenciĝas la amuzo. Kiel menciite supre, la disponebla kvoto estas 200 ms. Se vi laboras paralele dek fadenoj sur 12-kerna maŝino (vidu ilustraĵon por scenaro 2), dum ĉiuj aliaj podoj estas neaktivaj, la kvoto elĉerpiĝos en nur 20 ms (ekde 10 * 20 ms = 200 ms), kaj ĉiuj fadenoj de ĉi tiu podo pendos » (akcelilo) dum la sekvaj 80 ms. La jam menciita cimo de horaro, pro kio okazas troa strolado kaj la ujo eĉ ne povas plenumi la ekzistantan kvoton.

Kiel taksi strolladon en podoj?

Nur ensalutu al la pod kaj ekzekutu cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods — la totala nombro de horarperiodoj;
  • nr_throttled — nombro da strotitaj periodoj en la komponado nr_periods;
  • throttled_time — akumula strekita tempo en nanosekundoj.

CPU-limoj kaj agresema estrangilo en Kubernetes

Kio vere okazas?

Kiel rezulto, ni ricevas altan estrangiĝon en ĉiuj aplikoj. Foje li estas enen unufoje kaj duono pli forta ol kalkulita!

Ĉi tio kondukas al diversaj eraroj - malsukcesoj pri preteca kontrolo, ujo-frostiĝo, paŭzoj de reto-konekto, tempomalsukcesoj ene de servovokoj. Ĉi tio finfine rezultigas pliigitan latentecon kaj pli altajn erarajn indicojn.

Decido kaj konsekvencoj

Ĉio estas simpla ĉi tie. Ni forlasis CPU-limojn kaj komencis ĝisdatigi la OS-kernon en aretoj al la plej nova versio, en kiu la cimo estis riparita. La nombro da eraroj (HTTP 5xx) en niaj servoj tuj malpliiĝis signife:

HTTP 5xx-eraroj

CPU-limoj kaj agresema estrangilo en Kubernetes
HTTP 5xx-eraroj por unu kritika servo

Respondtempo p95

CPU-limoj kaj agresema estrangilo en Kubernetes
Kritika servo-peto latenteco, 95-a percentilo

Operaciaj kostoj

CPU-limoj kaj agresema estrangilo en Kubernetes
Nombro da ekzemplaj horoj pasigitaj

Kio estas la kapto?

Kiel dirite ĉe la komenco de la artikolo:

Analogio povas esti desegnita kun komunuma apartamento... Kubernetes rolas kiel dom-makleristo. Sed kiel konservi luantojn de konfliktoj unu kun la alia? Kio se unu el ili, ekzemple, decidas prunti la banĉambron por duono de la tago?

Jen la kapto. Unu senzorga ujo povas manĝi ĉiujn disponeblajn CPU-resursojn sur maŝino. Se vi havas inteligentan aplikaĵon (ekzemple, JVM, Go, Node VM estas ĝuste agordita), tiam ĉi tio ne estas problemo: vi povas labori en tiaj kondiĉoj dum longa tempo. Sed se aplikoj estas malbone optimumigitaj aŭ tute ne optimumigitaj (FROM java:latest), la situacio povas foriri de kontrolo. Ĉe Omio ni havas aŭtomatigitajn bazajn Dockerfiles kun taŭgaj defaŭltaj agordoj por la ĉefa lingvostako, do ĉi tiu problemo ne ekzistis.

Ni rekomendas monitori la metrikojn UZO (uzado, saturiĝo kaj eraroj), API-prokrastoj kaj erarprocentoj. Certigu, ke rezultoj renkontas atendojn.

referencoj

Jen nia rakonto. La jenaj materialoj multe helpis kompreni kio okazis:

Kubernetes-eraportoj:

Ĉu vi renkontis similajn problemojn en via praktiko aŭ havas sperton rilate al strekado en konteneritaj produktadmedioj? Kunhavigu vian rakonton en la komentoj!

PS de tradukisto

Legu ankaŭ en nia blogo:

fonto: www.habr.com

Aldoni komenton