Diego Braga, Cloud Native Solution Architect in Kiratech, intervista Giulio Roggero, CTO & Founder Mia-Platform.
Diego Braga è curatore degli episodi del canale Youtube 'Cloud Native Community', aperto con l'obiettivo di trasmettere alla community italiana informazioni legate al mondo Cloud e DevOps in modo fresco e colloquiale, invitando ogni volta ospiti che portano la loro esperienza di rilievo, i loro punti di vista e le loro considerazioni sul tema del giorno. Il protagonista di questa intervista è Giulio Roggero, CTO e speaker internazionale, profondo conoscitore dell’ecosistema Kubernetes.
Guarda il video o leggi l’intervista di seguito!
Diego: Oggi parliamo dei costi delle applicazioni Cloud Native, un tema semplice solo in apparenza. Soprattutto nel design di un’applicazione, i costi andrebbero considerati fin dai primi passi del progetto.
Giulio, prima di cominciare con le domande, ci racconti brevemente chi sei e di cosa ti occupi?
Giulio: Sono CTO e co-founder di Mia-Platform, una soluzione per sviluppare applicazioni cloud native o piattaforme (a noi piace chiamarla meta-piattaforma). Nel mio ruolo ho a che fare tutti i giorni con applicazioni che vanno in produzione, problemi in produzione, costi che salgono e che vanno tenuti sotto controllo.
Noi diciamo sempre: “ogni euro risparmiato è un euro guadagnato”.
D: Giusto! Entriamo nel merito del tema di oggi: applicazioni Cloud Native e costi che, essendo appunto Cloud Native, possono girare su varie infrastrutture. On premise, in cloud, su più cloud, multi-cloud, ecc.
Partiamo però dal principio: se ti dovessero chiedere di definire cos’è un’applicazione cloud native, qual è la spiegazione più semplice che riusciresti a dare?
G: Se aprissimo ora Google e cercassimo “Cloud Native” probabilmente ci uscirebbe “The Twelve-Factor App”. Lascerei un attimo da parte questo concetto perché nel tempo è stato rivisitato e riadattato.
Di fatto le applicazioni software sono applicazioni che devono essere realizzate secondo certi paradigmi: clean code, TDD, responsabilità chiara sia a livello di nomi che di runtime, facile manutenzione, ecc.
Queste sono le caratteristiche delle applicazioni software in generale.
A volte si attribuiscono queste caratteristiche alle applicazioni Cloud Native, anche se mi permetto di dire che è un po’ riduttivo perché le applicazioni Cloud Native hanno diverse caratteristiche in più. Noi ne abbiamo individuate 7, ma quelle a cui tengo maggiormente sono:
- L’applicazione deve fare un log che sia comprensibile e tracciabile e storicamente gestito in modo da poter fare troubleshooting. Essendo applicazioni che scalano in modo dinamico, i log tendenzialmente devono andare tutti in un unico punto (non posso mapparli in modo sparso) e devono essere ordinati temporalmente.
- L’applicazione deve essere piccola dal punto di vista della gestione e delle risorse perché deve poter scalare in alto o in basso in modo rapido. Ogni volta che aumento la replica dell’applicazione, ad esempio, non può metterci 8 minuti a partire ma deve metterci solo qualche secondo.
- Deve essere possibile misurarla sia a livello di stato di salute e readiness, sia a livello di metriche esposte, altrimenti si perde il filo di cosa si sta facendo. Quando hai centinaia di repliche della stessa applicazione e inizi ad avere dei problemi, non riesci più a leggere i log e l’aggregazione diventa difficile: quello che ti salva è la misurazione nell’osservare cosa sta facendo in quel momento l’applicazione, quanti messaggi sta scodando al secondo, quanti sono in coda - ad esempio da una coda kafka -, ecc. L’applicazione cloud native deve essere osservabile in modo che io possa, in modo automatico o semi-automatico, ripararla e ripristinare il sistema nella sua continuità.
D: Speravo proprio che non spiegassi i 12 factor!
Ma quindi non c’è bisogno di un microservizio perché l’applicazione sia Cloud Native?
G: Non saprei dirti se ci sia bisogno oppure no. Un’applicazione Cloud Native ha le caratteristiche che abbiamo visto, e anche altre. Che queste caratteristiche siano condizioni necessarie per un microservizio è abbastanza logico, ma non è detto che un’applicazione Cloud Native sia un microservizio.
D’altro canto sono ormai talmente sovrapposti i concetti che viene più semplice applicare lo stesso meccanismo che applichiamo quando chiamiamo “Scottex” la carta assorbente, indipendentemente dal marchio che stiamo utilizzando.
D: Bella questa metafora!
Sono d’accordo, spesso si dà per scontato che l’applicazione Cloud Native debba andare su container, ma quello che hai appena spiegato è applicabile anche a una piccolissima applicazione che gira su un server minimale. È chiaro però che andando verso il mondo dei container e di Kubernetes abbiamo dei costrutti che ci permettono anche di definire by code quelli che sono i limiti maggiori o minori che una di queste risorse dovrà andare a consumare. Quindi si possono fare delle reservation, si possono mettere dei limiti, è tutto più complicato ed esplicativo.
La mia prossima domanda è: come faccio a capire fin dall’inizio, e a livello di risorse, cosa occuperà la mia applicazione, quali risorse devo prevedere, e se in base a queste informazioni devo disegnare la mia applicazione in un modo piuttosto che in un altro?
G: Questa è una domanda difficilissima, sulla quale ancora non ho una risposta. Stiamo però studiando il tema e provo a condividere dei parametri sui quali si può fare una metrica e avere una buona misura.
È vero che le applicazioni Cloud Native non vanno per forza su container e possono andare su infrastruttura, è vero anche che i container kubernetes stanno facendo emergere delle API Standard che probabilmente diventeranno standard per gestire e orchestrare sistemi operativi distribuiti (come mi piace chiamare Kubernetes).
Da questo punto di vista, diventa importante anche capire come vado a segnare i limiti delle mie risorse per ottimizzare il carico dell’infrastruttura.
Come vado a capire se quel programma, quell’applicativo, quel servizio o quel container sia dimensionato in modo corretto? L’unico modo che abbiamo trovato noi è avere una tabella strutturata in base al linguaggio di programmazione usato.
Prendiamo un sottoinsieme: sviluppo greenfield di una logica applicativa dentro un container; all’interno potresti sviluppare con linguaggi più standard degli application server (classico Java all’interno di uno Spring Boot, o Python e Node.js fino ad arrivare a Elixir, Rust, Go).
Abbiamo preso tanti ‘hello world’ e li abbiamo fatti partire per capire il fingerprint di memoria (diverso da quello della CPU).
Abbiamo fatto un po’ di prove e abbiamo visto che Java in partenza fa dai 150 ai 300 megabyte di RAM di occupazione, Node.js sui 50, Go sui 5, con Rust e C++ siamo arrivati a meno di 5. Se però a quel 5 faccio fare un milione di richieste al minuto, ovviamente aumenterà la dimensione.
Il linguaggio di programmazione - e il framework sottostante - è importante per ridurre il fingerprint ma non basta perché va capito che stress viene posto all’applicativo. Qui diventa molto importante fare stress test.
Questo vale per tutte le applicazioni non su container, perché anche in questo caso è necessario effettuare un dimensionamento e un capacity plan; si tende a non farli perché si dà per scontato di avere un’infrastruttura talmente grande che non ce ne sarà bisogno
In una soluzione cloud questo non è possibile, tant’è che solitamente si passa al cloud per risparmiare.
Nel cloud vado a spendere solo quello che mi serve, quindi stresso il sistema per fare un capacity plan corretto a seconda della CPU e della RAM facendo stress test con varie condizioni a contorno.
D: La domanda che ne consegue è: mettiamo che io sia su cloud, come faccio a vedere quali sono i costi di un’applicazione e come li monitoro? Devo per forza avere un prodotto del cloud provider? E se sono in modalità IaaS?
Qual è la tua esperienza?
G: Per ogni pod hai la possibilità di assegnare dei limiti e delle request alla CPU e alla RAM. A quel punto il pod consumerà entro quei limiti e puoi misurare quanta RAM e CPU sta consumando in quel momento.
Il pod è quindi la tua misurazione di base, il punto di partenza. Se inizi a misurare in modo periodico quanta RAM e CPU consuma il tuo pod, puoi fare costo x RAM e costo x CPU e tirare fuori un costo per singolo pod. Questa può essere una base di partenza.
Per assegnare i limiti di CPU e RAM abbiamo già visto che sono utili gli stress test. La vertical pod autoscaling di kubernetes può essere utile per suggerirti questi limiti: questo ti aiuta a dimensionare ed essere tranquillo.
Può succedere che, nonostante il dimensionamento, quel servizio non sia usato come ti aspettavi ma sia usato pochissimo. Potresti avere così un margine molto alto tra quello che ti aspettavi e quello che è stato effettivamente usato e avere un cost saving potenziale che puoi fare sul singolo pod.
Quindi, se prendiamo ad esempio un contesto dove abbiamo:
- singola applicazione con un aggregato di microservizi all’interno di un namespace di pochi microservizi
- singolo team
- singolo cluster
Diventa abbastanza semplice misurare perché ho metriche raccolte, ad esempio, da Prometheus e ho uno storico di consumi e sui quali posso andare a fare i miei calcoli. Questa è una soluzione manuale ma fattibile.
Inizia a essere un problema quando quel cluster Kubernetes è usato da più applicazioni, da più team, o addirittura da più team di diverse aree della stessa azienda con unit di costo differenti.
A quel punto devi iniziare a taggare con delle lable tutti i tuoi pod per poter fare un aggregato di questi costi per consumo di ogni singolo pod.
Su questo aspetto ci sono un po’ di soluzioni che aiutano: kubemodel, ad esempio, è un progetto open source che ti aiuta a fare questo lavoro.
Concettualmente è abbastanza semplice: ho i costi di CPU consumata, di RAM consumata, e posso farlo sia su cloud sia su on premise.
D: È vero e posso farlo su Google, Amazon, e su qualsiasi cloud.
Andare a costruire il proprio modello di costo come suggerisci potrebbe essere vincente.
Ora che abbiamo visto come monitorare CPU e RAM, e relativi costi - e quindi ho l’ observability - come faccio a tenerli sotto controllo? C’è un modo per rilevare se sto uscendo dalla trend line o se sto consumando troppo/troppo poco rispetto al previsto.
G: Noi abbiamo, ad esempio, diversi cluster con qualche migliaio di pod che girano. Non è banalissimo gestire tutti i costi perché i team vanno per conto proprio.
Nella mia esperienza ho imparato a mettere prima di tutto degli allarmi sui costi macro secondo il mio budget globale, che ogni tot % scattano, sia sotto che sopra il 100% (soprattutto sopra il 100%!). Quando arriva l’allarme al 50% guardo che giorno del mese è e vedo se siamo in linea oppure no.
Poi ogni progetto ha il suo billing, le sue aggregazioni di costo, e finchè ti può aiutare il cloud provider ci arrivi nello stesso modo che sul globale.
Quando non arrivi fino a lì, puoi allora usare gli allarmi su Prometheus che sono sul consumo di risorse aggregate su namespace.
Non l’ho ancora provato, ma mi sembra molto interessante come approccio l’auto pilot di Google che ti fa il billing per singolo pod running CPU, ma è uscito davvero da poco e va ancora capito e sperimentato.
Di sicuro darsi degli allarmi su un budget prefissato è la cosa più importante, e va verificato a periodi fissi e valutato di volta in volta in base all’ingresso di nuovi progetti o nuove variabili.
D: Quindi bisogna verificare costantemente il consumo misurato vs quello atteso e andare a vedere il motivo: può essere di business, che sta crescendo, oppure dovuto a dei problemi implementativi.
Ora ti chiedo: le figure che fanno questa analisi dei costi sono all’interno del progetto e del feature team o ci sono persone dedicate?
G: Chi controlla i costi tendenzialmente fa budget e cost control fuori dal team, si tratta di un’area separata. Chi però ti deve dare le informazioni e viene allertato dagli allarmi è il feature team. Il feature team è responsabile di spendere quel budget e risparmiare, mentre il controllo è eseguito da un’area esterna in modo che ci sia riconciliazione tra quanto pagato in fattura e quanto avevo previsto e monitorato nei miei sistemi di gestione. Questo perché il rischio è pensare di spendere x, in realtà aver pagato y e non accorgersene.
Devi coinvolgere l’area finanziaria dell’azienda perché il rischio è fare un bellissimo lavoro tecnico ma non è per forza un lavoro che porta valore all’azienda, e non sempre i team hanno accesso alle fatture che arrivano.
D: Chiaro, quindi il cost controller chiama il feature team e insieme vedono da dove derivano gli spostamenti di budget che sono stati rilevati.
Possiamo dire che l’unico modo di confrontare i costi tra i vari cloud è quello di costruirsi un proprio modello di controllo dei costi?
G: Noi ci stiamo provando. Confrontare i costi tra cloud vendor non è banale, perché un conto è guardare il listino, un altro è iniziare a fare un po’ di reservation, fare attenzione a come vai ad allocare i tuoi node pull sotto Kubernetes a seconda della tipologia di macchine, ecc. Così inizi ad avere un mix di costi che non è facilmente confrontabile.
In questo momento storico puoi costruire un tuo modello, in alternativa ci sono soluzioni di mercato che ti aiutano a farlo. Noi al momento stiamo costruendo il nostro anche a seconda di quanto andiamo a riservare e comprare CPU per il futuro. Questo diventa poi un po’ un borsino delle risorse perché ti permette di monitorarle anche negli anni e fare un vero capacity plan.
Il capacity plan è davvero importante sul cloud, unito a qualche intuizione buona sul futuro.
È ancora complesso capire se spostare l'applicazione da un cloud all’altro, però conviene avere un modello per capire come orientarsi e al momento sul mercato non sembra esserci niente.
Ti faccio un esempio: parlo di Google ma vale anche per gli altri, AWS, ecc.
Tu puoi riservarti le CPU per 3 anni con un risparmio di costi notevole. Il problema è che se ti riservi le cpu, il downscaling a cosa serve? Io posso sempre fare downscale dei miei cluster, quindi ridurre o spegnere i pod, ma si tratta di consumi già acquistati.
Davide Bianchi, Senior Technical Leader di Mia-Platform, ha appena sviluppato Kube-green, un progetto open source che spegne i pod inutilizzati e li fa ripartire quando servono. Ma se compri cpu per 3 anni allora tanto vale lasciare tutto acceso.
Qui inizia a essere una questione non solo di costi ma anche etica e ambientale, quindi vale la pena fare un buon borsino con il totale a 3 anni, a 1 anno e variabile. Questo mix è la vera arte della “FinOps” perché se riesci a fare questo mix riesci a essere davvero efficace sulla scaling dei costi.
D: Il downscaling in effetti è qualcosa che troppo spesso si sottovaluta, anche per ambienti di sviluppo.
Noi stiamo parlando di multi cloud, ma io continuo a sostenere che anche il mio datacenter che ho in casa sia un cloud se lavoro in cloud, ma così è ancora più difficile confrontare i costi tra private e public cloud.
G: Se ci pensi il vantaggio di Kubernetes, container e Docker è che hanno tolto il concetto che posso condividere solo un’applicazione. Posso invece condividerne diverse condividendo le millicpu. La prima volta che l’ho letto mi ha molto colpito perché ho realizzato che puoi realmente dividere in millicpu, quindi una millicpu=un core ti fa capire quanto puoi condividere sulla stessa infrastruttura. A quel punto anche se la tua infrastruttura ha un costo definito, puoi renderla sempre più efficace ed efficiente mettendo in condivisione sempre più cose senza per forza fare scaling.
D: Bisogna considerare poi costi vs performance. Anche le performance sono una metrica che deve essere considerata.
“Il Cloud Native molto bello ma io sto spendendo molto più di quello che mi aspettavo”, ti hanno mai fatto questa osservazione?
G: Dipende cosa ci hai messo sopra, se hai messo cose grosse, dentro non ci risparmi molto, ma se hai messo cose piccole, che scalano in modo dinamico, allora lì puoi effettivamente avere un risparmio. Il classico elefante monolitico su cloud non ti fa risparmiare ma anzi magari ci perdi.
Se porto l’elefante su cloud e poi riduco il networking, inizio ad affettare e a modulare lo scaling, allora inizio a risparmiare.
Ad oggi ancora non mi hanno detto “mi è costato molto di più andare su cloud” ma sicuramente il beneficio lo hai dopo un po’ che hai un’architettura Cloud Native vera, altrimenti non è detto che avrai realmente beneficio.
D: La buzzword del 2021 è FinOps: ed è davvero un tema per cui se voglio fare multi cloud, zero lock in, ecc, il controllo dei costi su cloud è qualcosa che deve tassativamente essere messo in priorità massima. Sei d’accordo?
G: Sì, dal giorno 0 devi mettere gli allarmi su quanto spendi altrimenti puoi considerarti cieco. Apri l’account e metti gli allarmi. Anche sul 120% di spesa. Ma anche sul 200%.
Ridurre il debito tecnico è una cosa professionalmente etica da fare e lo diamo per scontato. Stiamo però passando a un nuovo livello di etica da integrare, che è quella ambientale, che consideri quello che consumiamo e quanto impattiamo.
Bitcoin e blockchain consumano tantissima energia ma non credo che inizialmente fosse stato previsto.
Il software che scriviamo oggi esisterà anche tra 10 anni, e se scalerà come deve farlo? Con milioni di utenti potrebbe consumare tantissima energia in più rispetto a quello che vediamo oggi.
Quello sarà il debito tecnico sul cloud native dei prossimi anni. Avremo bisogno di cluster giganteschi se non stiamo attenti a ridurre al minimo il fingerprint dei nostri pod.
Questi sono i problemi che stiamo creando oggi e che dovremo risolvere in futuro.
© MIA s.r.l. Tutti i diritti riservati