Come accordare l'orchestra del cloud con i “container”
Buone pratiche per sviluppare applicazioni e servizi in modo sicuro, leggero e scalabile nel settore pubblico
di Daniele Pizzolli e Fabrizio De Rosa, Team Cloud Italia del Dipartimento per la trasformazione digitale
Ogni tecnologia che abilita il cloud ha un ruolo preciso, proprio come gli strumenti in un'orchestra di musica classica. E perché la melodia sia armoniosa e avvincente è necessaria una perfetta coordinazione tra tutti gli strumenti in scena.
Oggi parliamo dei “container”, dei veri e propri contenitori digitali che suonano il loro spartito in modo efficiente e sincronizzato, costruendo applicazioni e servizi in modo sicuro, leggero e scalabile. A dirigere la musica c'è il maestro d'orchestra, ad esempio Kubernetes, che ottimizza le risorse in sicurezza, permettendo ai container di collaborare insieme senza stonature. È necessario che l'orchestra sia ben affiatata per offrire prestazioni adeguate al funzionamento di organizzazioni complesse come le amministrazioni pubbliche italiane.
In questo articolo esploreremo alcuni dei passi fondamentali per l'utilizzo di queste tecnologie, analizzandone i benefici e le differenze principali con il modello di migrazione lift and shift, ovvero il semplice trasferimento di dati e servizi che rimangono dentro macchine virtuali.
I container e le virtual machine
I container sono una tecnologia che consente di allocare e isolare risorse, come ad esempio la memoria volatile (RAM) e la CPU, utilizzando il sistema operativo senza la necessità di coinvolgere l'hardware, diversamente da quanto avviene con le macchine virtuali.
Il fatto che l'isolamento sia ottenuto tramite il sistema operativo rende i container più veloci ad accendersi e a spegnersi, in quanto non c'è bisogno di inizializzare l'hardware (seppure emulato) e avviare tutto il sistema operativo della virtual machine (VM). Queste ultime risultano meno isolate, venendo a mancare la separazione netta a livello di CPU gestita dall'hypervisor, ovvero lo strato di software che gestisce le macchine virtuali dialogando con l'hardware.
Come in altri ambiti dell'informatica, non è tutto o bianco o nero: la distinzione fra container e VM, a seconda delle tecnologie usate, può non essere così evidente.
Da un lato ci sono container gestiti integralmente dal sistema operativo, dall'altro VM con uno strato di sistema operativo così esiguo da essere assimilabili a container.
Come si costruisce un container
La costruzione dell'immagine di un container è molto simile a quella di una VM, ma per fortuna molto più standardizzata. Se le immagini delle VM sono molto differenti a seconda della tecnologia, per i container c'è una buona standardizzazione de-facto nel formato dell'immagine (Image Format Specification), delle configurazioni (Runtime Specification) e la distribuzione degli artefatti (Distribution Specification) portati avanti dall'Open Container Initiative (OCI).
L'immagine di un container si può trovare sia preparata dal fornitore del software o da system integrator di terze parti, che costruita a partire da immagini di base, di norma condivise direttamente dai vari produttori di sistemi operativi all'interno di un processo automatizzato di Continuouos Integration/Continuous Delivery (CI/CD).
Qui è possibile notare le prime differenze sostanziali con le VM. Le buone pratiche per la gestione dei container prevedono che l'immagine sia stateless, ovvero che non porti con sé nessuna informazione specifica legata alla singola istanza (o al singolo deploy, se preferiamo la nomenclatura inglese). Le configurazioni vengono infatti applicate tramite appositi file o variabili d'ambiente al momento dell'inizializzazione e i dati persistenti sono archiviati in appositi volumi o database, o ancora meglio in sistemi di storage e database distribuiti, al contrario di quanto avviene solitamente con i monoliti nelle VM dove software, configurazioni e dati sono accorpati.
L'immagine di un container deve essere quindi costruita per auto-configurarsi alla partenza, cosa fattibile ma non banale in quanto richiede competenze DevOps.
Se la sicurezza riveste un ruolo prioritario, è meglio introdurre nel gruppo di lavoro anche competenze di tipo DevSecOps.
Un' orchestra per migliorare l'ottimizzazione delle risorse
Per eseguire e gestire un'immagine di un container si possono usare vari sistemi, dai più semplici basati su configurazioni più o meno statiche, eseguite all'interno di una VM, fino a sofisticati sistemi di orchestrazione che prevedono il monitoraggio delle risorse, il rilevamento di condizioni di criticità e la scalabilità automatica, spesso offerti come servizi SaaS dai cloud provider.
I sistemi più semplici sono facili da adottare, ma non consentono configurazioni che permettono di operare risparmi in base all'utilizzo di tali sistemi.
I cloud provider mettono a disposizione varie interfacce ed API per gestire il tutto. Il sistema di gran lunga più diffuso è certamente Kubernetes, un progetto Free e Open Source gestito dalla Cloud Native Computing Foundation (CNCF), il direttore d'orchestra dei container. Di solito ogni provider personalizza l'offerta con varie estensioni più o meno aperte o proprietarie.
La base comune di Kubernetes aiuta a ridurre il rischio di lock-in.
Le personalizzazioni dei cloud provider possono rappresentare un vantaggio gestionale, ma talvolta introducono complicazioni. Il campo dei sistemi di container orchestration è in continua evoluzione e ci sono decine di sistemi che rientrano nella definizione. Tra i più noti menzioniamo Docker Swarm e Nomad. Ci sono poi strumenti di gestione dei sistemi di container orchestration, come OpenShift o Rancher o appunto i sistemi messi a disposizione da ogni cloud provider. A volte le differenze fra i sistemi sono minime, a volte sostanziali. Anche in questo campo l'introduzione di automatismi basati su quello che comunemente viene chiamato “intelligenza artificiale” porterà ad ulteriori possibili scelte gestionali.
La complessità gestionale di introdurre un orchestratore di container è ripagata da un aumento della flessibilità, della resilienza, dell'ottimizzazione delle risorse, ottenibile dopo aver conseguito una certa esperienza.
Se tendenzialmente nelle VM che ospitano servizi in produzione l'accensione e lo spegnimento sono eventi rarissimi, di contro i container dovrebbero essere adottati per essere continuamente accesi e spenti oltre a lavorare in parallelo per ottenere quella che viene definita la scalabilità orizzontale
In questo modo il fallimento del singolo non si ripercuote sul sistema, che può anche essere aggiornato velocemente e gradualmente.
Da virtual machine a container
Bisogna partire da un'analisi dell'applicazione che si vuole migrare. Un buon approccio è sintetizzato nel paradigma dei 12 fattori per le applicazioni, o in generale nelle migliori pratiche della containerizzazione, riassunte qui. Di certo alcuni requisiti, come quello di non usare dati locali, potrebbero essere difficili da soddisfare se l'applicazione è un monolite pensato per lavorare direttamente sul filesystem: in questo caso la componente dello storage dell'applicazione andrà completamente ri-fattorizzata.
Fino a che tutte le buone pratiche non saranno soddisfatte, l'applicazione continuerà a vivere in una VM e solo quando raggiungerà la flessibilità necessaria per essere containerizzata potrà essere migrata sui container.
In questo caso sarà utile, parallelamente al processo di ri-fattorizzazione dell'applicazione, ristrutturare l'ambiente di Continuos Integration (CI) e Continuos Delivery (CD) per produrre le immagini dell'applicazione e per testarle automaticamente. Nell'ambiente di CI si possono inserire anche processi di scansione delle dipendenze per vulnerabilità note, sistemi di controllo della formattazione e della percentuale di codice coperto da test, che contribuiscono a migliorare la qualità del codice dell'applicazione e a tenere sotto controllo gli aspetti più visibili della sicurezza. È possibile trovare un esempio delle raccomandazioni della CNCF qui.
Come risparmiare: un esempio pratico
I container sono eseguiti all'interno di VM o direttamente nelle macchine fisiche o all'interno di cluster condivisi messi a disposizione e completamente gestiti dai cloud provider.
Nel caso venga utilizzato un cluster dedicato, al fine di ottenere dei risparmi legati all'uso delle risorse su scale medio/grandi, il sistema di orchestrazione tiene conto delle risorse richieste in tempo reale e rilascia le risorse non necessarie.
Ad esempio, facendo gestire il carico dei nodi ad un sistema di orchestrazione di container, 100 macchine virtuali con un utilizzo medio della CPU del 50% possono essere ridotte a 63, se teniamo come parametro di utilizzo medio della CPU l'80%.
Se viene rilevato un utilizzo medio delle risorse superiore, il meccanismo di autoscaling aggiungerà nuove VM al cluster. La soglia dell'80% è una soglia arbitraria, da valutare di caso in caso, per esempio, bilanciando i tempi di risposta dell'applicazione con la riserva di CPU che si vuole tenere.
Allo stesso modo, è possibile ottimizzare l'utilizzo della RAM e ovviamente bisogna tenere in considerazione anche il picco di richieste alla rete e le richieste verso lo storage.
Dopo aver messo in piedi il sistema e monitorato le prestazioni per un periodo ragionevole, è possibile analizzare i dati per determinare il numero ottimale di VM da mantenere stabilmente, ottenendo risparmi significativi a lungo termine. I picchi di utilizzo, invece, possono essere gestiti con risorse a consumo, riducendo i costi complessivi.
Un'analisi dei costi dovrebbe anche tenere conto della maggiore resilienza del sistema ai guasti o agli attacchi cibernetici.
Quanto costa un'ora di interruzione dei servizi? Quanto tempo ci vuole a ripristinare un sistema basto interamente su VM? Un sistema basato su container, se progettato e gestito correttamente, può garantire un'elevata continuità operativa, riducendo al minimo le interruzioni. Per una disamina più puntuale sull'analisi dei costi rimandiamo al manuale di abilitazione al cloud.
Anomalie e dove trovarle
Quando si collocano diverse applicazioni nello stesso cluster, è importante considerare attentamente la gestione della sicurezza. La gestione dei container segue le buone pratiche: monitora la sicurezza dell'applicazione anche in fase di costruzione dell'artefatto software (build) ed è integrata in un sistema di CI/CD per eseguire un rapido aggiornamento in caso emergessero problematiche, permettendo in questo modo di predisporre una risposta alle minacce in maniera molto efficace. La dinamicità offerta dai container permette anche di adottare paradigmi del tipo “service mesh” dove il traffico stesso fra i microservizi è oggetto di osservazione e analisi. Questo consente una rilevazione delle anomalie e una segregazione degli eventuali componenti malfunzionanti in maniera molto puntuale e precisa rispetto ad un'applicazione servita da un applicativo monolitico eseguito all'interno di una VM.
Cambio di paradigma: da tutto statico a tutto dinamico
La tecnologia dei container porta con sé un radicale cambio di paradigma, dove alla staticità delle VM si affianca la dinamicità dei container. Per questo non è facile pensare ad una transizione fluida da una tecnologia all'altra. Ci saranno necessariamente dei salti da effettuare, ad esempio nel migrare lo storage locale a quello distribuito, che devono essere progettati con attenzione e testati sul campo prima di arrivare in produzione. Allo stesso modo il paradigma *stateless*, dove i container non devono tenere lo stato dell'applicazione cambia l'approccio alla gestione dei dati. Le operazioni di backup e di restore dei dati, così come la gestione degli aggiornamenti nello schema del database, devono essere adattate agli strumenti e alle pratiche della gestione container.
È importante notare che non tutte le applicazioni (o parti di applicazioni) si sposano bene con il paradigma dei container.
In questo caso si deve valutare se l'applicazione possa essere sostituita da un servizio cloud nativo del provider (per esempio nel caso di database) o mantenuto all'interno di una VM.
Il gioco di squadra è (quasi) tutto
Per arrivare a questo traguardo occorre creare un gruppo di lavoro ben affiatato, aggiornato sulle buone pratiche e con gli strumenti giusti a disposizione. La competenza sui container, oggetti molto più leggeri, ma anche effimeri, rispetto alle virtual machine, non si improvvisa. Esistono però innumerevoli risorse, dai tutorial alla documentazione e al materiale dei workshop liberamente scaricabile, fino a corsi e sessioni pratiche su una particolare tecnologia. Il processo di refactoring di un'applicazione per il cloud dovrà necessariamente far riprogrammare i gruppi di lavoro e la loro organizzazione: prima i developer sviluppavano il software e i sysadmin lo installavano manualmente sulle virtual machine.
Oggi con i container tutto deve essere più fluido e integrato per garantire un funzionamento ottimale.
Se non si dispone di molte competenze interne, per alcune tecnologie o framework di programmazione, i cloud provider, o terze parti, mettono a disposizione degli strumenti di valutazione della prontezza (readiness) dell'applicazione al fine di essere migrata da VM a provider, e in alcuni casi il processo può anche essere automatizzato. Tali strumenti possono essere molto potenti, ma di contro sono molto invasivi e non si consiglia di utilizzarli nell'istanza di produzione con i dati reali. Usare il primo strumento che si trova (spesso richiede solo pochi clic) sarebbe equivalente a consegnare le proprie chiavi di casa ad uno sconosciuto che si propone di valutarla per fare una proposta di ristrutturazione. Fidarsi è bene, non fidarsi del tutto è meglio. Prima di un utilizzo effettivo è necessario valutare l'impatto sulla sicurezza che comporta questo accesso privilegiato.
Che si scelga di affidarsi a una squadra interna o al supporto di consulenti e strumenti specializzati, la migrazione ai container rappresenta un passo importante verso sistemi più resilienti e performanti.
Mappare le competenze
I container sono una tecnologia necessaria per stare al passo con i tempi. In questo approfondimento ci siamo focalizzati sui benefici in fase di gestione, ma la loro adozione permette anche di usufruire di ambienti di sviluppo più controllati, insieme a sistemi di test e staging più facili da gestire, abilitando l'adozione di sistemi e architetture orientate ai microservizi.
La tecnologia e l'offerta di servizi, in continua evoluzione, è certamente matura per essere adottata senza controindicazioni nella maggioranza dei casi.
L'effettiva gestione della VM o del cluster sul quale vengono eseguiti i container può essere delegata ad un modello SaaS (Software as a Service) specializzato, a volte chiamato CaaS (Container as a Service), dove si delega la complessa gestione dell'infrastruttura sottostante al cloud provider per focalizzarsi sullo sviluppo dell'applicazione.
La tecnologia ha raggiunto uno stato di standardizzazione tale che, anche se prendessimo decisioni errate per la migrazione a questo modello, comunque riusciremmo facilmente a cambiare i componenti che non soddisfano più le nostre esigenze o il sistema di orchestrazione senza grossi contraccolpi, assicurando così continuità operativa.
Mappare le competenze è il primo passo fondamentale per adottare i container senza troppi timori. Comincia questo percorso leggendo il manuale di abilitazione al cloud.
:::
Le immagini presenti in questo articolo sono state sviluppate con il supporto dell’Intelligenza Artificiale con l’obiettivo di rappresentare visivamente i temi trattati.
Questo blog è redatto da Developers Italia