Limiti di CPU è throttling aggressivu in Kubernetes

Nota. transl.: Questa storia d'ochju di Omio-un aggregatore di viaghju europeu-porta i lettori da a teoria basica à l'affascinanti intricacies pratiche di a cunfigurazione di Kubernetes. A familiarità cù tali casi aiuta micca solu à allargà i vostri orizonti, ma ancu impediscenu prublemi micca triviali.

Limiti di CPU è throttling aggressivu in Kubernetes

Avete mai avutu una applicazione bloccata in u locu, smette di risponde à i cuntrolli di salute, è ùn pò micca capisce perchè? Una spiegazione pussibule hè ligata à i limiti di quota di risorse CPU. Questu hè ciò chì avemu da parlà in questu articulu.

TL; DR:
Hè ricumandemu fermamente di disattivà i limiti di CPU in Kubernetes (o disattivà e quote CFS in Kubelet) se utilizate una versione di u kernel Linux cun un bug di quota CFS. In u core ci hè seriu è ben cunnisciutu un bug chì porta à throttling eccessivu è ritardi
.

In Omio tutta l'infrastruttura hè gestita da Kubernetes. Tutti i nostri carichi di travagliu stateless è senza stati funzionanu esclusivamente in Kubernetes (utilicemu Google Kubernetes Engine). In l'ultimi sei mesi, avemu cuminciatu à osservà rallentamenti casuali. L'applicazioni si congelanu o cessanu di risponde à i cuntrolli di salute, perde a cunnessione à a reta, etc. Stu cumpurtamentu ci hà perplessu per un bellu pezzu, è infine avemu decisu di piglià u prublema in seriu.

Sommariu di l'articulu:

  • Uni pochi parolle nantu à i cuntenituri è Kubernetes;
  • Cumu e dumande è i limiti di CPU sò implementati;
  • Cumu u limitu di CPU funziona in ambienti multi-core;
  • Cumu seguità u throttling CPU;
  • Soluzione di prublema è sfumature.

Uni pochi parolle nantu à i cuntenituri è Kubernetes

Kubernetes hè essenzialmente u standard mudernu in u mondu di l'infrastruttura. U so compitu principale hè l'orchestrazione di u containeru.

Contenidors

In u passatu, avemu avutu à creà artefatti cum'è Java JAR / WARs, Python Eggs, o eseguibili per eseguisce nantu à i servitori. In ogni casu, per fà funziunà, un travagliu supplementu deve esse fattu: installà l'ambiente di runtime (Java / Python), mette i schedarii necessarii in i posti ghjusti, assicurendu a cumpatibilità cù una versione specifica di u sistema operatore, etc. In altri palori, l'attenzione attenta deve esse pagata à a gestione di cunfigurazione (chì era spessu una fonte di cuntinzione trà sviluppatori è amministratori di sistema).

I cuntenituri anu cambiatu tuttu. Avà l'artefattu hè una maghjina di cuntainer. Pò esse rapprisintatu cum'è una spezia di file eseguibile estensatu chì cuntene micca solu u prugramma, ma ancu un ambiente di esecutivu cumpletu (Java/Python/...), è ancu i schedarii / pacchetti necessarii, preinstallati è pronti à esse. corre. I cuntenituri ponu esse implementati è eseguiti in diversi servitori senza alcunu passu supplementu.

Inoltre, i cuntenituri operanu in u so propiu ambiente sandbox. Hanu u so propiu adattatore di rete virtuale, u so propiu sistema di schedariu cù accessu limitatu, a so ghjerarchia di prucessi, e so limitazioni in CPU è memoria, etc. Tuttu questu hè implementatu grazia à un subsistema speciale di u kernel Linux - namespaces.

Kubernetes

Cum'è dichjaratu prima, Kubernetes hè un orchestratore di container. Funziona cusì: dà un pool di macchine, è poi dite: "Ehi, Kubernetes, lanciamu dece istanze di u mo containeru cù 2 processori è 3 GB di memoria ognunu, è mantenemu in esecuzione!" Kubernetes hà da piglià a cura di u restu. Truvarà a capacità libera, lanciarà cuntenituri è riavvia se ne necessariu, stende l'aghjurnamenti quandu cambia versione, etc. Essenzialmente, Kubernetes permette di astrazione di u cumpunente hardware è rende una larga varietà di sistemi adattati per implementà è eseguisce applicazioni.

Limiti di CPU è throttling aggressivu in Kubernetes
Kubernetes da u puntu di vista di u laicu

Chì sò e dumande è i limiti in Kubernetes

Va bè, avemu cupertu cuntenituri è Kubernetes. Sapemu ancu chì parechji cuntenituri ponu reside nantu à a stessa macchina.

Una analogia pò esse tracciata cù un appartamentu cumunale. Un locu spaziosu (macchine / unità) hè pigliatu è affittatu à parechji inquilini (contenitori). Kubernetes agisce cum'è un agente immubiliare. A quistione sorge, cumu mantene l'inquilini da cunflitti cù l'altri? E se unu di elli, dì, decide di piglià in prestu u bagnu per a mità di u ghjornu?

Hè quì chì e dumande è i limiti entranu in ghjocu. CPU Demande necessariu solu per scopi di pianificazione. Questu hè qualcosa cum'è una "lista di desideri" di u cuntinuu, è hè utilizatu per selezziunà u node più adattatu. À u listessu tempu u CPU limitazione pò esse paragunatu à un accordu di affittu - appena avemu sceltu una unità per u cuntinuu, u ùn pò micca va oltre i limiti stabiliti. È hè quì chì u prublema nasce ...

Cumu e dumande è i limiti sò implementati in Kubernetes

Kubernetes usa un mecanismu di throttling (saltà i cicli di clock) integratu in u kernel per implementà i limiti di CPU. Se una applicazione supera u limitu, u throttling hè attivatu (vale à dì riceve menu cicli di CPU). E dumande è i limiti per a memoria sò organizati in modu diversu, cusì sò più faciuli di detectà. Per fà questu, basta à verificà l'ultimu status di riavvia di u pod: s'ellu hè "OOMKilled". U throttling di CPU ùn hè micca cusì simplice, postu chì K8s rende solu metriche dispunibuli per usu, micca per cgroups.

Richiesta CPU

Limiti di CPU è throttling aggressivu in Kubernetes
Cumu a dumanda di CPU hè implementata

Per simplicità, fighjemu u prucessu cù una macchina cù un CPU 4-core cum'è un esempiu.

K8s usa un mecanismu di gruppu di cuntrollu (cgroups) per cuntrullà l'assignazione di risorse (memoria è processore). Un mudellu gerarchicu hè dispunibule per questu: u zitellu eredita i limiti di u gruppu parenti. I dettagli di distribuzione sò guardati in un sistema di file virtuale (/sys/fs/cgroup). In u casu di un processatore questu hè /sys/fs/cgroup/cpu,cpuacct/*.

K8s usa u schedariu cpu.share per assignà e risorse di u processatore. In u nostru casu, a radicali cgroup riceve 4096 parte di risorse di CPU - 100% di a putenza di processore dispunibule (1 core = 1024; questu hè un valore fissu). U gruppu radicali distribuisce risorse proporzionalmente secondu e parte di i discendenti registrati in cpu.share, è elli, à u turnu, facenu u listessu cù i so discendenti, etc. In un node Kubernetes tipicu, u cgroup root hà trè figlioli: system.slice, user.slice и kubepods. I primi dui sottogruppi sò usati per distribuisce risorse trà i carichi critichi di u sistema è i prugrammi d'utilizatori fora di K8s. L'ultimu - kubepods - creatu da Kubernetes per distribuisce risorse trà pods.

U diagramma sopra mostra chì u primu è u sicondu sottugruppu anu ricevutu ognunu 1024 azzioni, cù u subgruppu kuberpod attribuitu 4096 azzioni Cumu hè pussibule: dopu à tuttu, u gruppu radicali hà accessu solu 4096 azzioni, è a summa di l'azzioni di i so discendenti supera significativamente stu numeru (6144)? U puntu hè chì u valore hè sensu logicu, cusì u pianificatore Linux (CFS) l'utiliza per assignà proporzionalmente risorse CPU. In u nostru casu, i primi dui gruppi ricevenu 680 azioni reali (16,6% di 4096), è kubepod riceve u restu 2736 azzioni In casu di downtime, i primi dui gruppi ùn anu micca aduprà e risorse attribuite.

Fortunatamente, u pianificatore hà un mecanismu per evità di perdite risorse CPU inutilizate. Trasferisce a capacità "idle" à una piscina glubale, da quale hè distribuitu à i gruppi chì anu bisognu di putenza di processore supplementu (u trasferimentu si faci in batch per evità perditi arrotondamenti). Un metudu simili hè applicatu à tutti i discendenti di i discendenti.

Stu mekanismu assicura una distribuzione ghjusta di u putere di u processatore è assicura chì nimu prucessa "robba" risorse da l'altri.

Limitu CPU

Malgradu u fattu chì e cunfigurazioni di i limiti è e dumande in K8 parenu simili, a so implementazione hè radicalmente diversa: questu più ingannevoli è a parte menu documentata.

K8s s'impegna Mécanisme des quotas du CFS per implementà i limiti. I so paràmetri sò specificati in i schedari cfs_period_us и cfs_quota_us in u cartulare cgroup (u schedariu hè ancu situatu quì cpu.share).

Ô cuntrariu cpu.share, a quota hè basatu nantu periodu di tempu, è micca nantu à a putenza di processore dispunibule. cfs_period_us specifica a durata di u periodu (epica) - hè sempre 100000 μs (100 ms). Ci hè una opzione per cambià stu valore in K8s, ma hè solu dispunibule in alfa per avà. U pianificatore usa l'epica per riavviare e quote usate. Second file cfs_quota_us, specifica u tempu dispunibule (quota) in ogni epoca. Nota chì hè ancu specificatu in microsecondi. A quota pò esse più di a durata di l'epica; in altri palori, pò esse più grande di 100 ms.

Fighjemu dui scenarii nantu à e macchine 16 core (u tipu di computer più cumuni chì avemu in Omio):

Limiti di CPU è throttling aggressivu in Kubernetes
Scenariu 1: 2 fili è un limitu di 200 ms. Nisun throttling

Limiti di CPU è throttling aggressivu in Kubernetes
Scenariu 2: 10 fili è limitu di 200 ms. U throttling principia dopu à 20 ms, l'accessu à e risorse di u processatore hè ripresu dopu à un altru 80 ms

Diciamu chì avete stabilitu u limitu di CPU 2 kernels; Kubernetes traduce stu valore in 200 ms. Questu significa chì u cuntinuu pò utilizà un massimu di 200 ms di tempu CPU senza throttling.

È questu hè induve u divertimentu principia. Cumu l'hà dettu sopra, a quota dispunibule hè 200 ms. Sè vo avete travagliatu in parallelu dieci i fili in una macchina di 12 core (vede l'illustrazione per u scenariu 2), mentre chì tutti l'altri pods sò inattivi, a quota serà esaurita in solu 20 ms (dapoi 10 * 20 ms = 200 ms), è tutti i fili di stu pod si penderanu. » (acceleratore) per i prossimi 80 ms. U digià citatu bug di pianificazione, per via di quale si trova un throttling eccessivu è u cuntinuu ùn pò ancu cumpiendu a quota esistente.

Cumu valutà u throttling in pods?

Basta à accede à u pod è eseguite cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods - u numeru tutale di periodi di pianificazione;
  • nr_throttled - numeru di periodi throttled in a cumpusizioni nr_periods;
  • throttled_time - tempu throttled cumulativu in nanosecondi.

Limiti di CPU è throttling aggressivu in Kubernetes

Chì succede veramente ?

In u risultatu, avemu un altu throttling in tutte l'applicazioni. Calchì volta hè in una volta è mezu più forte chè calculatu !

Questu porta à diversi errori - fallimenti di verificazione di prontezza, congelazione di container, rotture di cunnessione di rete, timeout in e chjama di serviziu. Questu ultimamente si traduce in una latenza aumentata è tassi d'errore più alti.

Decisione è cunsequenze

Tuttu hè simplice quì. Abandunamu i limiti di CPU è cuminciamu à aghjurnà u kernel OS in clusters à l'ultima versione, in quale u bug hè stata corretta. U numaru d'errori (HTTP 5xx) in i nostri servizii hà subitu diminuitu significativamente:

Errori HTTP 5xx

Limiti di CPU è throttling aggressivu in Kubernetes
Errori HTTP 5xx per un serviziu criticu

Tempu di risposta p95

Limiti di CPU è throttling aggressivu in Kubernetes
Latenza di dumanda di serviziu criticu, 95 percentile

Costi operativi

Limiti di CPU è throttling aggressivu in Kubernetes
Numero di ore di istanza spese

Chì ghjè a pesca?

Cum'è dettu à u principiu di l'articulu:

Una analogia pò esse disegnata cù un appartamentu cumunale ... Kubernetes agisce cum'è un realtor. Ma cumu mantene l'inquilini da cunflitti cù l'altri? E se unu di elli, dì, decide di piglià in prestu u bagnu per a mità di u ghjornu?

Eccu a cattura. Un contenitore trascuratu pò manghjà tutte e risorse di CPU dispunibili nantu à una macchina. Se tenete una pila d'applicazioni intelligenti (per esempiu, JVM, Go, Node VM sò cunfigurati bè), allora questu ùn hè micca un prublema: pudete travaglià in tali cundizioni per un bellu pezzu. Ma s'è l'applicazioni sò pocu ottimizzati o micca ottimisati in tuttu (FROM java:latest), a situazione pò esse fora di cuntrollu. In Omio avemu i Dockerfiles di basa automatizati cù paràmetri predeterminati adatti per a pila di lingua maiò, cusì stu prublema ùn esiste micca.

Avemu cunsigliatu per monitorà e metriche USE (usu, saturazione è errori), ritardi di l'API è tassi d'errore. S'assurer que les résultats répondent aux attentes.

referenze

Questa hè a nostra storia. I materiali seguenti aiutanu assai à capisce ciò chì succede:

Rapporti di bug Kubernetes:

Avete scontru prublemi simili in a vostra pratica o avete una sperienza ligata à u throttling in ambienti di produzzione containerizzati? Condividi a vostra storia in i cumenti!

PS da u traduttore

Leghjite puru nant'à u nostru blog:

Source: www.habr.com

Add a comment