ProHoster > Blog > Amministrazione > Autoscaling è gestione di risorse in Kubernetes (revisione è video rapportu)
Autoscaling è gestione di risorse in Kubernetes (revisione è video rapportu)
27 d'aprile à a cunferenza Strike 2019, cum'è parte di a sezione "DevOps", u rapportu "Autoscaling è gestione di risorse in Kubernetes" hè statu datu. Parla di cumu pudete aduprà K8s per assicurà una alta dispunibilità di e vostre applicazioni è assicurà un rendimentu di punta.
Per tradizione, avemu piacè di prisentà video di u rapportu (44 minuti, assai più informativu chè l'articulu) è u riassuntu principale in forma di testu. Vai !
Analizemu u tema di u rapportu parola per parolla è cuminciamu da a fine.
Kubernetes
Diciamu chì avemu cuntenituri Docker nantu à u nostru òspite. Perchè? Per assicurà a ripetibilità è l'isolamentu, chì à u turnu permette una implementazione simplice è bona, CI / CD. Avemu assai tali veiculi cù cuntenituri.
Chì furnisce Kubernetes in questu casu?
Smettimu di pensà à queste macchine è cuminciamu à travaglià cù a "nuvola" cluster di cuntenituri o baccelli (gruppi di cuntenituri).
Inoltre, ùn pensemu mancu à i podi individuali, ma gestisce piùоgruppi più grandi. Tali primitivi di altu livellu permettenu di dì chì ci hè un mudellu per eseguisce una certa carica di travagliu, è quì hè u numeru necessariu di istanze per eseguisce. Se dopu cambiamu u mudellu, tutti i casi cambianu.
Cù l'aiutu di API declarative Invece di eseguisce una sequenza di cumandamenti specifichi, discrimu a "struttura di u mondu" (in YAML), chì hè creatu da Kubernetes. È dinò: quandu a descrizzione cambia, a so visualizazione attuale cambierà ancu.
Gestione di risorse
CPU
Eseguimu nginx, php-fpm è mysql in u servitore. Questi servizii anu daveru ancu più prucessi in esecuzione, ognuna di e quali richiede risorse di calculu:
(i numeri nantu à a diapositiva sò "pappagalli", a necessità astratta di ogni prucessu per u putere di computing)
Per fà più faciule di travaglià cù questu, hè logicu cumminà i prucessi in gruppi (per esempiu, tutti i prucessi nginx in un gruppu "nginx"). Una manera simplice è ovvia di fà questu hè di mette ogni gruppu in un cuntainer:
Per cuntinuà, avete bisognu di ricurdà ciò chì hè un containeru (in Linux). A so apparizione hè stata pussibile grazia à trè funzioni chjave in u kernel, implementate assai tempu fà: capacità, namespaces и cgruppi. È u sviluppu ulteriore hè statu facilitatu da altre tecnulugii (cumprese "conchiglie" convenienti cum'è Docker):
In u cuntestu di u rapportu, ci interessa solu cgruppi, perchè i gruppi di cuntrollu sò a parte di a funziunalità di cuntenituri (Docker, etc.) chì implementa a gestione di risorse. I prucessi cumminati in gruppi, cum'è vulemu, sò gruppi di cuntrollu.
Riturnemu à i requisiti di CPU per questi prucessi, è avà per gruppi di prucessi:
(Ripete chì tutti i numeri sò una espressione astratta di a necessità di risorse)
À u listessu tempu, u CPU stessu hà una certa risorsa finita (in l'esempiu questu hè 1000), chì tutti pò mancanu (a summa di i bisogni di tutti i gruppi hè 150 + 850 + 460 = 1460). Chì succede in stu casu?
U kernel cumencia à distribuisce e risorse è a face "giustamente", dendu a stessa quantità di risorse à ogni gruppu. Ma in u primu casu, ci sò più di quelli necessariu (333>150), cusì l'eccessu (333-150 = 183) ferma in riserva, chì hè ancu ugualmente distribuitu trà dui altri cuntenituri:
In u risultatu: u primu cuntinuu avia abbastanza risorse, u sicondu - ùn hà micca abbastanza risorse, u terzu - ùn hà micca abbastanza risorse. Questu hè u risultatu di l'azzioni pianificatore "onestu" in Linux - CFS. U so funziunamentu pò esse aghjustatu cù l'assignazione pesi ognunu di i cuntenituri. Per esempiu, cusì:
Fighjemu u casu di una mancanza di risorse in u secondu containeru (php-fpm). Tutte e risorse di u containeru sò distribuite ugualmente trà i prucessi. In u risultatu, u prucessu maestru travaglia bè, ma tutti i travagliadori rallentanu, ricevenu menu di a mità di ciò chì anu bisognu:
Questu hè cumu u CFS scheduler funziona. Chjameremu ancu i pesi chì assignemu à i cuntenituri dumande. Perchè questu hè cusì - vede più.
Fighjemu tutta a situazione da l'altra parte. Comu sapete, tutte e strade portanu à Roma, è in u casu di un computer, à u CPU. Un CPU, parechje attività - avete bisognu di un semaforu. A manera più simplice di gestisce e risorse hè "semaforu": anu datu un prucessu un tempu d'accessu fissu à u CPU, dopu u prossimu, etc.
Stu approcciu hè chjamatu quotes dura (limitazione dura). Ricordemu solu cum'è limiti. In ogni casu, si distribuisce i limiti à tutti i cuntenituri, un prublema nasce: mysql guidava longu a strada è à un certu puntu u so bisognu di CPU finisci, ma tutti l'altri prucessi sò furzati à aspittà finu à chì u CPU. inattivu.
Riturnemu à u kernel Linux è a so interazzione cù u CPU - a stampa generale hè a siguenti:
cgroup hà dui paràmetri - essenzialmente questi sò dui "torsioni" simplici chì permettenu di determinà:
u pesu per u containeru (richiesta) hè Ardu;
percentuale di u tempu tutale di CPU per travaglià nantu à i compiti di u containeru (limiti) hè quota.
Cumu misurà CPU?
Ci sò modi diffirenti:
Ce pappagalli, nimu sà - avete bisognu di negozià ogni volta.
Interessu più chjaru, ma relative: 50% di un servitore cù 4 core è cù 20 core sò cose completamente diverse.
Pudete aduprà quelli chì sò digià citati pesi, chì Linux sapi, ma sò ancu relative.
L'opzione più adatta hè di misurà e risorse di l'informatica seconde. Quelli. in seconde di u tempu di processore relative à seconde di tempu reale: 1 secondu di u tempu di processore hè statu datu per 1 veru secondu - questu hè un core tutale di CPU.
Per fà ancu più faciule di parlà, cuminciaru à misurà direttamente kernels, chì significa per elli u stessu tempu CPU relative à u veru. Siccomu Linux capisce i pesi, ma micca tantu tempu CPU / core, un mecanismu era necessariu per traduce da unu à l'altru.
Fighjemu un esempiu simplice cù un servitore cù core 3 CPU, induve trè pods seranu datu pesi (500, 1000 è 1500) chì sò facilmente cunvertiti in e parti currispundenti di i nuclei attribuiti à elli (0,5, 1 è 1,5).
Se pigliate un secunnu servitore, induve ci saranu duie volte di core (6), è mette i stessi poddi, a distribuzione di nuclei pò esse facilmente calculata per simplificà multiplicà per 2 (1, 2 è 3, rispettivamente). Ma un mumentu impurtante si trova quandu un quartu podu si prisenta nantu à stu servitore, chì u pesu, per comodità, serà 3000. Piglia una parte di e risorse di CPU (a mità di i nuclei), è per i podi rimanenti sò ricalculati (a mità):
Kubernetes è risorse CPU
In Kubernetes, i risorse di CPU sò generalmente misurati in milliadrax, i.e. 0,001 core sò pigliati cum'è u pesu di basa. (A listessa cosa in a terminologia Linux / cgroups hè chjamata CPU share, anche se, più precisamente, 1000 millicores = 1024 CPU shares). K8s assicura chì ùn mette micca più pods in u servitore chì ci sò risorse di CPU per a summa di i pesi di tutti i pods.
Cumu succede questu? Quandu aghjunghje un servitore à un cluster Kubernetes, hè infurmatu quanti core CPU hà dispunibule. È quandu crea un novu pod, u pianificatore Kubernetes sà quanti core avarà bisognu di stu pod. Cusì, u pod serà assignatu à un servitore induve ci sò abbastanza core.
Chì succede se ùn a dumanda hè specificata (vale à dì chì u pod ùn hà micca un numeru definitu di core chì hà bisognu)? Scupritemu cumu Kubernetes conta in generale e risorse.
Per un pod pudete specificà e dumande (CFS scheduler) è limiti (ricurdate u semaforu?):
Se sò specificati uguali, allora u pod hè assignatu una classa QoS mantinuti. Stu nùmeru di nuclei sempre dispunibule per ellu hè garantitu.
Se a dumanda hè menu di u limitu - QoS class burstable. Quelli. Aspittemu un pod, per esempiu, per sempre aduprà 1 core, ma questu valore ùn hè micca una limitazione per questu: иногда pod pò aduprà più (quandu u servitore hà risorse gratuiti per questu).
Ci hè ancu una classa QoS u megliu sforzu - include quelli assai pods per i quali a dumanda ùn hè micca specificata. I risorse sò dati à elli l'ultimi.
memoria
Cù a memoria, a situazione hè simile, ma un pocu sfarente - dopu tuttu, a natura di sti risorse hè diversa. In generale, l'analogia hè a siguenti:
Videmu cumu e dumande sò implementate in memoria. Chì i baccelli campanu nantu à u servitore, cambiendu u cunsumu di memoria, finu à chì unu d'elli diventa cusì grande chì esce a memoria. In questu casu, l'assassinu OOM appare è uccide u prucessu più grande:
Questu ùn hè micca sempre cunvene per noi, cusì hè pussibule di regulà quale prucessi sò impurtanti per noi è ùn deve esse uccisu. Per fà questu, utilizate u paràmetru oom_score_adj.
Riturnemu à e classi QoS di u CPU è fate una analogia cù i valori oom_score_adj chì determinanu e priorità di cunsumu di memoria per i pods:
U valore oom_score_adj più bassu per un pod - -998 - significa chì un tali pod deve esse uccisu l'ultimu, questu mantinuti.
U più altu - 1000 - hè u megliu sforzu, tali baccelli sò uccisi prima.
Per calculà i valori rimanenti (burstable) ci hè una formula, l'essenza di quale si riduce à u fattu chì più risorse un podu hà dumandatu, u menu prubabile di esse uccisu.
U sicondu "twist" - limit_in_bytes - per i limiti. Cù questu, tuttu hè più simplice: simpricimenti assignemu a quantità massima di memoria emessa, è quì (a cuntrariu di u CPU) ùn ci hè micca quistione di cumu si misurà (memoria).
Tuttu
Ogni pod in Kubernetes hè datu requests и limits - i dui paràmetri per CPU è memoria:
basatu nantu à e dumande, u pianificatore Kubernetes travaglia, chì distribuisce pods trà i servitori;
basatu annantu à tutti i paràmetri, a classa QoS di u pod hè determinata;
I pesi parenti sò calculati nantu à e richieste di CPU;
u scheduler CFS hè cunfiguratu basatu annantu à e richieste di CPU;
OOM killer hè cunfiguratu basatu annantu à e dumande di memoria;
un "semaforo" hè cunfiguratu basatu annantu à i limiti di CPU;
Basatu nantu à i limiti di memoria, un limitu hè cunfiguratu per u cgroup.
In generale, sta stampa risponde à tutte e dumande nantu à cumu si trova a parte principale di a gestione di risorse in Kubernetes.
Autoscaling
K8s cluster-autoscaler
Imaginemu chì tuttu u cluster hè digià occupatu è un novu pod deve esse creatu. Mentre chì u pod ùn pò micca appare, si ferma in statu In attesa. Per apparisce, pudemu cunnette un novu servitore à u cluster o ... installate cluster-autoscaler, chì u farà per noi: urdinate una macchina virtuale da u fornitore di nuvola (usendu una dumanda API) è cunnette à u cluster. , dopu chì u pod sarà aghjuntu.
Questu hè autoscaling di u cluster Kubernetes, chì travaglia grandi (in a nostra sperienza). Tuttavia, cum'è in altrò, ci sò qualchi sfumature quì ...
Sempre chì avemu aumentatu a dimensione di u cluster, tuttu era bè, ma ciò chì succede quandu u cluster cuminciò à liberà si? U prublema hè chì a migrazione di pods (per liberà l'ospiti) hè assai tecnicamente difficiule è caru in termini di risorse. Kubernetes usa un approcciu completamente diversu.
Cunsiderate un cluster di servitori 3 chì hà Deployment. Hà 6 pods: avà ci sò 2 per ogni servitore. Per qualchì mutivu vulemu disattivà unu di i servitori. Per fà questu avemu aduprà u cumandamentu kubectl drain, chì:
pruibisce di mandà novi pods à stu servitore;
eliminerà i pods esistenti nantu à u servitore.
Siccomu Kubernetes hè rispunsevule per mantene u numeru di pods (6), hè simplicemente ricreà elli nantu à altri nodi, ma micca in quellu chì hè disattivatu, postu chì hè digià marcatu cum'è indisponibile per l'ospitu di novi pods. Questa hè una meccanica fundamentale per Kubernetes.
Tuttavia, ci hè ancu una sfumatura quì. In una situazione simile, per StatefulSet (invece di Deployment), l'azzioni seranu diverse. Avà avemu digià una applicazione stateful - per esempiu, trè baccelli cù MongoDB, unu di quale hà qualchì tipu di prublema (i dati sò diventati currutti o un altru errore chì impedisce à u pod di principià currettamente). È decidemu di novu di disattivà un servitore. Chì succede ?
MongoDB pudia mori perchè hà bisognu di un quorum: per un cluster di trè installazioni, almenu duie deve funziunà. Tuttavia, questu ùn succede micca - grazie à PodDisruptionBudget. Stu paràmetru determina u numeru minimu necessariu di baccelli di travagliu. Sapendu chì unu di i pods MongoDB ùn funziona più, è videndu chì PodDisruptionBudget hè stallatu per MongoDB minAvailable: 2, Kubernetes ùn vi permetterà micca di sguassà un pod.
Bottom line: per u muvimentu (è in fattu, a ricreazione) di pods per travaglià currettamente quandu u cluster hè liberatu, hè necessariu di cunfigurà PodDisruptionBudget.
Scala horizontale
Pensemu à una altra situazione. Ci hè una applicazione chì funziona cum'è Deployment in Kubernetes. U trafficu di l'utilizatori vene à i so podi (per esempiu, ci sò trè), è misurà un certu indicatore in elli (per esempiu, CPU load). Quandu a carica aumenta, l'avemu registratu nantu à un schedariu è cresce u numeru di pods per distribuisce e dumande.
Oghje in Kubernetes ùn hè micca bisognu di fà manualmente: un aumentu / diminuzione automaticu di u numeru di pods hè cunfiguratu secondu i valori di l'indicatori di carica misurati.
E dumande principali quì sò: ciò chì esattamente misurà и quantu à interpretà valori ottenuti (per piglià una decisione nantu à cambià u numeru di baccelli). Pudete misurà assai:
Cumu fà questu tecnicamente - cullà metriche, etc. - Aghju parlatu in dettagliu in u rapportu Monitoraghju è Kubernetes. È u cunsigliu principali per sceglie i paràmetri ottimali hè esperimentu!
Ci sò USE u metudu(Utilizazione Saturazione è Errori), u significatu di quale hè a siguenti. À chì basa hè sensu di scala, per esempiu, php-fpm? Basatu nantu à u fattu chì i travagliadori sò esce, questu hè utilizazione. È se i travagliadori sò finiti è novi cunnessione ùn sò micca accettati, questu hè digià saturazione. Issi dui paràmetri deve esse misurati, è sicondu i valori, scaling deve esse realizatu.
Inveci di 'na cunchiusioni
U rapportu hà una continuazione: nantu à a scala verticale è cumu selezziunà e risorse ghjusti. Parlaraghju di questu in futuri video u nostru YouTube - abbonate per ùn mancate micca!
Videos è slides
Video da a performance (44 minuti):
Presentazione di u rapportu:
PS
Altri rapporti nantu à Kubernetes nantu à u nostru blog: