Azure Kubernetes Services (AKS) este locul perfect unde puteți implementa soluția de microservicii pe care o aveți, peste Kubernetes. AKS ne oferă posibilitatea să ne concentrăm asupra aplicației și asupra modului de rezolvare a problemelor de business, iar Microsoft va gestiona infrastructura de care Kubernetes are nevoie pentru a rula.
Odată ce ajungeți live iar numărul de utilizatori crește, va fi nevoie să scalați aplicația în funcție de diferiți factori, precum numărul utilizator, numărul de vizualizări sau alte metrici specifice businessului vostru. Vă propun să descoperim împreună ceea ce ne oferă Azure din acest punct de vedere și cum ne poate ajuta să scalăm aplicația automat, pe baza unor metrici ale sistemului.
Una din cele mai atractive funcționalități pe care o arhitectură de tip microservicii o oferă este flexibilitatea din perspectiva scalabilității. Avem un control mult mai granular asupra părților din aplicație pe care vrem să scalăm, comparativ cu o soluție clasică, unde suntem limitați din cauza a diferiți factori. Într-o soluție bazată pe microservicii putem să scalăm componentele asupra cărora loadul este peste limită, fără să afectăm și restul sistemului.
În interiorul Kubernetesului, există multiple axe pe care putem să creștem capabilitatea sistemului și implicit a aplicației noastre. Două dintre ele sunt la nivel de aplicație (software) și pot să fie automatizate fără probleme. A treia este legată de configurarea hardware a clusterului și devine o problemă chiar și în cloud (AWS sau Azure), unde chiar dacă avem această capabilitate, timpul necesar ca să scalăm este de ordinul minutelor.
Prima dimensiune este numărul de replici (instanțe) al fiecărui serviciu sau pod. Un pod reprezintă o colecție de servicii grupate împreună și care rulează pe același nod. În momentul când loadul pe un pod este mare, este necesar să creștem numărul de replici al acelui pod. În contextul în care un cluster de Kubernetes are mai multe noduri reprezentate de mașini fizice sau virtuale, avem posibilitatea să creștem numărul de replici al unui pod pe mai multe noduri, fără să fie necesar să adăugăm noi noduri. Această activitate se realizează automat și durează câteva secunde.
A doua dimensiune este reprezentată de numărul de noduri pe care clusterul îl are. Fiecare cluster are trei sau mai multe noduri. În momentul în care încărcarea pe un anumit nod crește, avem posibilitatea să creștem și dimensiunea clusterului, adăugând noduri noi. Problema apare din punct de vedere al disponibilității resurselor fizice, deoarece este necesar să ai computation power. În interiorul AKS, acest lucru se poate face automat, numărul de noduri putând să fie crescut în funcție de load. Odată ce noi noduri sunt adăugate în cluster, Kubernetes va redirecționa o parte din poduri pe aceste noduri.
În comparație cu prima dimensiune, acțiunea de creștere a numărului de noduri poate să dureze câteva minute bune, în funcție de disponibilitatea resurselor pentru crearea mașinii respective și configurarea acesteia. Pentru a optimiza timpul de așteptare, Azure are un pool de mașini ținute la cald, cu configurări de OS deja făcute. În acest mod, timpul de așteptare scade de la câteva zeci de minute la doar 2-3 minute.
A treia dimensiune pe care o avem disponibilă este configurarea pe care fiecare nod îl are. În funcție de nevoie, putem să ne decidem să adăugăm noduri mai puternice în cluster sau cu configurație specific nevoilor pe care noi le avem. De exemplu, putem să ne decidem că vrem noduri care să aibă o capacitate a memoriei mult mai mare față de restul nodurilor, pentru a răspunde la anumite nevoi într-o manieră specifică.
Când scalăm în acest fel este nevoie să adăugăm noile noduri în cluster, să migrăm podurile pe aceste noduri, iar apoi să facem retire la nodurile existente.
Până în acest moment am văzut diferite moduri prin care putem să ne scalăm clusterul de Kubernetes din Azure. În următoarea parte a articolului, vom analiza diferite moduri prin care putem să scalăm instanța noastră de AKS.
Mai mult ca sigur că știți deja despre scalarea manuală și nu vom insista foarte multe asupra ei. Trebuie să știm că putem scala manual numărul de replici ale unui pod. În exemplul de mai jos scalăm numărul de replici a podului numit Cards de la 5 la 9.
kubectl scale --replicas=9 deployment/rv_epi_card
Folosind comanda get pods putem să vedem lista cu toate podurile care există în cluster, inclusiv replicile pentru fiecare tip de pod.
$ kubectl get pods
READY STATUS RESTARTS AGE
rv-epi-card-3545353453-2hfh0 1/1 Running 0 3m
rv-epi-card-3545353453-bzt05 1/1 Running 0 3m
rv-epi-card-3545353453-fvcvm 1/1 Running 0 3m
rv-epi-card-3545353453-hrbf2 1/1 Running 0 15m
rv-epi-card-3545353453-qphz8 1/1 Running 0 3m
rv-epi-card-3545353453-th3h1 1/1 Running 0 3m
rv-epi-card-3545353453-5z504 1/1 Running 0 20m
rv-epi-card-3545353453-rvfvm 1/1 Running 0 3m
rv-epi-card-3545353453-1rbgf 1/1 Running 0 15m
Într-un mod asemănător putem să scalăm dimensiunea clusterului adăugând noduri adiționale. Această acțiune poate să fie făcută direct din portalul de Azure.
Când discutăm despre scalarea automată în interiorul AKS, trebuie să ținem cont că în interiorul AKS avem posibilitatea să scalăm în mod automat în două direcții. Una din ele este controlată de către Kubernetes și se referă la numărul de replici pentru fiecare pod sau serviciu. A doua dimensiune este legată de dimensiunea clusterului, unde AKS ne oferă posibilitatea să creștem sau să scadem dinamic numărului de noduri în funcție de diferiți parametri.
Horizontal Pod Autoscaler (HPA) este capabil să monitorizeze loadul consumat de fiecare pod în parte și să decidă dacă este nevoie să crească numărul de replici. În interiorul AKS, HPA este unul și același pe care îl avem într-un cluster de Kubernetes (cu versiunea 1.8 sau mai sus).
Configurația default este ca o dată la 30 de secunde să se verifice numărul de resurse pe care fiecare replică o consumă, iar în funcție de încărcare, HPA decide dacă noi replici trebuie să fie create sau nu. Informațiile legate de încărcare sunt colectate de către Metric Server și consumate de HPA.
Sunt cazuri în care metricele colectate default de către Metric Server nu sunt suficiente și avem nevoie de metrici custom. În aceste cazuri, putem să configurăm și să instalăm sisteme de monitorizare precum Prometheus. Acesta ne permite să definim și să colectăm metrici custom. Acestea sunt expuse mai departe spre HPA printr-un adaptor (Prometheus Adapter), asemănător cu modul în care Metric Server le expune mai departe.
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2alpha1
metadata:
name: rv-epi-card-hpa
spec:
scaleTargetRef:
kind: Deployment
name: rv-epi-card
minReplicas: 2
maxReplicas: 8
metrics:
- type: Object
object:
target:
kind: Service
name: sample-metrics-app
metricName: http_request
targetValue: 256
În exemplul de mai sus, avem configurat fișierul *.yaml, astfel încât să reacționeze dacă numărul de requesturi HTTP este 256. HPA va monitoriza această metrică și se va asigura prin creșterea sau scăderea numărului de replici că numărul de requesturi HTTP care pot să fie servite de podul rv-epi-card este în jurul acestei valori.
Flexibilitatea de a crește dinamic dimensiunea unui cluster Kubernetes este specifică provideriilor de cloud, precum Azure. Acest lucru se datorează acțiunii de scalare în sine, care este la nivel de infrastructură și afectează direct numărul de mașini virtuale (VM) care sunt disponibile în cluster.
CA verifică odată la 10 secunde loadul curent al clusterului pe fiecare nod în parte. Integrarea actuală între HPA și CA permite CA să detecteze dacă HPA are nevoie să creeze noi replici, dar nu are suficiente resurse și poate să decidă automat să crească numărul de noduri.
Este important să remarcăm modul în care CA și HPA ia în considerare resursele consumate. HPA ține cont de numărul de resurse consumate de fiecare replică în parte în comparație cu CA care se uită direct la resursele necesare pentru fiecare replică în parte (specificate în *.yaml). În exemplul de mai jos avem o configurație de serviciu care specifică nevoia de 96MB de memorie și 25% dintr-un vCPU.
resources:
requests:
cpu: 250m
memory: 96Mb
În momentul în care CA detectează noduri care nu au nici o replică a unui pod sau serviciul care rulează pe acel nod pentru mai mult de 10 minute, atunci va decide să elimine acel nod din CA.
CA nu are capacitatea de a muta o replică de pe un nod pe altul, această responsabilitate aparține HPA-ului. Din această cauză, balansarea pe noduri pentru a optimiza numărul de noduri pe care clusterul îl are nu poate să fie automatizată doar cu aceste doua sisteme.
CA și HPA sunt două mecanisme care ne ajută să răspundem la nevoia de resurse și să scalăm în funcție de nevoile de care noi avem nevoie. HPA poate să răspundă în câteva secunde la un spike, în comparație cu CA, care are o latență de reacție. Pe lângă această latență, nu știm cât poate să dureze alocarea unui nou nod în cluster. Chiar dacă nu avem un SLA și știm că în general, durează circa 2-3 minute, s-ar putea ca această latență să fie mult prea mare și Să se repercuteze negativ asupra businessului.
Pe un deployment clasic de Kubernetes, nu am avea posibilitatea să reacționăm așa cum face CA, din cauză că nu am avea resurse hardware disponibile. În interiorul Azure, Microsoft ne oferă posibilitatea să integrăm Azure Container Instances (ACI) cu AKS. ACI este o soluție din zona SaaS care ne oferă posibilitatea să hostăm și să rulăm microserviciile noastre. Prin această integrare, avem posibilitatea să împingem temporar loadul din clusterul AKS spre ACI, până în momentul în care burstul trece sau alocăm noi noduri în cluster.
Putem să vedem ACI ca o locație virtuală, ca un pool de resurse pe care le folosim în momentul în care nu avem suficiente resurse. Integrarea pe care Azure a făcut-o între cele două sisteme este smart. Instanța de Kubernetes vede ACI ca o colecție de noduri din cluster pe care HPA poate să creeze replici. Aceste noduri virtuale sunt adăugate într-un subnet în interiorul clusterului, iar conexiunea între cele două servicii este una securizată. În interiorul la ACI, fiecare instanță de serviciu sau pod rulează într-un sandbox complex securizat și izolat.
Scalarea în interiorul AKS este flexibilă și destul de simplu de folosit. Având la dispoziție sistemele clasice a Kubernetes, precum HPA, putem să controlăm într-un mod unificat în toate environmentele pe care le avem. CA și ACI ne permit să facem lucruri, pe care până acuma nu le puteam face pe Kubernetes. Integrarea pe care acuma o avem cu scalarea dinamică a numărului de noduri și extinderea resurselor computaționale în ACI, ne permite să fim gata să preluăm loaduri care până acuma erau imposibil de gestionat pe deploymenturi on-premises.