Arhitectura datelor și a sistemelor, de la zero Lecția 67 / 80

Optimizarea costurilor de compute: spot, autoscaling, right-sizing

Trei pârghii mută cea mai mare parte a facturii de compute: spot instances pentru workload-uri care tolerează întreruperea, autoscaling care răspunde la încărcare fără să oscileze și right-sizing-ul VM-urilor care sunt în mare parte supradimensionate. Capacitatea rezervată acoperă baseline-ul predictibil.

Lecția 65 a încadrat costul ca pe un aisberg, cu compute-ul drept partea vizibilă pe care o urmărește toată lumea. Lecția 66 a intrat adânc în storage. Lecția de față acoperă latura de compute: cele trei pârghii operaționale care, pentru majoritatea echipelor, generează cea mai mare parte a economiilor pe compute. Spot și preemptible instances pentru workload-urile care tolerează întreruperea. Autoscaling care răspunde la încărcarea reală fără să oscileze și fără să rateze vârfurile. Right-sizing pentru VM-urile care sunt supradimensionate de la ultima panică de capacitate de acum trei ani.

Lecția atinge și capacitatea rezervată (Reserved Instances și Savings Plans pe AWS, Committed Use Discounts pe GCP, Reservations pe Azure), care e o pârghie contractuală mai degrabă decât una arhitecturală, dar se compune cu munca arhitecturală. Și se încheie cu pattern-urile de autoscaling specifice Kubernetes (Cluster Autoscaler, Karpenter) pe care majoritatea echipelor moderne le vor întâlni mai devreme sau mai târziu.

Pârghia unu: spot și preemptible instances

Furnizorii de cloud operează la scară mare și, în orice moment dat, au capacitate excedentară care n-a fost alocată clienților on-demand. Vând acea capacitate excedentară cu un discount masiv, cu mențiunea că furnizorul o poate revendica cu preaviz scurt când cererea on-demand crește.

AWS le numește Spot Instances, cu economii de 60 până la 90 la sută față de ratele on-demand, în funcție de tipul de instanță și de regiune. Avertisment de revendicare la două minute. GCP are Spot VMs (fostele Preemptible VMs) cu 60 până la 91 la sută reducere și un avertisment de 30 de secunde. Azure are Spot Virtual Machines cu prețuri similare și un avertisment de 30 de secunde. Economia între cele trei e suficient de apropiată încât alegerea e de obicei dictată de pe ce rulează restul workload-ului, mai degrabă decât de prețul Spot izolat.

Economiile anunțate (60 până la 90 la sută) sunt reale, susținute și substanțiale. O echipă care rulează un workload ETL batch ce încape pe Spot plătește o fracțiune din factura unei echipe care rulează același workload pe on-demand. Întrebarea de încadrare nu e „ar trebui să folosim Spot”, ci „care dintre workload-urile noastre tolerează întreruperea”.

Workload-uri care se potrivesc bine pe Spot.

  • Batch jobs care sunt idempotente și retryable. Un ETL nocturn care poate fi reluat după o întrerupere e exemplul de manual.
  • Spark workers (executors). Driver-ul rulează de obicei pe on-demand sau pe o instanță stabilă, dar executorii pot fi pe Spot. Mecanismul de task-retry al Spark gestionează grațios pierderea unui executor.
  • Antrenare ML distribuită cu checkpointing. Un job de training care face checkpoint la câteva minute pierde cel mult câteva minute de progres când e revendicat.
  • Web workers stateless în spatele unui load balancer cu un pool sănătos de instanțe. Pierzi 20 la sută din capacitate pentru scurt timp, autoscaler-ul aduce înlocuiri.
  • CI/CD runners. Un build întrerupt face retry pe alt runner.

Workload-uri care nu se potrivesc pe Spot.

  • Servicii stateful cu o singură instanță. Pierderea instanței înseamnă pierderea stării.
  • Noduri leader în sisteme distribuite (controllers Kafka, Spark drivers, ZooKeeper, etcd). Pierderea unei alegeri de leader e recuperabilă, dar costisitoare, iar revendicarea Spot e prea frecventă ca să fie absorbită curat.
  • Joburi interactive lungi fără checkpointing. Revendicarea la jumătate înseamnă o luare de la zero.
  • Servicii sensibile la latență cu SLO-uri stricte pe tail-latency. Evenimentul de revendicare în sine produce un spike de latență în timpul failover-ului.

Pattern-ul matur e o flotă mixtă: un baseline on-demand sau Reserved pentru workload-urile care au nevoie de stabilitate, cu Spot pentru rest. Auto Scaling Groups pe AWS suportă asta direct prin „mixed instances policies”, lăsând echipa să specifice o capacitate de bază pe on-demand, cu restul completat din pool-uri de Spot. Karpenter (acoperit mai jos) merge mai departe și lasă cluster autoscaler-ul să aleagă Spot sau on-demand per pod, în funcție de toleranțele declarate.

Pârghia doi: autoscaling

Majoritatea workload-urilor n-au încărcare constantă. Traficul web atinge un vârf după-amiaza și scade noaptea. Joburile batch rulează în valuri. Query-urile analitice se grupează în jurul orelor de program. O flotă statică dimensionată pentru vârf e inactivă de cele mai multe ori, plătind pentru capacitate pe care n-o folosește.

Autoscaling-ul ajustează dimensiunea flotei ca să se potrivească încărcării observate. Făcut bine, echipa plătește pentru ceea ce folosește și nimic mai mult. Făcut prost, autoscaling-ul produce o factură mai proastă decât o flotă statică, pentru că oscilează între operații de scale-up și scale-down, nu reușește să răspundă suficient de repede la spike-urile de trafic (cauzând cereri pierdute și încălcări de SLO) sau scalează prematur pe semnale zgomotoase.

Mecanica e directă conceptual. Definești o metrică pe care autoscaler-ul o urmărește (utilizarea CPU, request rate, queue depth). Definești praguri la care adaugă sau elimină capacitate. Controller-ul de autoscaling verifică metrica la un interval și ajustează dimensiunea flotei.

Capcanele sunt mai subtile decât sugerează mecanica.

Oscilație. Scale up la 70 la sută CPU, scale down la 30 la sută. Adaugi o instanță la 70, media scade la 40, controller-ul scalează în jos, media urcă înapoi la 70, controller-ul scalează din nou în sus. Flota face ping-pong între dimensiuni, plătind în mod repetat pentru overhead-ul de pornire și oprire al instanțelor. Soluția e un gap de histerezis (scale up la 70, scale down la 40) și o perioadă de cooldown (după orice acțiune de scaling, așteaptă 10 minute înainte de a lua în considerare alta).

Scale-up lent. Apare un spike de trafic, autoscaler-ul decide să adauge capacitate, AWS provizionează o instanță în câteva minute, instanța bootează și rulează scriptul de inițializare încă un minut, load balancer-ul o marchează ca healthy după încă câteva secunde, și abia apoi începe să servească trafic. Timp total de la spike până la capacitate, vreo cinci minute. Dacă spike-ul e mai scurt de cinci minute, autoscaler-ul închide ușa de la grajd după ce a fugit calul. Soluția e o marjă de overcapacitate (target 60 la sută în loc de 80 la sută), warm pools (instanțe pre-inițializate gata să servească) și predictive scaling care se uită la pattern-uri istorice și scalează preemptiv.

Scale-down înainte ca încărcarea să scadă. Eșecul invers: încărcarea scade, autoscaler-ul scalează în jos pe baza semnalului imediat, apoi încărcarea revine și echipa rămâne fără capacitate. Soluția e scaling asimetric: scale up agresiv, scale down lent. O configurație tipică face scale up în 60 de secunde de la traversarea pragului superior și așteaptă 10 până la 15 minute de utilizare scăzută susținută înainte de scale down.

Latența de cold-start. Chiar și când capacitatea e disponibilă, un container sau VM proaspăt pornit e lent la primele câteva cereri pentru că JIT compiler-ul, cache-urile și connection pool-urile nu sunt încălzite. Echipa care ignoră cold-start-ul vede tail latency-ul sărind de fiecare dată când autoscaler-ul adaugă capacitate. Soluția e la nivel de aplicație (warm-up endpoints, connection pools pre-încălzite) plus la nivel de platformă (rampare graduală a traficului pentru instanțele noi).

Thrashing pe metrici zgomotoase. Utilizarea CPU e zgomotoasă pe instanțe mici și pe workload-uri bursty. Deciziile de scaling luate pe media de 10 secunde produc mai mult thrashing decât scaling-ul pe media de 5 minute. Soluția e netezirea metricilor (folosește medii pe 5 minute, ponderează observațiile recente puțin mai mult) și să iei în considerare scaling pe semnale mai stabile (queue depth, request rate) pentru workload-urile unde CPU e prea zgomotos.

Forma unei configurații de autoscaling bine reglate: utilizare țintă în jur de 60 până la 70 la sută, reguli de scaling asimetric, histerezis între pragurile de up și down, o perioadă de cooldown și predictive scaling stratificat deasupra pentru workload-urile cu pattern-uri zilnice puternice. Făcut bine, autoscaling-ul poate reduce factura unei flote cu 40 până la 60 la sută față de provizionarea statică dimensionată pentru vârf.

Pârghia trei: right-sizing

Majoritatea VM-urilor sunt supradimensionate. Tipul de instanță a fost ales la deployment-ul inițial pe baza unor presupuneri despre încărcare, umplut cu un margin de siguranță și niciodată reevaluat. Aplicația folosește acum 15 la sută din CPU și 30 la sută din memorie în medie, iar echipa plătește pentru 100 la sută din instanță.

Exercițiul e direct și ar trebui să fie o disciplină trimestrială.

flowchart LR
    Measure["Measure utilisation<br/>CPU, memory, disk, network<br/>over a representative week"] --> Recommend["Pick instance type<br/>with 30-40 percent headroom<br/>over observed peak"]
    Recommend --> Test["Test in staging<br/>under production-like load"]
    Test --> Deploy["Roll out gradually<br/>monitor for regressions"]
    Deploy --> Repeat["Revisit quarterly"]
    Repeat --> Measure

Fereastra de măsurare trebuie să surprindă ciclul natural al workload-ului. Un serviciu web cu pattern-uri săptămânale are nevoie de o săptămână de date. Un job batch cu cicluri lunare are nevoie de o lună. Vârful observat în fereastră, plus o marjă de siguranță de 30 până la 40 la sută, definește cel mai mic tip de instanță care încape.

Marja de 30 până la 40 la sută nu e arbitrară. Acoperă incertitudinea de măsurare, creșterea viitoare și spike-urile imprevizibile pe care fereastra de măsurare nu s-a întâmplat să le surprindă. O echipă care face right-size la 5 la sută marjă va petrece următorul trimestru stingând incendii pe instanțele care lovesc plafonul într-o zi aglomerată. O echipă care face right-size la 70 la sută marjă plătește pentru capacitate pe care n-o va folosi.

Atât AWS, cât și GCP livrează recommenders de right-sizing care automatizează măsurarea și recomandarea. AWS Compute Optimizer (https://aws.amazon.com/compute-optimizer/, consultat 2026-05-01) analizează metricile CloudWatch pentru EC2, EBS, Lambda, ECS și RDS și produce recomandări pentru tipuri de instanță mai mici, mai mari sau dintr-o familie diferită. GCP Recommender (https://cloud.google.com/recommender, consultat 2026-05-01) face echivalentul pentru Compute Engine, cu acoperire similară pe restul flotei GCP. Azure are Azure Advisor cu o categorie de cost optimization. Niciuna dintre cele trei nu e un substitut pentru judecata inginerească, dar elimină cea mai mare parte a muncii de colectare de date și oferă echipei un punct de pornire pentru discuție.

Right-sizing-ul e rara intervenție de cost fără cost arhitectural. Aplicația nu se schimbă. Instanța e înlocuită cu una mai mică din aceeași familie, workload-ul rulează același cod, comportamentul vizibil utilizatorului e identic, iar factura scade. Motivul pentru care echipele nu fac right-sizing mai des nu e că ar fi greu; e că rareori există un trigger forțat. O recenzie trimestrială de cost cu right-sizing pe agenda permanentă e practica ce-l face de rutină.

Capacitatea rezervată și committed use discounts

Reserved Instances (AWS) și Savings Plans (AWS), Committed Use Discounts (GCP) și Reservations (Azure) sunt instrumentele contractuale care schimbă un angajament multi-anual contra unui discount de 30 până la 60 la sută față de ratele on-demand. Mecanica diferă între furnizori; încadrarea e consistentă.

Argumentul de bază: un workload care oricum va rula continuu pentru următorii unu până la trei ani poate fi plătit în avans cu un discount semnificativ. Riscul e că workload-ul se schimbă (e retras, migrează la alt tip de instanță, se mută în altă regiune) înainte ca angajamentul să se maturizeze, lăsând echipa să plătească pentru capacitate pe care n-o poate folosi.

Disciplina e să măsori mai întâi baseline-ul predictibil. Minimul rolant pe 30 de zile al utilizării de compute, în instance-hours, e un proxy rezonabil pentru „capacitatea pe care echipa o folosește indiferent de situație”. Rezervă până la acel baseline. Lasă porțiunea variabilă deasupra pe on-demand sau Spot. Greșeala clasică e supra-rezervarea (blocând 80 la sută din utilizarea curentă, apoi descoperind că utilizarea curentă includea un workload deprecated care e retras, lăsând rezervarea orfană) sau sub-rezervarea (blocând 20 la sută și plătind preț întreg pe porțiunea predictibilă de deasupra).

AWS Savings Plans, introduse în 2019, au făcut calculul mai ușor decât modelul mai vechi de Reserved Instances: un Savings Plan se angajează la o cheltuială per oră în dolari mai degrabă decât la un tip specific de instanță, iar discountul se aplică flexibil pe familii și dimensiuni de instanțe. La nivelul anului 2026, Savings Plans sunt de obicei punctul de pornire potrivit pentru o echipă nouă în capacitatea rezervată pe AWS.

Pattern-ul combinat: capacitate rezervată sau angajată pentru baseline-ul predictibil, on-demand pentru vârfurile predictibile peste baseline, Spot pentru workload-urile care tolerează întreruperea. O platformă de date matură tipică are toate cele trei straturi rulând împreună, cu proporțiile reglate pe mixul de workload-uri.

Autoscaling specific Kubernetes

Pentru echipele care rulează pe Kubernetes, povestea de autoscaling are două straturi. Autoscaling-ul la nivel de pod (Horizontal Pod Autoscaler, Vertical Pod Autoscaler) decide câte replici de pod să ruleze și cât CPU și memorie cere fiecare pod. Autoscaling-ul la nivel de cluster decide câte VM-uri subiacente să ruleze ca să găzduiască acele pod-uri.

Cluster Autoscaler-ul a fost autoscaler-ul implicit la nivel de cluster încă din primii ani Kubernetes. Urmărește pod-urile neschedulabile și adaugă noduri din node pools configurate, și urmărește nodurile subutilizate și le elimină. Funcționează bine, dar e constrâns de modelul cu node pools: fiecare pool e un tip fix de instanță, iar autoscaler-ul poate alege doar câte din acel tip să ruleze.

Karpenter, introdus de AWS în 2021 și acum un proiect CNCF, e alternativa modernă. În loc de node pools fixe, Karpenter se uită la pod-urile pending, calculează tipul de instanță cu cea mai bună potrivire pentru fiecare lot și-l provizionează direct. Rezultatul e packing mai dens, scale-up mai rapid (Karpenter poate lansa noduri în vreo un minut, comparat cu câteva minute pentru Cluster Autoscaler) și cost mai mic pentru că alegerea instanței e conștientă de workload. Karpenter gestionează și integrarea Spot nativ, cu toleranțe declarate care lasă pod-urile să opteze pentru pool-uri de Spot.

Pentru o echipă pe EKS în 2026, Karpenter e alegerea recomandată. Cluster Autoscaler-ul încă funcționează și e încă potrivit pentru echipele care îl rulează deja stabil. Cluster-urile greenfield ar trebui să meargă implicit pe Karpenter. Documentația Karpenter (https://karpenter.sh/, consultat 2026-05-01) acoperă setup-ul și pattern-urile.

Punând totul cap la cap

Imaginea combinată a costului pentru o echipă matură de date care rulează pe AWS în 2026:

  • Baseline predictibil: Reserved Instances sau Savings Plans pentru 30 până la 60 la sută discount față de on-demand.
  • Vârf variabil: on-demand, dimensionat prin autoscaling care țintește 60 până la 70 la sută utilizare.
  • Workload-uri care tolerează întreruperea: Spot, integrat prin mixed-instances policies sau Karpenter.
  • Right-sizing: recenzie trimestrială cu recomandările Compute Optimizer ca punct de pornire.

O echipă care rulează toate cele patru pârghii bine captează în mod tipic 50 până la 70 la sută economii față de o factură de compute neoptimizată. O echipă care nu rulează niciuna lasă cea mai mare parte a economiilor disponibile pe masă. Cele mai multe echipe stau undeva la mijloc, cu una sau două pârghii în joc și restul pe backlog.

Firul care leagă primele trei lecții ale Modulului 9: costul nu e un proiect punctual. E o disciplină. Lecția 65 a încadrat aisbergul. Lecția 66 a acoperit pârghiile de storage. Lecția aceasta a acoperit compute-ul. Lecțiile următoare din modul intră în optimizarea la nivel de query, pattern-uri arhitecturale de cost (multi-region versus single-region, costuri de trafic în microservicii, trade-off-uri serverless versus provizionat) și practicile culturale care țin costul ca pe o preocupare comună alături de fiabilitate și performanță.

Citări și lectură suplimentară

  • AWS, EC2 Spot Instances, https://aws.amazon.com/ec2/spot/ (consultat 2026-05-01). Modelul de pricing, mecanica întreruperii și pattern-urile de integrare cu Auto Scaling Groups.
  • GCP, Spot VMs, https://cloud.google.com/compute/docs/instances/spot (consultat 2026-05-01). Pricing și mecanica preempțiunii pe GCP.
  • AWS Compute Optimizer, https://aws.amazon.com/compute-optimizer/ (consultat 2026-05-01). Recomandări de right-sizing pentru EC2, EBS, Lambda, ECS și RDS.
  • GCP Recommender, https://cloud.google.com/recommender (consultat 2026-05-01). Serviciul echivalent de recomandări pe GCP.
  • AWS, Savings Plans, https://aws.amazon.com/savingsplans/ (consultat 2026-05-01). Mecanismul flexibil de discount bazat pe angajament.
  • Karpenter, https://karpenter.sh/ (consultat 2026-05-01). Autoscaler-ul modern de noduri pentru Kubernetes, cu documentație despre instalare, configurarea NodePool și integrarea Spot.
  • Proiectul Kubernetes Autoscaler, https://github.com/kubernetes/autoscaler (consultat 2026-05-01). Implementările de referință pentru Cluster Autoscaler și Vertical Pod Autoscaler.
  • FinOps Foundation, grupul de lucru „Rate optimisation”, https://www.finops.org/ (consultat 2026-05-01). Resurse comunitare despre Spot, capacitate rezervată și right-sizing ca parte din practica FinOps mai largă.
Caută