Dalle VMs al Serverless, passando per i Container
Container, macchine virtuali (VMs) e serverless computing: un viaggio all’interno della virtualizzazione a tutti i livelli per scoprire qual è il modo migliore per sviluppare, eseguire e gestire le applicazioni in questo tempo carico di nuove idee, devices ed esperienze digitali.
La virtualizzazione, le tecnologie su cui si basano i container e anche molti paradigmi su cui si fonda la definizione di cloud non sono idee nuove nel mondo dell’informatica. Nuovo è il panorama che si delinea: l’evoluzione dal bare metal alle architetture serverless, transitando per virtualizzazione e container, non è solo un’evoluzione tecnologica, ma l’immagine di un nuovo modo di intendere il business ed i suoi strumenti.
Virtualizzazione e Virtual Machine
La virtualizzazione è oggi una tecnologia consolidata, della quale si è ormai detto tutto e che affonda le sue radici addirittura nei sistemi IBM 370 degli anni ‘70. VMWare, uno dei leader nel settore, ha ormai compiuto oltre 20 anni, Red Hat si è ritagliata uno spazio significativo in questo mercato già dal 2008 con l’acquisizione di Qumranet, e con la presentazione delle prime versioni di Red Hat Virtualization.
Sebbene sia lontana dall’essere una novità, vale la pena iniziare proprio qui il nostro discorso per meglio comprendere quali contesti e quali motivazioni hanno spinto l’evoluzione dei sistemi, dei servizi e del business IT in generale nella direzione che oggi vediamo.
Sul finire degli anni ’90 molte aziende che utilizzavano server fisici e stack software associati a un singolo fornitore cominciarono ad aggiornare i propri ambienti ricorrendo a sistemi operativi ed applicazioni meno costosi di vendor eterogenei, restando però sempre vincolate ad hardware fisici utilizzati poco o in modo poco ottimizzato.
La virtualizzazione, cioè il partizionamento dei sistemi fisici in sistemi virtuali, apparve come la soluzione naturale almeno per due ordini di problemi: da un lato consente di ottimizzare l’utilizzo delle risorse ma offre anche la possibilità di gestire i sistemi in modo più flessbile.
Senza approfondire gli aspetti tecnologici, i sistemi virtuali o virtual machine, sono server a tutti gli effetti, isolati ed indipendenti gli uni dagli altri: hanno il proprio sistema operativo, i propri software e servizi e dispongono di risorse dedicate. L’hardware, che comprende cpu, ram, schede di rete, storage, è costituito da un’astrazione del sistema fisico. Di conseguenza server Linux, Windows, Unix possono convivere sul medesimo hardware fisico.
Con una semplificazione estrema, Microsoft Azure definisce le VMs come un “file, tipicamente chiamato immagine, che si comporta come un pc. In altre parole, è un pc creato dentro ad un pc”.
L’astrazione dell’hardware e la possiblità di eseguire virtual machine è garantita dall’hypervisor, anche chiamato system monitor, costituito da un livello software e da funzionalità messe a disposizione dall’hardware e dal firmware della maggior parte dei modermi sistemi.
Un’infrastruttura basata su virtual machine si comporta a tutti gli effetti come un’infrastruttura fisica, rispetto alla quale garantisce una migliore allocazione delle risorse, maggiore affidabilità e semplicità di gestione.
La virtualizzazione offre una prima risposta alle necessità di consolidamento, ottimizzazione e riduzione dei costi, senza tuttavia introdurre un elemento di vera innovazione nella definizione dei processi e dei servizi.
Non solo: una virtual machine, dal punto di vista dell’hypervisor, è un processo sempre attivo e, in quanto tale, occupa risorse (cpu, ram, storage) anche quando non è direttamente coinvolta nell’erogazione di un servizio.
Si può fare di meglio? Si possono coniugare consolidamento, efficienza, rapidità di sviluppo e deploy e capacità di scaling out?
Negli scenari opportuni, i container possono costituire una valida alternativa.
Container
I container non solo offrono la possibilità di superare alcuni limiti della virtualizzazione tradizionale, ma pongono le basi per un cambiamento radicale nel modo di intendere lo sviluppo ed il ciclo di vita dei servizi.
Container: un po’ di storia
L’idea alla base dei container non è nata nel mondo Linux ma affonda le proprie radici in una tecnologia nota come jail FreeBSD, comparsa nel 2000, che consente il partizionamento di un sistema FreeBSD in sottosistemi (jail) isolati sia tra di loro sia rispetto al sistema sottostante estendendo il concetto di chroot.
Questo è stato portato nel mondo Linux con il progetto Linux Vserver ed è stato integrato negli anni successivi con nuove tecnologie, tra cui cgroup, systemd, Linux Kernel Namespace, delineando così il progetto Linux Container (LXC).
Nel 2008, con l’ingresso in scena di Docker, sono stati aggiunti nuovi strumenti e nuove idee, quali la possibilità di creare immagini stratificate (derivanti, cioè, dalla fusione di più immagini) e l’introduzione dell’image registry. I progetti riguardanti i container nel mondo Linux hanno quindi ricevuto una nuova spinta che ha portato fino alla nascita della Open Container Initiative, i cui membri, tra cui Docker e Red Hat, collaborano per la definizione di standard aperti e condivisi per le tecnologie container.
Con queste premesse e questi strumenti a disposizione, è naturale interrogarsi per capire se esistano alternative alla virtualizzazione tradizionale.
Perché virtualizzare tutto un sistema a partire dall’hardware quando sarebbe sufficiente virtualizzare, in senso lato, il sistema operativo, offrendo agli applicativi un ambiente di esecuzione semplificato, isolato e consistente?
Per ottenere questo risultato è possibile creare un container, cioè un ambiente costituito sia da un’immagine in cui sono presenti il codice o l’applicazione, gli strumenti e le librerie sia dal contesto runtime necessario.
> Leggi anche: “Docker e Kubernetes: passato, presente e futuro dei container”
Container: caratteristiche
Al di là degli aspetti più strettamente tecnici, un container Linux è l’insieme di uno o più processi isolati dal resto del sistema, che
- presentano un’interfaccia di gestione standard (per l’avvio, l’arresto, le variabili d’ambiente),
- ottimizzano l’impiego delle risorse rispetto alle virtual machine,
- semplificano la gestione di applicazioni più ampie (distribuite su più container)
- e vengono eseguiti a partire da immagini appositamente costruite.
La presenza degli standard proposti da enti di standardizzazione garantisce inoltre interoperabilità e possibilità di orchestrare i container anche tra cloud differenti.
Container: innovazione
Il concetto di immagini ed il modo di costruirle ed aggregarle costituisce l’aspetto più significativo ed innovativo, non tanto da un punto di vista tecnologico, quanto per l’impatto che ha sullo sviluppo e sulla gestione operativa, con conseguenze che si ripercuotono anche sul modo di intendere il business.
Le immagini sono immutabili, questo significa che ogni container eseguito a partire dalla stessa immagine è identico agli altri, non conserva in sé informazioni di stato o dati persistenti. La persistenza è affidata ad altri strumenti quali database e filesystem esterni. Questo determina, in primo luogo, una netta distinzione tra l’ambiente runtime dell’applicazione ed i dati su cui questa opera, introducendo logiche di separazione funzionale che portano benefici in termini di pulizia, gestione del processo e sicurezza.
La vera innovazione nel processo di sviluppo e nel ciclo di vita dell’applicazione risiede nel fatto che una volta creato, su una o più immagini, un ambiente operativo completo e consistente, separato dai dati su cui opera, questo potrà attraversare tutte le fasi dallo sviluppo alla produzione senza subire variazioni.
Lo stesso container eseguito sul pc di uno sviluppatore potrà essere recuperato dal registro e portato in test o produzione, istanziato una o più volte (scaling out), così da poter fronteggiare esigenze di carico variabili, oppure distrutto e re-istanziato nella sua forma originale nel caso in cui venga compromesso.
I benefici che derivano da questo nuovo modo di operare sono evidenti: portabilità, controllo delle versioni, sicurezza e, soprattutto, una drastica riduzione del time to market e dei costi ad esso connessi.
Serverless
I container, sebbene permettano di migliorare l’allocazione delle risorse rispetto alle virtual machine, non consentono realmente di scalare a zero e di crescere in modo lineare: quando un container non eroga servizi, rimane comunque attivo come processo. Una risposta a questa esigenza può venire da approcci serveless,
Un’allocazione davvero efficiente delle risorse richiede che tutta la potenza di calcolo venga effettivamente istanziata solo on demand e che sia rilasciata immediatamente dopo l’uso.
I primi passi in questa direzione furono compiuti da Google con l’introduzione del Google App Engine nel 2008 ma la vera spinta è giunta con l’introduzione da parte di Amazon nel 2014 di AWS Lambda, primo vero modello FaaS. Successivamente si sono aggiunte soluzioni alternative proposte da altri vendor: Microsoft con Azure Functions, Ibm e Google con le proprie Cloud Functions. Anche il mondo open source si è mosso in questa direzione con il rilascio di prodotti quali Apache OpenWhisk, OpenLambda ed IronFunctions.
Il serverless computing è una delle modalità per la distribuzione di servizi in un contesto cloud che prevede l’esecuzione di applicazioni o, più correttamente, funzioni, senza che questo richieda alcuna visibilità dell’infrastruttura sottostante: provisioning, scaling e gestione avvengono modo automatico e lineare solo a fronte di reali richieste e necessità. Il termine serverless non è quindi da intendersi come “assenza” di server ma come trasparenza dei sistemi coinvolti dal punto di vista degli sviluppatori e degli utenti.
Questa caratteristica fa sì che il paradigma DevOps, tipico nell’impiego di tecnologie a container, venga abbandonato per tornare ad una nuova, più netta, distinzione tra la componente infrastrutturale e quella applicativa, introducendo due nuovi concetti nel mondo cloud:
- FaaS (Function as a Service) che consente agli sviluppatori di disporre di un ambiente di esecuzione delle proprie applicazioni (siano esse C#, Java, Node.js, Python, ecc.) che viene istanziato solo a fronte di determinati eventi;
- BaaS (Backend as a Service) che permette di demandare a terze parti funzionalità tipiche delle applicaizioni non dovendole implementare in prima persona (è ad esempio il caso di servizi come Auth0 che offre funzionalità di identity management ed autenticazione).
Serverless: funzionamento
Un approccio serverless presuppone che la logica di esecuzione non dipenda dallo stato dei sistemi, analogamente a quanto già descritto per i container, ma si spinge oltre.
In un ambito container, possiamo identificare un’applicazione anche complessa con un container. In un contesto serverless invece dobbiamo immaginare un’applicazione come l’integrazione di diversi elementi: funzioni di calcolo, servizi di comunicazione e segnalazione, servizi di archiviazione e reperimento dei dati.
Queste componenti devono essere attivate on demand ed essere in grado di interagire tra loro, con altri sistemi e con gli utenti: di conseguenza gli eventi costituiscono il punto di collegamento e lo strumento d’interazione che è caratteristico della logica serverless.
Le funzioni FaaS possono quindi essere richiamate da eventi definiti e messi a disposizione direttamente dal provider di servizi: con Amazon AWS, ad esempio, gli eventi sono rappresentati dagli aggiornamenti su file e oggetti S3, dall’istante temporale (per le operazioni schedulate) o dall’inserimento di messaggi su un message bus. Tipicamente le funzioni possono essere invocate anche richiamando URL dedicati o con l’utilizzo di API specifiche.
Serverless: vantaggi e svantaggi
L’approccio serverless permette di estremizzare alcuni vantaggi offerti dai container:
- allocazione delle risorse ottimale, capace di crescere linearmente con l’aumento del carico;
- separazione della funzione dai dati e dall’infrastruttura;
- ulteriore diminuzione del time to market delle nuove release, poiché si rende necessario solo il rilascio delle funzioni modificate;
- impulso alla progettazione di applicazioni basate su microservizi;
- definizione dei costi su una reale base pay per use.
Vantaggi che però non devono trarre in inganno in quanto devono essere correttamente analizzati anche in considerazione delle limitazioni che vengono introdotte in un contesto serverless:
- i provider pongono limiti per quanto riguarda le risorse ed il tempo di esecuzione che possono essere dedicati alle funzioni, quindi queste devono essere attentamente progettate e non tutti i workload si prestano a questo tipo di approccio;
- l’assenza di controllo sull’ambiente di esecuzione può complicare le operazioni di debug, di test ed ottimizzazione;
- le funzioni non sempre sono portabili tra vendor differenti con la stessa facilità con cui si sposta un container;
- ridisegnare applicazioni legacy nell’ottica di funzioni e microservizi può spesso essere un’operazione lunga ed onerosa.
Use Cases
In questa panoramica si è cercato di evidenziare quanto sia radicale la trasformazione che negli ultimi anni sta scuotendo il mondo dei servizi IT, andando a ridefinire le infrastrutture, i modelli di sviluppo e addirittura i modelli di business.
Tuttavia, quello che può sembrare un processo evolutivo in cui le nuove tecnologie sono destinate a sostituire le precedenti, è in realtà un percorso molto meno lineare: esistono e probabilmente esisteranno ancora a lungo scenari nei quali ognuna delle tre tecnologie sarà l’unica applicabile, altri in cui dovranno integrarsi ed ognuna si ritaglierà il proprio spazio.
Innanzi tutto non tutti i workload sono portabili in container: in alcuni casi sarebbe necessario riprogettare e riscrivere l’applicazione. Non è detto che questo sia sempre possibile, quindi permangono situazioni in cui le virtual machine consentono un controllo del sistema o una flessibilità che le rende indispensabili.
I container trovano il loro impiego ideale in applicazioni complesse, che richiedono un elevato controllo dell’ambiente operativo, eventualmente con lunghi tempi di elaborazione e che allo stesso tempo si prestano all’implementazione in ambiente containerizzato. Anche se l’impiego di risorse è meno efficiente rispetto ad un approccio serverless, le prestazioni sono mediamente migliori in quanto almeno il primo container è sempre attivo e non deve essere istanziato ex novo. Anche la progettazione, lo sviluppo e la gestione possono essere più semplici dal momento che la presenza di framework e standard condivisi permette l’orchestrazione tra cloud di differenti vendor con uno scaling out molto più semplice rispetto ai server virtuali.
Per contro i container presentano anche alcuni svantaggi. Le modifiche a singole funzioni richiedono la creazione ed il deploy di una nuova immagine, con dilatazione dei tempi di rilascio e possibilità di errore. La crescita del numero di istanze in risposta all’aumento del carico porta a difficoltà nel monitoraggio ed a possibili problemi prestazionali in quanto la capacità di crescita è comunque sempre limitata dalla velocità delle componenti che garantiscono la persistenza dei dati.
Un tipico esempio di impiego può essere un grande sito e-commerce costituito da numerose parti quali il listino, la gestione del magazzino e dei pagamenti, ognuna delle quali pacchettizzabile in un container per il quale il tempo di esecuzione ed i limiti di memoria non costituiscono un problema.
L’approccio serverless può essere l’ideale in un contesto di microservizi e in scenari, come l’IoT, in cui determinate funzioni devono essere invocate solo al verificarsi di precisi eventi e non essere parte di un servizio sempre attivo. Trattandosi di un modello strettamente pay per use, permette l’ottimizzazione dei costi, soprattutto nei casi in cui sia difficile procedere ad un dimensionamento a priori o prevedere il carico che si dovrà fronteggiare.
La difficoltà progettuale e l’assenza di standard, che determina in molti casi il problema del vendor lock in, costituiscono ancora una forte limitazione del campo di impiego.
In sintesi, nessuna tecnologia è migliore dell’altra in senso assoluto: ognuna risponde a specifiche esigenze. Possono convivere ed essere integrate, in base alle necessità, in un singolo progetto.
Si prestano anche alla nascita di “ibridazioni” con l’introduzione di nuovi strumenti. L’approccio più corretto non è quindi decidere a priori un percorso per lo sviluppo delle proprie applicazioni, quanto iniziare con un’attenta analisi delle caratteristiche e dei requisiti così da scegliere le tecnologie più idonee per ognuno dei componenti.