Cloud native: approcci e vantaggi

Cloud Native

Cover 1

Applicazioni cloud native: definizione e metodologia

Le app cloud-native sono una insieme di microservizi autonomi e indipendenti con basso accoppiamento, pensate per offrire vantaggi tangibili come la possibilità di integrare velocemente i feedback degli utenti e quindi stimolando lo sviluppo continuo di una soluzione. Il Cloud-native è un approccio allo sviluppo e all’esecuzione di applicazioni che sfruttano i vantaggi del modello di delivery del cloud computing per accelerare la creazione di nuove applicazioni e riguarda il modo in cui le applicazioni vengono create e distribuite, non dove vengono sviluppate.

La Cloud Native Computing Foundation, principale promotore di questi principi, fornisce una definizione ufficiale di Cloud native:

‘’Le tecnologie Cloud native consentono alle organizzazioni di creare ed eseguire applicazioni scalabili in ambienti moderni e dinamici come cloud pubblici, privati e ibridi. Contenitori, reti di servizio, microservizi, infrastrutture immutabili e API dichiarative esemplificano questo approccio.
Queste tecniche consentono di accoppiare liberamente sistemi resilienti, gestibili e osservabili. Combinati con una robusta automazione, consentono agli ingegneri di effettuare cambiamenti ad alto impatto con frequenza e prevedibilità, con un lavoro minimo.”

Obiettivo Cloud native: distribuire le app desiderate secondo un ritmo stabilito dall’azienda

Cosa significa “cloud” nelle applicazioni cloud-native?

Un’app “cloud-native” è progettata specificamente per fornire un’esperienza di sviluppo e gestione automatizzata coerente nei cloud privati, pubblici e ibridi.  L’aspetto più critico dell’approccio cloud native è la capacità di offrire una potenza di calcolo quasi illimitata, on-demand, insieme ai moderni servizi di dati e applicazioni disponibili per gli sviluppatori. Quando le aziende costruiscono e gestiscono applicazioni in modo nativo del cloud, portano nuove idee sul mercato più velocemente e rispondono prima alle richieste dei clienti, ottimizzandone il ciclo di vita.

Per sfruttare appieno questi vantaggi, è necessario trasformare lo sviluppo applicativo.

Con sviluppo cloud-native si intende proprio questo: un approccio alla realizzazione e all’aggiornamento rapido delle app, che al contempo migliora la qualità e riduce i rischi. È un modo per creare ed eseguire app reattive, scalabili e tolleranti agli errori, ovunque si trovino: nei cloud pubblici, privati o ibridi.

 

CiCd

 

Le applicazioni native del cloud sono conformi a un framework o “contratto” progettato per massimizzare la resilienza attraverso comportamenti prevedibili; l’infrastruttura altamente automatizzata e divisa in container, utilizzata nelle piattaforme cloud, guida il modo in cui il software viene scritto e rilasciato. Un buon esempio di tale “contratto” è illustrato dai 12 principi documentati per la prima volta come app a 12 fattori.

 

Struttura cloud native: App 12 Fattori

Una metodologia ampiamente accettata per la costruzione di applicazioni basate sul cloud è l’applicazione Dodici Fattori: questa descrive un insieme di principi e pratiche che gli sviluppatori seguono per costruire applicazioni ottimizzate per i moderni ambienti cloud, con una particolare attenzione alla portabilità e all’automazione.
Mentre questa metodologia è applicabile a qualsiasi applicazione web-based, molti professionisti la considerano come una solida base per la costruzione di app cloud native, visto che i sistemi basati su questi principi possono implementare, scalare e aggiungere funzionalità rapidamente per reagire ai dinamici cambiamenti di mercato.
Questi fattori sono:

  1. Code Base
    Un unico codice di base per ogni microservizio, memorizzato nel proprio repository che tracciato con il controllo di versione, può distribuire a più ambienti (QA, Staging, Produzione).

  2. Dependancies
    Ogni microservizio isola e impacchetta le proprie dipendenze, includendo cambiamenti senza influenzare l’intero sistema.

  3. Configuration
    Le informazioni di configurazione vengono rimosse dai microservizi ed esternalizzate al di fuori del codice, attraverso uno strumento di gestione della configurazione; la stessa distribuzione può poi propagarsi attraverso gli ambienti con la corretta configurazione applicata.

  4. Backing Services
    Le risorse ausiliarie (archivi di dati, cache, mediatori di messaggi) dovrebbero essere esposte tramite un URL indirizzabile: in questo modo la risorsa viene disaccoppiata dall’applicazione, consentendone l’intercambiabilità.

  5. Build, Release, Run
    Ogni release deve far rispettare una rigida separazione tra build, release e run stage; ciascuno infatti, dovrebbe essere contrassegnato con un identificativo unico e supportare la capacità di roll back. Come vedremo, i sistemi CI/CD moderni contribuiscono a soddisfare questo principio.

  6.  Processes
    Ogni microservizio dovrebbe essere eseguito nel proprio processo, isolato da altri servizi in esecuzione. L’eventuale esternalizzazione richiede l’utilizzo di un servizio di backup come una distributed cache o data store.

  7. Port Binding
    Ogni microservizio dovrebbe essere autonomo con le sue interfacce e funzionalità esposte sulla propria porta; in questo modo si garantisce il suo isolamento da altri microservizi.

  8. Concurrency
    I servizi si estendono scale out,  su un gran numero di piccoli processi identici (copie) in contrapposizione al ridimensionamento scaling-up di una grande singola istanza sulla macchina più potente disponibile.

  9. Disposability
    Le istanze di servizio (service instances) dovrebbero essere monouso, favorendo startup veloci per aumentare le opportunità di scalabilità e arresti per lasciare il sistema in uno stato corretto. Contenitori Docker con Orchestrator soddisfano intrinsecamente questo requisito.

  10. Dev/Prod Parity
    Mantenere gli ambienti il più simile possibile durante tutto il ciclo di vita dell’applicazione, evitando pericolose scorciatoie. Qui, l’adozione di containers che pertanto promuovono lo stesso ambiente di esecuzione, contribuiscono notevolmente a questo fattore.

  11. Logging
    Trattare i log generati dai microservizi come flussi di eventi (event streams); successivamente elaborarli con l’utilizzo di un event aggregator e diffondere i relativi dati in strumenti di data-mining/ log management come Azure Monitor o Splunk e, infine, in un archivio a lungo termine.

  12. Admin Processes
    Eseguire compiti amministrativi/ gestionali come processi one-off; questi processi possono includere data clean up e generazione di analytics per un eventuale report. Gli strumenti che eseguono tali compiti dovrebbero essere richiamati dall’ambiente di produzione, ma in modo separato dall’applicazione.

Un aspetto da tenere in considerazione è  che tra non molto tempo, con l’evolversi delle tecnologie e delle pratiche cloud native, evolverà anche la loro definizione.
I sistemi cloud-native però, sono progettati per accogliere cambiamenti rapidi e su larga scala e l‘adozione di tecnologie e pratiche cloud native consente alle aziende di creare software in-house e agli imprenditori di collaborare strettamente con il reparto IT, tenendo il passo con i concorrenti e fornendo servizi migliori ai propri clienti
Per tanto è importante per le imprese avere una piattaforma per lo sviluppo e la gestione di applicazioni e servizi cloud native che automatizzi e integri i concetti di Microservices, Containers, DevOps e Continuous Integration / Continuous Delivery.

Microservizi

Con Microservizi (microservices) si intende l’utilizzo di un approccio architetturale (di piccoli servizi) allo sviluppo di un’applicazione. Attraverso l’utilizzo di questa architettura ogni servizio implementa le capacità aziendali, viene eseguito nel proprio processo e comunica tramite API HTTP o messaggistica. Ogni microservizio può essere implementato, aggiornato, ridimensionato e riavviato indipendentemente da altri servizi, tipicamente come parte di un sistema automatizzato, consentendo frequenti aggiornamenti delle applicazioni in tempo reale senza impatto sui clienti finali. 

  • Ciascuno implementa uno specifico potenziale commerciale all’interno di un più ampio contesto di dominio.
  • Ciascuno di essi è sviluppato in modo autonomo e può essere utilizzato in modo indipendente.
  • Ciascuno è contiene autonomamente la propria tecnologia di archiviazione dati (SQL, NoSQL) e piattaforma di programmazione.
  • Ciascuno viene eseguito nel proprio processo e comunica con gli altri utilizzando protocolli di comunicazione standard come HTTP/HTTPS, WebSockets, o AMQP.
  • Raggruppati insieme formano una applicazione.

Da notare come i microservizi promuovono il principio “One codebase’‘ dell’applicazione a dodici fattori, visto in precedenza.
Inoltre avendo un ciclo di vita autonomo ed indipendente, non è necessario attendere un rilascio trimestrale per distribuire una nuova funzionalità o aggiornamento ma è possibile aggiornare una piccola area di un’applicazione complessa, con meno rischi di danneggiare l’intero sistema.
Inoltre, invece di ridimensionare l’intera applicazione come una singola unità, si ridimensionano solo quei servizi che richiedono per esempio, più potenza di elaborazione o larghezza di banda della rete; questo approccio di scala a grana fine fornisce un maggiore controllo del sistema e aiuta a ridurre i costi complessivi dato che si scalano solo porzioni di tutto il sistema.

Container

I container sono tecnologie che consentono di creare pacchetti e isolare le applicazioni con il loro intero runtime environment e tutti i file necessari per l’esecuzione. Offrono sia efficienza che velocità rispetto alle macchine virtuali standard (VM), utilizzando infatti la virtualizzazione a livello di sistema operativo (OS), una singola istanza del sistema viene dinamicamente suddivisa tra uno o più container isolati, ciascuno con un unico file system scrivibile e una quota di risorse. Il basso overhead di creazione e distruzione dei contenitori, combinato con l’alta densità di imballaggio in una singola VM, rende i contenitori un veicolo di calcolo ideale per l’implementazione di microservizi individuali.
La CNCF colloca la containerizzazione dei microservizi come primo passo nella loro mappa Cloud-Native Trail – guida per le imprese che iniziano il loro viaggio cloud-native.

Creare un container per un microservizio è semplice: il codice, le sue dependencies, e runtime sono uniti in un binary chiamato container image. Queste immagini sono memorizzate in un container registry, che funge da archivio (repository) o libreria (library) per le immagini; un registry può essere situato sul computer di sviluppo, nel data center, o in una public cloud. Per esempio il cloud Azure, che noi di EDALAB utilizziamo quotidianamente, dispone di un container registry per memorizzare le immagini dei container vicino alle applicazioni cloud che le eseguiranno. Quando necessario, si trasforma l’immagine in un container in running instance. Questa istanza può essere eseguita su qualsiasi computer che ha installato una container runtime engine e si possono avere tutte le instances del servizio racchiuso nei container necessarie.
Pertanto, poiché lo sviluppo di un’applicazione si basa sulla configurazione nel suo ambiente e dipende da librerie, dependancies e file specifici, con i contenitori, questi diventano facili da emulare localmente senza tutte le spese generali di ricreare ambienti server complicati; il tutto senza influenzare l’intero sistema come indicato nel principio
“Dipendancies” dall’applicazione a dodici fattori.
I container supportano carichi di lavoro sia per Linux che per Windows e il cloud Azure, citato in precedenza, abbraccia apertamente entrambi ed è Linux, non Windows Server, il sistema operativo più popolare utilizzato.

DevOps

Una delle migliori definizioni di DevOps deriva da un suo piu fervente sostenitore, Donovan Brown:

“DevOps è l’unione di persone, processi, e prodotti per consentire la fornitura continua di valore ai nostri utenti finali.”

Si tratta di un’ampia gamma di idee che abbracciano l’intero ciclo di vita di sviluppo del software, dalla specificazione di un’applicazione fino alla consegna e al funzionamento di tale applicazione. Questo termine, derivato dalla contrazione delle parole Development (sviluppo) e Operations (processi) descrive per tanto, quegli approcci finalizzati ad accelerare i processi con cui un’idea (per esempio: nuova funzionalità del software, una richiesta di miglioramento, o una correzione di bug) va dallo sviluppo alla sua distribuzione, il tutto in un ambiente dove continua a fornire valore per l’utente.

Diventa necessario quindi una collaborazione integrata tra sviluppatori e IT con l’obiettivo di fornire costantemente software di alta qualità che rispondano alle richieste dei clienti. Questo ha il potenziale per creare una cultura e un ambiente in cui lo sviluppo, il test e il rilascio del software avvengano rapidamente, frequentemente e in modo più coerente; le applicazioni Cloud-native, basandosi su questi principi, hanno chiari vantaggi in termini di velocità di sviluppo, stabilità e scalabilità, affidando la loro gestione proprio a questi modelli DevOps.
Naturalmente, questo significa modifiche più frequenti al codice e un uso più dinamico dell’infrastruttura, dove le strategie di gestione tradizionali non riescono a tenere il passo con questo tipo di domanda, ecco perché l’adozione delle tecnologie cloud native è un viaggio di cambiamenti graduali ma fondamentali, che rappresentano un ciclo di cambiamento che può essere difficile da abbracciare.

Continuous Integration / Continuous Delivery

Continuous Integraton (CI) Continuous Delivery (CD) è un processo, spesso visualizzato come una pipeline, che comporta l’aggiunta di un alto grado di automazione e monitoraggio continuo per lo sviluppo di app cloud native, in modo che le modifiche al codice sorgente si traducono automaticamente in un nuovo contenitore in fase di costruzione, testato e distribuito in fase di sviluppo e, eventualmente, in produzione.
Caso per caso, quello a cui i termini si riferiscono dipende dalla quantità di automazione incorporata nella suddetta pipeline. Molte imprese iniziano con l’aggiunta di CI, e solo in seguito si spostano verso automating delivery e distribuzione, per esempio, durante sviluppo cloud-native apps.

Noi di EDALAB forniamo servizi di supporto e consulenza per lo sviluppo software attraverso pratiche di CI-CD, aiutando il team di sviluppatori ad ottimizzare il processo di creazione e di rilascio del codice.

Questo processo, abilitato dalle pratiche di sviluppo Agile, permette di rilasciare costantemente piccole porzioni di software alla produzione, attraverso l’automazione: la consegna continua rende il rilascio più affidabile, in modo che le aziende possano consegnare frequentemente, con meno rischi, e ottenere un feedback più veloce dagli utenti finali, come raffigurato nel seguente grafico:

 

Cicd flow
CI/CD strategy for Node.js/Express app using AWS CodeBuild/CodeDeploy/CodePipeline


Fonte:
GitHub

Ma perché le applicazioni native del cloud sono importanti?

Le applicazioni cloud native sono costruite appositamente per il modello cloud. Queste applicazioni, costruite e distribuite in una rapida cadenza da piccoli team di funzionalità dedicate a una piattaforma che offre un facile scale-out e disaccoppiamento hardware, forniscono alle organizzazioni una maggiore agilità, resilienza e portabilità in ambienti cloud.

Cloud come vantaggio competitivo.
Cloud-nativo significa passare dagli obiettivi del cloud ai risparmi sui costi IT al motore della crescita aziendale. Nell’era del software, le aziende che possono costruire e fornire rapidamente applicazioni in risposta alle esigenze dei clienti costruiranno un successo duraturo.
Consentire ai team di concentrarsi sulla resilienza.
Quando l’infrastruttura legacy fallisce, i servizi possono soffrire. In un mondo nativo del cloud, i team si concentrano specificamente sull’architettura per la resilienza. Un focus nativo del cloud aiuta gli sviluppatori e gli architetti a progettare sistemi che rimangono online indipendentemente dal singhiozzo in qualsiasi parte dell’ambiente; Inoltre, manutenzioni e aggiornamenti sono universali per tutte le versioni dell’applicazioni: gli aggiornamenti, le patch e le manutenzioni possono essere eseguiti o applicati automaticamente senza interruzione del servizio.

Ottenere una maggiore flessibilità.
I fornitori di cloud pubblici continuano a offrire servizi impressionanti a costi ragionevoli. Ma la maggior parte delle imprese non è pronta a scegliere una sola infrastruttura. Con una piattaforma che supporta un approccio cloud native, le imprese costruiscono applicazioni che girano su qualsiasi spazio cloud (pubblico o privato) senza modifiche. I team conservano la possibilità di eseguire applicazioni e servizi laddove ciò sia più sensato per il business, senza doversi bloccare nel cloud di un unico fornitore.

Allineare le operazioni con il business complessivo.
Automatizzando le operazioni IT, le aziende possono trasformarsi in un team snello e concentrato, allineato con i professionisti del settore. Eliminano il rischio di fallimenti dovuti a errori umani, poiché il personale si concentra sui miglioramenti automatizzati per sostituire le attività amministrative di routine e banali. Grazie alle patch e agli aggiornamenti automatici in tempo reale a tutti i livelli della pila, eliminano i tempi di inattività e la necessità di esperti di operazioni con competenze “di seconda mano”.

La differenza con le applicazioni tradizionali
Le applicazioni tradizionali non possono realizzare tutti i vantaggi dell’esecuzione su una piattaforma nativa del cloud a causa del modo unico in cui ciascuna di esse viene architettata o sviluppata. Questo tipo di applicazione spesso richiede più tempo per essere costruita, viene rilasciata in grandi lotti, può scalare solo gradualmente e presuppone un’elevata disponibilità di servizi dipendenti. In aggiunta, eventuali aggiornamenti, patch e manutenzioni
devono essere personalizzate per l’ambiente di lavoro specifico e spesso richiedono una configurazione ad hoc che implica un interruzione temporanea del servizio.

Spostarsi al livello Cloud-Native è tipicamente guidato dalla necessità dell’impresa di modernizzare le proprie applicazioni il più possibile al fine di migliorare drasticamente la struttura delle grandi app, come abbiamo visto, creando sottosistemi autonomi (microservizi) che possono essere implementati e scalati indipendentemente dalle altre aree di applicazione, riducendo i costi a lungo termine e aumentando l’agilità di crescita e sviluppo fornendo significativi vantaggi competitivi a basso costo.