ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 150
Numărul 149 Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 139
Abonament PDF

Inovație în Scalabilitate: Autoscalarea condusă de evenimente în Kubernetes

Mircea Talu
Junior DevOps Engineer @ Accesa



PROGRAMARE


Kubernetes Event-Driven Autoscaling (KEDA) este o unealtă open source, care permite scalarea automată a workloadurilor bazate pe evenimente în Kubernetes. Dar ce înseamnă asta pentru noi, ca dezvoltatori de aplicații sau administratori? Haideți să aruncăm o privire!

Ce înțelegem prin scalabilitate?

Scalabilitatea reprezintă una dintre cele mai relevante atribute ale unei aplicații la momentul actual. Abilitatea de a ridica sau elimina instanțe - în funcție de traficul pe care îl avem - este necesară pentru o utilizare eficientă a resurselor computaționale, dar și pentru a asigura disponibilitatea aplicației. Importanța utilizării eficiente a resurselor rezidă în considerente de ordin financiar, dar și legate de mediul înconjurător, disponibilitatea fiind crucială pentru o experiență bună a utilizatorului.

Cum putem atinge scalabilitatea?

În primul rând, pentru a putea scala un volum de muncă într-un mod eficient, acesta trebuie împărțit în bucăți cât mai mici. Spre exemplu, dacă avem un număr ridicat de utilizatori pe front-end și dorim să scalăm, nu putem face acest lucru dacă avem o structură monolitică (front-end și back-end în același container).

Ce este un container?

Un container este o unitate standard de software, care împachetează codul și dependințele sale, astfel încât aplicația să poată rula rapid și fiabil.

Unul dintre marile avantaje ale containerelor este faptul că acestea virtualizează sistemul de operare și creează un spațiu izolat pentru aplicație. În acest mod, putem rula containere pe orice mașină, indiferent de sistemul de operare, versiunea sa și mediul de rulare.

Drept urmare, este mult mai ușor să lansăm noi instanțe ale unei aplicații dacă aceasta este containerizată.

Cum administrăm o flotă de containere?

Odată cu creșterea popularității containerelor, inginerii software au întâmpinat o nouă problemă: cum pot fi administrate flote de containere într-un mod eficient și automat? Pe 9 septembrie 2014, Google a venit cu o soluție revoluționară: Kubernetes.

Kubernetes este un sistem open-source de orchestrare a containerelor pentru automatizarea implementării, scalării și gestionării software-ului. Pe scurt, haideți să înțelegem componenta principală a acestui sistem.

Ce este un Pod?

Podul reprezintă cea mai mică unitate care poate fi creată și administrată în Kubernetes, fiind un grup de unul sau mai multe containere, cu stocare și rețea comune și o specificație care explică cum trebuie rulate containerele. Ne putem gândi la un Pod ca la un înveliș pentru containere, care le face compatibile cu clusterul de Kubernetes.

Așadar, Podul este unitatea pe care dorim să o scalăm în funcție de volumul de lucru pe care îl are de procesat.

Ce face un HorizontalPodAutoscaler?

În Kubernetes, un HorizontalPodAutoscaler actualizează automat o resursă de workload (cum ar fi un Deployment sau StatefulSet), cu scopul de a scala automat numărul de Poduri pentru a se potrivi cererii. Aceasta este o resursă nativă în Kubernetes și poate fi folosită direct, fără nevoia unei extensii.

Scalare orizontală înseamnă că răspunsul la sarcina crescută este de a ridica mai multe Poduri. Acest lucru este diferit de scalarea verticală, care pentru Kubernetes ar însemna alocarea mai multor resurse - de exemplu: memorie sau CPU - Podurilor care rulează deja.

Care sunt limitările acestui HorizontalPodAutoscaler?

În ciuda importanței sale, principala limitare a HorizontalPodAutoscalerului este faptul că el scalează Podurile doar în funcție de cât CPU și memorie utilizează. De exemplu, dacă media de utilizare a CPU-ului pentru setul nostru de Poduri este mai mare decât valoarea dorită, vom ridica mai multe Poduri pentru a distribui workloadul. Dacă media este mai mică, vom elimina un număr de Poduri pentru a folosi resursele eficient.

Acest mod de scalare este folositor, dar el nu poate acoperi toate cazurile de utilizare exact așa cum ne-am dori. Deoarece HorizontalPodAutoscalerul este nativ pentru Kubernetes, el se uită doar în interiorul clusterului. Drept urmare, el nu ne poate rezolva problema scalării în funcție de stimuli externi.

Ce este Kubernetes Event-Driven Autoscaling?

Kubernetes Event-Driven Autoscaling (KEDA) este o componentă ușoară care poate fi adăugată în orice cluster Kubernetes. KEDA funcționează alături de componente standard Kubernetes, cum ar fi HorizontalPodAutoscaler și poate extinde funcționalitatea sa.

După cum îi spune numele, KEDA ne permite scalarea condusă de evenimente. Pentru a înțelege necesitatea sa, vom considera un caz inspirat din viața de zi cu zi.

Suntem managerul unui supermarket și trebuie să decidem când trebuie deschise/închise casele de plată. Inițial, avem o singură casă deschisă, deoarece traficul nu este mare dimineața. Dar, pe măsură ce ne îndreptăm către orele de vârf, supermarketul are tot mai mulți cumpărători. În funcție de care metrică vom decide dacă trebuie deschisă o nouă casă?

Dacă ne-am orienta după HorizontalPodAutoscaler, am deschide o nouă casă când utilizarea resurselor noastre (răbdarea casierilor) ar ajunge la limită. Aceasta nu pare o soluție optimă în cazul de față. Mai degrabă, am alege să deschidem o nouă casă atunci când numărul de cumpărători care așteaptă la coadă crește peste un anumit număr (10, spre exemplu). Astfel, scalăm în funcție de abilitatea noastră de a procesa cumpărătorii, care este, de fapt, ceea ce urmărim să facem. Dacă numărul de cumpărători care așteaptă la coadă crește peste 10, este evident că nu dispunem de numărul necesar de case pentru procesare.

Revenind de la acest exercițiu de gândire, vom încerca să transpunem problema într-o aplicație software. Înlocuim cumpărătorii cu mesaje care trebuie procesate, casierii cu containerele noastre și coada cu un queue (Kafka, RabbitMQ etc).

Figura 1. Analogie supermarket - aplicație

Pentru a reuși să obținem același mod de scalare, în funcție de mesaje (evenimente), trebuie să găsim un mod de a extinde acel HorizontalPodAutoscaler. Pentru asta vom folosi KEDA!

Cum integrăm KEDA?

Primul pas pe care îl vom face este să instalăm KEDA în clusterul nostru de Kubernetes. Această instalare ne definește o resursă personalizată (CustomResource) de tip ScaledObject. Această resursă o vom conecta la Deploymentul nostru de Poduri și ea va defini procesul de scalare prin intermediul unei configurații.

Instalarea nu este un proces dificil - ea poate fi efectuată cu ajutorul unui Helm chart.

Odată ce avem KEDA instalat în cluster, putem folosi resursele pe care ni le oferă. În exemplul de mai jos, vom utiliza un ScaledObject pe care îl vom conecta la aplicația noastră containerizată, denumită function. Această aplicație procesează mesaje dintr-un queue (Azure Service Bus Queue) și le afișează pe ecran.

Mai jos avem configurația resursei de tip ScaledObject.

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: {{ include "function.fullname" . }}
spec:
  scaleTargetRef:
    # apiVersion: {api-version-of-target-resource} 
    # Opțional. Implicit: apps/v1
    # kind: {kind-of-target-resource} 
    # Opțional. Implicit: Deployment
    name: {{ include "function.fullname" . }}
   # Obligatoriu. Trebuie să fie în același namespace 
   #cu ScaledObject-ul
   # envSourceContainerName: {container-name} 
   # Opțional. Implicit: 
   #.spec.template.spec.containers[0]
  pollingInterval:  30 
  # Opțional. Implicit: 30 de secunde

  cooldownPeriod:   30 
  # Opțional. Implicit: 300 de secunde

  idleReplicaCount: 0  
  # Opțional. Implicit: ignorat, trebuie să fie mai 
  # mic decât minReplicaCount 

  minReplicaCount:  1  # Opțional. Implicit: 0
  maxReplicaCount:  10 # Opțional. Implicit: 100

După cum putem vedea, avem de a face cu o serie de parametri care trebuie setați:

Starea idle apare atunci când coada noastră este goală pentru acea perioadă de timp specificată (30 de secunde, în cazul nostru). În imagine, idleReplicaCount este setat la 0, ceea ce înseamnă că vom opri toate instanțele aplicației noastre dacă ne aflăm în starea idle.

Acest procedeu deosebit se numește scalare la zero și este un atribut dezirabil pentru orice aplicație. În mod tradițional, dacă nu folosim KEDA, HorizontalPodAutoscalerul ar avea nevoie de cel puțin o instanță care rulează pentru a putea scala, datorită modului în care a fost construit. Însă, cu ajutorul KEDA, putem opri această instanță și apoi să o pornim doar atunci când vom avea din nou trafic, ca și cum nimic nu s-ar fi întâmplat.

minReplicaCount și maxReplicaCount sunt doi parametri sugestivi - ei setează minimul (1) și maximul (10) de instanțe pe care le putem avea atunci când nu ne aflăm în starea idle.

Excelent! Am reușit să configurăm scalarea cu doar cinci numere și un cuvânt!

Totuși, ceea ce ne rămâne de făcut este să îi transmitem lui KEDA care este acel queue la care trebuie să asculte și când trebuie declanșată scalarea.

triggers:
  - type: azure-servicebus
    metadata:
   # Necesar: queueName SAU topicName 
   # ȘI subscriptionName
      queueName: {{ .Values.queueName }}
      # Opțional, necesar când pod identity este 
      # folosită
      # namespace: service-bus-namespace
      # Opțional, se poate folosi și 
      # TriggerAuthentication

      connectionFromEnv: {{ .Values.env.name }}
      messageCount: "5" 
      # Opțional. Numărul de mesaje la care este 
      # declanșată scalarea. Implicit: 5 mesaje

      activationMessageCount: "2"
      # cloud: Private # Opțional. 
      # Implicit: AzurePublicCloud
      # endpointSuffix: servicebus.airgap.example 
      # Necesar când cloud=Private

Pentru acest lucru, vom folosi secțiunea de triggers (declanșatoare). Aici specificăm queue-ul la care ascultă KEDA (un Azure Service Bus Queue) și modul în care ne conectăm la acesta (connectionFromEnv), care este, de fapt, un connection string.

Ultimul parametru important este messageCount, numărul de mesaje la care vom lua măsuri. Dacă avem peste cinci mesaje adunate în queue, vom considera că viteza de procesare nu este suficientă și vom scala orizontal, adăugând Poduri.

După cum putem observa, KEDA este vendor-agnostic, suportând a gamă variată de furnizori și de evenimente declanșatoare, Azure Service Bus Queue fiind doar unul dintre ele.

Cum arată practic scalarea în cluster?

Singurul pas care ne-a rămas este să testăm dacă scalarea are loc așa cum ne așteptăm. Pentru a testa, vom trimite un număr uriaș de mesaje (10000) deodată în queue din portalul Azure. După câteva secunde, surprinsă de ultimele evenimente întâmplate, KEDA receptează schimbarea majoră care a avut loc la nivelul lungimii queue-ului și începe să ridice automat și rapid o întreagă flotă de Poduri pentru procesare. În imagine, am crescut numărul maxim de Poduri la 50 pentru a vizualiza mai ușor "cireașa de pe tort".

După ce toate mesajele sunt procesate și coada devine goală, KEDA va opri Podurile și nu vom rămâne cu niciunul, din moment ce ne vom afla în starea idle.

Cum încheiem acest capitol și ce înseamnă Event-Driven Autoscaling pentru viitor?

Într-o eră a microserviciilor, unde scalabilitatea reprezintă un aspect cheie și comunicarea asincronă prin queues, topics sau alte moduri de transmitere a mesajelor este des întâlnită în majoritatea aplicațiilor software, KEDA ne oferă o soluție simplă și extensibilă. KEDA facilitează astfel comunicarea asincronă, cel mai bun mod de comunicare între microservicii. Acest mod de comunicare nu necesită ca microserviciile să se aștepte unul pe celălalt precum într-un model Request-Reply.

Pe de altă parte, utilizarea eficientă a resurselor are atât un impact financiar important, cât și unul asupra mediului înconjurător.

În final, nu putem să uităm de cel mai mare avantaj pe care ni-l oferă KEDA: satisfacția inegalabilă de a urmări în timp real cum zeci sau chiar sute de Poduri pornesc instantaneu și ne "devorează" în întregime coada plină de mesaje.

NUMĂRUL 149 - Development with AI

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects