Che cosa significa “Nativo del cloud”?

Suggerimento

Questo contenuto è un estratto dall'eBook, "Progettazione di applicazioni .NET native del cloud per Azure", disponibile nella Documentazione di .NET o come PDF scaricabile gratuitamente che può essere letto offline.

App .NET native del cloud per l'anteprima della copertina di eBook di Azure.

Smetti di fare ciò che stai facendo e chiedi ai colleghi di dare una definizione del termine "Nativo del cloud". Con ottime probabilità otterrai risposte diverse.

Iniziamo con una definizione semplice:

L'architettura e le tecnologie native del cloud sono un approccio alla progettazione, alla costruzione e ai carichi di lavoro operativi compilati nel cloud che sfruttano appieno il modello di cloud computing.

La Cloud Native Computing Foundation fornisce la definizione ufficiale:

Le tecnologie native del cloud consentono alle organizzazioni di creare ed eseguire applicazioni scalabili in ambienti moderni e dinamici, ad esempio con cloud pubblici, privati e ibridi. I contenitori, le mesh di servizi, i microservizi, l'infrastruttura non modificabile e le API dichiarative esemplificano questo approccio.

Queste tecniche consentono di avere sistemi ad accoppiamento debole che sono resilienti, gestibili e osservabili. In combinazione con un'automazione affidabile, consentono ai tecnici di apportare modifiche ad alto impatto frequenti e prevedibili con fatica minima.

Il cloud nativo punta su velocità e agilità. I sistemi aziendali si stanno evolvendo dall'abilitazione delle capacità aziendali agli strumenti della trasformazione strategica che accelerano la velocità e la crescita aziendale. È fondamentale portare immediatamente nuove idee sul mercato.

Allo stesso tempo, i sistemi aziendali sono diventati sempre più complessi e gli utenti richiedono sempre di più. Si aspettano tempi di risposta rapidi, funzionalità innovative e tempi di inattività nulli. I problemi di prestazioni, gli errori ricorrenti e l'impossibilità di spostarsi rapidamente non sono più accettabili. Gli utenti si rivolgerebbero a un concorrente. I sistemi nativi del cloud sono progettati per adottare cambiamenti rapidi e agire su larga scala e con resilienza.

Ecco alcune aziende che hanno implementato tecniche native del cloud. Considera la velocità, l'agilità e la scalabilità ottenute.

Società Esperienza
Netflix Dispone di oltre 600 servizi in produzione. Distribuisce 100 volte al giorno.
Uber Dispone di oltre 1.000 servizi in produzione. Distribuisce diverse migliaia di volte ogni settimana.
WeChat Dispone di oltre 3.000 servizi in produzione. Distribuisce 1.000 volte al giorno.

Come puoi vedere, Netflix, Uber e WeChat espongono sistemi nativi del cloud costituiti da molti servizi indipendenti. Questo stile architettonico consente loro di rispondere rapidamente alle condizioni del mercato. Aggiornano istantaneamente piccole aree di un'applicazione dinamica, complessa, senza una ridistribuzione completa. Ridimensionano singolarmente i servizi in base alle esigenze.

I pilastri del cloud nativo

La velocità e l'agilità del cloud nativo derivano da molti fattori. In primo luogo, l'infrastruttura cloud. Ma c'è di più: anche altri cinque pilastri fondamentali illustrati nella figura 1-3 rappresentano la base dei sistemi nativi del cloud.

Pilastri fondamentali nativi del cloud

Figura 1-3. Pilastri fondamentali nativi del cloud

Dedichiamo un po' di tempo a comprendere meglio il significato di ogni pilastro.

Cloud

I sistemi nativi del cloud sfruttano appieno il modello di servizio cloud.

Progettato per prosperare in un ambiente cloud dinamico virtualizzato, questi sistemi usano ampiamente l'infrastruttura di calcolo Platform as a Service (PaaS) e i servizi gestiti. Considerano l'infrastruttura sottostante come eliminabile, con provisioning in minuti e ridimensionata, scalata o distrutta su richiesta, tramite l'automazione.

Si consideri la differenza tra il modo in cui si trattano gli animali domestici e le materie prime. In un data center tradizionale, i server vengono trattati come animali domestici: un computer fisico, a cui viene dato un nome significativo e di cui qualcuno si prende cura. È possibile operare la scalabilità aggiungendo altre risorse allo stesso computer (aumento delle prestazioni). Se il server si ammala, da buon infermiere puoi farlo tornare in salute. Se il server non dovesse più essere disponibile, tutti lo noterebbero.

Il modello di servizio per le materie prime è diverso. È possibile effettuare il provisioning di ogni istanza come macchina virtuale o contenitore. Sono identici e assegnati un identificatore di sistema, ad esempio Service-01, Service-02 e così via. Si esegue il ridimensionamento creando altre istanze (aumento). Quando un'istanza diventa non disponibile, nessuno se ne accorge.

Il modello per le materie prime adotta un'infrastruttura non modificabile. I server non vengono riparati o modificati. Se si verifica un errore su di uno, o se uno richiede l'aggiornamento, questo viene eliminato definitivamente e viene eseguito il provisioning di uno nuovo, tutto tramite l'automazione.

I sistemi nativi del cloud adottano il modello di servizio per le materie prime. Continuano a essere eseguiti man mano che l'infrastruttura viene ampliata o ridotta senza considerare i computer su cui sono in esecuzione.

La piattaforma cloud di Azure supporta questo tipo di infrastruttura altamente elastica con ridimensionamento automatico, riparazione automatica e funzionalità di monitoraggio.

Progettazione moderna

Come si progetta un'app nativa del cloud? Che aspetto dovrebbe avere l'architettura? Quali principi, modelli e procedure consigliate si dovrebbe rispettare? Quali problemi di infrastruttura e operativi sarebbero importanti?

L'applicazione Twelve-Factor

Una metodologia ampiamente accettata per la costruzione di applicazioni basate sul cloud è l'applicazione Twelve-Factor. Descrive una serie di principi e procedure che gli sviluppatori seguono per costruire applicazioni ottimizzate per ambienti cloud moderni. Particolare attenzione viene prestata alla portabilità tra ambienti e all’automazione dichiarativa.

Anche se applicabile a qualsiasi applicazione basata sul Web, molti professionisti considerano Twelve-Factor una solida base per la creazione di app native del cloud. I sistemi basati su questi principi possono essere distribuiti e scalati rapidamente ed è possibile aggiungervi funzionalità per reagire rapidamente ai cambiamenti del mercato.

La tabella seguente evidenzia la metodologia Twelve-Factor:

Fattore Spiegazione
1 - Base codice Una singola base di codice per ogni microservizio, archiviata nel proprio repository. Monitorata con il controllo della versione, può essere distribuita in più ambienti (controllo di qualità, staging, produzione).
2 - Dipendenze Ogni microservizio isola le proprie dipendenze e le inserisce in pacchetti, accettando le modifiche senza che influiscano sull'intero sistema.
3 - Configurazioni Le informazioni di configurazione vengono spostate dal microservizio verso l’esterno tramite uno strumento di gestione della configurazione all'esterno del codice. La stessa distribuzione può propagarsi su più ambienti con la configurazione corretta applicata.
4 - Servizi di backup Le risorse ausiliarie (archivi dati, cache, broker di messaggi) devono essere esposte tramite un URL indirizzabile. In questo modo la risorsa viene disaccoppiata dall'applicazione, consentendo l'interscambio.
5 - Compilazione, Rilascio, Esecuzione Ogni release deve applicare una separazione rigorosa tra le fasi di compilazione, rilascio ed esecuzione. Ognuna deve essere contrassegnata con un ID univoco e deve supportare la possibilità di eseguire il rollback. I sistemi CI/CD moderni consentono di soddisfare questo principio.
6 - Processi Ogni microservizio deve essere eseguito nel proprio processo, isolato da altri servizi in esecuzione. Esternalizzano lo stato necessario a un servizio di backup, ad esempio una cache distribuita o un archivio dati.
7 - Binding porta Ogni microservizio deve essere indipendente con le relative interfacce e funzionalità esposte sulla propria porta. In questo modo viene fornito l'isolamento da altri microservizi.
8 - Concorrenza Quando occorre aumentare la capacità, aumenta il numero di servizi orizzontalmente tra più processi identici (copie) anziché aumentare le prestazioni di una singola istanza di grandi dimensioni nel computer più potente disponibile. Sviluppa l'applicazione in modo che sia scalabile simultaneamente in ambienti cloud senza problemi.
9 - Eliminabilità Le istanze del servizio devono essere eliminabili. Favorisci l'avvio rapido per aumentare le opportunità di scalabilità e gli arresti normali per lasciare il sistema in uno stato corretto. I contenitori Docker, insieme a un agente di orchestrazione, soddisfano intrinsecamente questo requisito.
10 - Dev/Prod Parity Mantieni gli ambienti nel ciclo di vita dell'applicazione il più possibile simili, evitando costosi collegamenti. In questo caso, l'adozione di contenitori può contribuire notevolmente promuovendo lo stesso ambiente di esecuzione.
11 - Registrazione Considera i log generati dai microservizi come flussi di eventi. Elaborali con un aggregatore di eventi. Propaga i dati di log agli strumenti di gestione di data mining/log, ad esempio Monitoraggio di Azure o Splunk e, infine, all'archiviazione a lungo termine.
12 - Processi di amministrazione Esegui attività di amministrazione/gestione, ad esempio la pulizia dei dati o l'analisi dei calcoli, come processi occasionali. Usa strumenti indipendenti per richiamare queste attività dall'ambiente di produzione, ma separatamente dall'applicazione.

Nel libro, Beyond the Twelve-Factor App, l'autore Kevin Hoffman dettaglia ognuno dei 12 fattori originali (scritto nel 2011). Inoltre, illustra tre fattori aggiuntivi che riflettono la progettazione moderna delle applicazioni cloud di oggi.

Nuovo fattore Spiegazione
13 - API First Tutto diventa un servizio. Supponi che il codice venga usato da un client front-end, un gateway o un altro servizio.
14 - Telemetria In una workstation si ha una visibilità approfondita sull'applicazione e sul relativo comportamento. Nel cloud, questo non è possibile. Assicurati che la progettazione includa la raccolta di dati di monitoraggio, specifici del dominio e su integrità/sistema.
15 - Autenticazione/Autorizzazione Implementa l'identità dall'inizio. Prendi in considerazione le funzionalità di controllo degli accessi in base al ruolo disponibili nei cloud pubblici.

In questo capitolo e in tutto il libro faremo riferimento a molti dei 12 e più fattori.

Azure Well-Architected Framework

La progettazione e la distribuzione di carichi di lavoro basati sul cloud possono risultare difficili, soprattutto quando si implementa un'architettura nativa del cloud. Microsoft offre procedure consigliate standard del settore per aiutare l'utente e il team a offrire soluzioni cloud affidabili.

Microsoft Well-Architected Framework offre una serie di principi guida che possono essere usati per migliorare la qualità di un carico di lavoro nativo del cloud. Il framework è costituito da cinque pilastri di eccellenza dell'architettura:

Principi Descrizione
Gestione costi Concentrati sulla generazione anticipata del valore incrementale. Applica i principi Build-Measure-Learn per accelerare il time-to-market, evitando soluzioni a elevato utilizzo di capitale. Usando una strategia con pagamento in base al consumo, investi quando aumenti il numero di istanze, anziché dover sostenere un grande investimento in anticipo.
Eccellenza operativa Automatizza l'ambiente e le operazioni per aumentare la velocità e ridurre l'errore umano. Esegui rapidamente il rollback o l'inoltro dei problemi. Implementa il monitoraggio e la diagnostica fin dall'inizio.
Efficienza prestazionale Soddisfa in modo efficiente le richieste dei carichi di lavoro. Favorisci il ridimensionamento orizzontale e progettalo nei sistemi. Esegui continuamente test di prestazioni e di carico per identificare potenziali colli di bottiglia.
Affidabilità Crea carichi di lavoro resilienti e disponibili. La resilienza consente ai carichi di lavoro di eseguire il ripristino da errori e continuare a funzionare. La disponibilità garantisce agli utenti l'accesso al carico di lavoro in qualsiasi momento. Progetta applicazioni per prevedere gli errori e ripristinarli.
Sicurezza Implementa la sicurezza nell'intero ciclo di vita dell'applicazione, dalla progettazione e dall'implementazione alla distribuzione e alle operazioni. Presta particolare attenzione alla gestione delle identità, all'accesso all'infrastruttura, alla sicurezza delle applicazioni e alla sovranità e alla crittografia dei dati.

Per iniziare, Microsoft offre una serie di valutazioni online che consentono di valutare i carichi di lavoro cloud correnti rispetto ai cinque pilastri ben strutturati.

Microservizi

I sistemi nativi del cloud adottano i microservizi, uno stile architetturale diffuso per la costruzione di applicazioni moderne.

Creato come set distribuito di servizi di piccole dimensioni indipendenti che interagiscono tramite un'infrastruttura condivisa, i microservizi condividono le caratteristiche seguenti:

  • Ognuno implementa una funzionalità aziendale specifica all'interno di un contesto di dominio più ampio.

  • Ognuno viene sviluppato in modo autonomo e può essere distribuito in modo indipendente.

  • Ognuno di essi integra la propria tecnologia di archiviazione dei dati, le dipendenze e la piattaforma di programmazione.

  • Ognuno viene eseguito nel rispettivo processo e comunica con gli altri tramite protocolli di comunicazione standard quali HTTP/HTTPS, gRPC, WebSocket o AMQP.

  • Insieme si compongono a formare un'applicazione.

La figura 1-4 mette a confronto un approccio applicativo monolitico con un approccio basato su microservizi. Nota che il monolite è costituito da un'architettura a più livelli, che viene eseguita in un singolo processo. In genere utilizza un database relazionale. L'approccio al microservizio, tuttavia, separa le funzionalità in servizi indipendenti, ognuno con propri dati, logica e stato. Ogni microservizio ospita il proprio archivio dati.

Distribuzione monolitica rispetto ai microservizi

Figura 1-4. Architettura monolitica e microservizi a confronto

Nota che i microservizi promuovono il principio dei processi dell'applicazione Twelve-Factor, descritti in precedenza nel capitolo.

Il fattore n. 6 specifica che "Ogni microservizio deve essere eseguito nel proprio processo, isolato da altri servizi in esecuzione".

Perché usare i microservizi?

I microservizi offrono agilità.

In precedenza nel capitolo è stata confrontata un'applicazione e-commerce creata come monolitica con i microservizi. Nell'esempio sono stati illustrati alcuni vantaggi evidenti:

  • Ogni microservizio ha un ciclo di vita autonomo e può evolversi in modo indipendente e distribuirsi di frequente. Non è necessario attendere una versione trimestrale per distribuire una nuova funzionalità o un aggiornamento. È possibile aggiornare una piccola area di un'applicazione in tempo reale con meno rischio di interrompere l'intero sistema. L'aggiornamento può essere eseguito senza una ridistribuzione completa dell'applicazione.

  • Ogni microservizio può essere ridimensionato in modo indipendente. Invece di ridimensionare l'intera applicazione come singola unità, si ridimensionano solo i servizi che richiedono una maggiore potenza di elaborazione per soddisfare i livelli di prestazioni desiderati e i contratti di servizio. La scalabilità con granularità fine offre un maggiore controllo del sistema e consente di ridurre i costi complessivi man mano che si ridimensionano parti del sistema, anziché tutto.

Una guida di riferimento eccellente per comprendere i microservizi è Microservizi -NET: architettura per le applicazioni .NET incluse in contenitori. Il libro approfondisce la progettazione e l'architettura dei microservizi. È una guida complementare per un'architettura di riferimento di microservizi full-stack disponibile da scaricare gratuitamente da Microsoft.

Sviluppo di microservizi

È possibile creare microservizi in qualsiasi piattaforma di sviluppo moderna.

La piattaforma Microsoft .NET è un'ottima scelta. Gratuita e open source, include molte funzionalità predefinite che semplificano lo sviluppo di microservizi. .NET è multipiattaforma. Le applicazioni possono essere compilate ed eseguite in Windows, macOS e nella maggior parte delle versioni di Linux.

.NET offre prestazioni elevate e ha ottenuto punteggi elevati rispetto a Node.js e ad altre piattaforme concorrenti. È interessante notare che TechEmpower ha condotto un ampio set di benchmark delle prestazioni in molte piattaforme e framework di applicazioni Web. .NET ha ottenuto punteggi nella top 10, ben oltre Node.js e altre piattaforme concorrenti.

.NET viene gestito da Microsoft e dalla community .NET su GitHub.

Problematiche relative ai microservizi

Sebbene i microservizi nativi del cloud distribuiti possano offrire un'enorme agilità e velocità, gli stessi presentano molte sfide:

Comunicazione

In che modo le applicazioni client front-end comunicheranno con i microservizi core in back-end? Consentirai la comunicazione diretta? In alternativa, potresti astrarre i microservizi back-end con una facciata del gateway che offre flessibilità, controllo e sicurezza?

In che modo i microservizi core back-end comunicano tra loro? Consentirai chiamate HTTP dirette che possono aumentare l'accoppiamento e influire sulle prestazioni e sull'agilità? Oppure potresti considerare la messaggistica disaccoppiata con tecnologie di accodamento e argomenti?

La comunicazione è illustrata nel capitolo Modelli di comunicazione cloud nativi.

Resilienza

Un'architettura di microservizi sposta il sistema dalla comunicazione in-process alla comunicazione di rete out-of-process. In un'architettura distribuita, cosa accade quando il servizio B non risponde a una chiamata di rete dal servizio A? In alternativa, cosa accade quando il servizio C diventa temporaneamente non disponibile e altri servizi che lo chiamano vengono bloccati?

La resilienza è illustrata nel capitolo Resilienza nativa del cloud.

Dati distribuiti

Per impostazione predefinita, ogni microservizio incapsula i propri dati, esponendo le operazioni tramite l'interfaccia pubblica. In tal caso, come esegui query sui dati o come implementi una transazione tra più servizi?

I dati distribuiti sono trattati nel capitolo Modelli di dati nativi del cloud.

Segreti

In che modo i microservizi archivieranno e gestiranno in modo sicuro i segreti e i dati di configurazione sensibili?

I segreti vengono trattati in dettaglio in Sicurezza nativa del cloud.

Gestire la complessità con Dapr

Dapr è un runtime di applicazioni open source distribuito. Grazie a un'architettura di componenti collegabili, semplifica notevolmente il plumbing dietro le applicazioni distribuite. Fornisce un'associazione dinamica che associa l'applicazione a funzionalità e componenti dell'infrastruttura predefiniti dal runtime Dapr. La figura 1-5 illustra Dapr da 20.000 piedi.

Dapr a 20.000 piediFigura 1-5. Dapr a 20.000 piedi.

Nella riga superiore della figura, nota come Dapr fornisce SDK specifici del linguaggio per le piattaforme di sviluppo più diffuse. Dapr v1 include il supporto per .NET, Go, Node.js, Python, PHP, Java e JavaScript.

Anche se gli SDK specifici del linguaggio migliorano l'esperienza di sviluppo, Dapr è indipendente dalla piattaforma. Dietro le quinte, il modello di programmazione di Dapr espone le funzionalità tramite protocolli di comunicazione HTTP/gRPC standard. Qualsiasi piattaforma di programmazione può chiamare Dapr tramite le API HTTP e gRPC native.

Le caselle blu al centro della figura rappresentano i blocchi predefiniti Dapr. Ognuno espone il codice di plumbing predefinito per una funzionalità di applicazione distribuita che l'applicazione può utilizzare.

La riga dei componenti rappresenta un ampio set di componenti dell'infrastruttura predefiniti che l'applicazione può utilizzare. Pensa ai componenti come al codice dell'infrastruttura che non è necessario scrivere.

La riga inferiore evidenzia la portabilità di Dapr e i diversi ambienti in cui può essere eseguito.

Guardando avanti, Dapr ha il potenziale di avere un impatto profondo sullo sviluppo di applicazioni native del cloud.

Contenitori

È naturale sentire citare il termine contenitore in qualsiasi conversazione nativa del cloud. Nel libro Cloud Native Patterns, l'autrice Cornelia Davis osserva che "I contenitori sono un ottimo strumento di abilitazione del software nativo del cloud". La Cloud Native Computing Foundation posiziona la containerizzazione dei microservizi come primo passaggio della Cloud-Native Trail Map, una guida per le aziende che iniziano il percorso nativo del cloud.

La creazione di contenitori di un microservizio è semplice e intuitiva. Il codice, le relative dipendenze e il runtime vengono inseriti in un pacchetto binario denominato immagine del contenitore. Le immagini vengono archiviate in un registro contenitori, che funge da repository o libreria per le immagini. Un registro può trovarsi nel computer di sviluppo, nel data center o in un cloud pubblico. Docker gestisce un registro pubblico tramite Docker Hub. Il cloud di Azure offre un registro contenitori privato per archiviare le immagini del contenitore vicino alle applicazioni cloud che le eseguiranno.

Quando un'applicazione viene avviata o ridimensionata, trasformi l'immagine del contenitore in un'istanza del contenitore in esecuzione. L'istanza viene eseguita in qualsiasi computer in cui è installato un motore di runtime del contenitore. Puoi avere il numero di istanze del servizio in contenitori di cui hai bisogno.

La figura 1-6 mostra tre microservizi diversi, ognuno nel proprio contenitore, tutti in esecuzione in un singolo host.

Più contenitori in esecuzione in un host contenitore

Figura 1-6. Più contenitori in esecuzione in un host contenitore

Nota come ogni contenitore gestisce il proprio set di dipendenze e runtime, che possono essere diversi l'uno dall'altro. In questo caso vengono visualizzate versioni diverse del microservizio di prodotto in esecuzione nello stesso host. Ogni contenitore condivide una sezione del sistema operativo host sottostante, della memoria e del processore, ma sono tutte isolate l'una dall'altra.

Nota che il modello di contenitore adotta il principio Dipendenze dell'applicazione Twelve-Factor.

Il fattore n.2 specifica che “Ogni microservizio isola le proprie dipendenze e le inserisce in pacchetti, accettando le modifiche senza che influiscano sull'intero sistema”.

I contenitori supportano carico di lavoro Linux e Windows. Il cloud di Azure adotta apertamente entrambi. È interessante notare che è Linux, non Windows Server, a essere diventato il sistema operativo più diffuso in Azure.

Anche se esistono diversi fornitori di contenitori, Docker ha acquisito la quota più ricca del mercato. L'azienda ha guidato lo spostamento del contenitore software. È diventato lo standard di fatto per la creazione di pacchetti, la distribuzione e l'esecuzione di applicazioni native del cloud.

Perché usare contenitori?

I contenitori offrono portabilità e garantiscono la coerenza tra ambienti. Incapsulando tutto in un singolo pacchetto, puoi isolare il microservizio e le relative dipendenze dall'infrastruttura sottostante.

Puoi distribuire il contenitore in qualsiasi ambiente che ospita il motore di runtime Docker. I carichi di lavoro in contenitori eliminano anche i costi di preconfigurazione di ogni ambiente con framework, librerie software e motori di runtime.

Condividendo il sistema operativo sottostante e le risorse host, un contenitore ha un footprint molto inferiore rispetto a una macchina virtuale completa. Le dimensioni ridotte aumentano la densità, o il numero di microservizi, che un determinato host può eseguire contemporaneamente.

Orchestrazione dei contenitori

Anche se gli strumenti come Docker creano immagini ed eseguono contenitori, sono necessari anche strumenti per gestirli. La gestione dei contenitori viene eseguita con un programma software speciale denominato agente di orchestrazione del contenitore. Quando si opera su larga scala con molti contenitori indipendenti in esecuzione, l'orchestrazione è essenziale.

La figura 1-7 mostra le attività di gestione che gli agenti di orchestrazione dei contenitori automatizzano.

Cosa fanno gli agenti di orchestrazione dei contenitori

Figura 1-7. Cosa fanno gli agenti di orchestrazione dei contenitori

Nella tabella seguente vengono descritte le attività di orchestrazione comuni.

Attività Spiegazione
Pianificazione Effettuare automaticamente il provisioning delle istanze del contenitore.
Affinità/anti-affinità Effettuare il provisioning di contenitori nelle vicinanze o lontani l'uno dall'altro, favorendo la disponibilità e le prestazioni.
Monitoraggio dell’integrità Rilevare e correggere automaticamente gli errori.
Failover Effettuare automaticamente il provisioning di un'istanza non riuscita in un computer integro.
Scalabilità Aggiungere o rimuovere automaticamente un'istanza del contenitore per soddisfare la domanda.
Rete Gestire una sovrimpressione di rete per la comunicazione dei contenitori.
Individuazione del servizio Abilitare i contenitori in modo che possano individuarsi tra loro.
Aggiornamenti in sequenza Coordinare gli aggiornamenti incrementali con una distribuzione senza tempi di inattività. Eseguire automaticamente il rollback delle modifiche problematiche.

Nota che gli agenti di orchestrazione dei contenitori adottano i principi di eliminabilità e concorrenza dell'applicazione Twelve-Factor.

Il fattore n. 9 specifica che "Le istanze del servizio devono essere eliminabili, favorendo le startup veloci per aumentare le opportunità di scalabilità e gli arresti normali per lasciare il sistema in uno stato corretto". I contenitori Docker insieme a un agente di orchestrazione soddisfano intrinsecamente questo requisito".

Il fattore n. 8 specifica che "I servizi vengono ridimensionati in un numero elevato di piccoli processi identici (copie) anziché aumentare le prestazioni di una singola istanza di grandi dimensioni nel computer più potente disponibile".

Sebbene esistano diversi agenti di orchestrazione dei contenitori, Kubernetes è diventato lo standard di fatto per il mondo nativo del cloud. Si tratta di una piattaforma open source portatile ed estendibile per la gestione dei carichi di lavoro in contenitori.

Puoi ospitare la tua istanza di Kubernetes, ma diventeresti responsabile del provisioning e della gestione delle relative risorse, che possono essere complesse. Il cloud di Azure offre Kubernetes come servizio gestito. Sia il servizio Azure Kubernetes (AKS) che Azure Red Hat OpenShift (ARO) consentono di sfruttare appieno le funzionalità e la potenza di Kubernetes come servizio gestito, senza dover installarla e gestirla.

L'orchestrazione dei contenitori è descritta in dettaglio in Ridimensionamento di applicazioni native del cloud.

Servizi di supporto

I sistemi nativi del cloud dipendono da molte risorse ausiliarie diverse, ad esempio archivi dati, broker di messaggi, monitoraggio e servizi di gestione delle identità. Questi servizi sono noti come servizi di supporto.

La figura 1-8 mostra molti servizi di supporto comuni usati dai sistemi nativi del cloud.

Servizi di supporto comuni

Figura 1-8. Servizi di supporto comuni

Puoi ospitare i tuoi nservizi di backup, ma diventeresti responsabile delle licenze, del provisioning e della gestione di tali risorse.

I provider di servizi cloud offrono un'ampia gamma di servizi di supporto gestiti. Anziché possedere il servizio, puoi semplicemente utilizzarlo. Il provider di servizi cloud gestisce la risorsa su larga scala ed è responsabile di prestazioni, sicurezza e manutenzione. Il monitoraggio, la ridondanza e la disponibilità sono integrati nel servizio. I provider garantiscono prestazioni a livello di servizio e supportano completamente i servizi gestiti: se apri un ticket, loro risolvono il problema.

I sistemi nativi del cloud favoriscono i servizi di supporto gestiti dai fornitori di servizi cloud. Il risparmio in termini di tempo e di lavoro può essere significativo. Il rischio operativo di ospitare il proprio sistema e riscontrare problemi può diventare costoso rapidamente.

Una procedura consigliata consiste nel considerare un servizio di supporto come risorsa collegata, associato dinamicamente a un microservizio con informazioni di configurazione (URL e credenziali) archiviate in una configurazione esterna. Queste linee guida sono specificate nell'applicazione Twelve-Factor, descritta in precedenza nel capitolo.

Il fattore n. 4 specifica che i servizi di supporto "devono essere esposti tramite un URL indirizzabile. In questo modo la risorsa viene disaccoppiata dall'applicazione, consentendo l'interscambio".

Il fattore n. 3 specifica che "Le informazioni di configurazione vengono spostate dal microservizio verso l’esterno tramite uno strumento di gestione della configurazione all'esterno del codice".

Con questo modello, un servizio di supporto può essere collegato e scollegato senza modifiche al codice. Puoi aumentare il livello di un microservizio dal controllo di qualità a un ambiente di gestione temporanea. Puoi aggiornare la configurazione del microservizio in modo che punti ai servizi di supporto nella gestione temporanea e inserire le impostazioni nel contenitore tramite una variabile di ambiente.

I fornitori di servizi cloud forniscono API per comunicare con i servizi di supporto proprietari. Queste librerie incapsulano il plumbing proprietario e la complessità. Tuttavia, la comunicazione diretta con queste API associa strettamente il codice a tale servizio di supporto specifico. È una pratica ampiamente accettata per isolare i dettagli di implementazione dell'API del fornitore. Introduci un livello intermedio o un'API intermedia, esponendo operazioni generiche al codice del servizio ed eseguendone il wrapping al suo interno. Questo accoppiamento libero consente di scambiare un servizio di backup per un altro o spostare il codice in un ambiente cloud diverso senza dover apportare modifiche al codice del servizio mainline. Dapr, illustrato in precedenza, segue questo modello con il set di blocchi predefiniti preintegrati.

Come pensiero finale, i servizi di supporto promuovono anche il principio di Senza stato dell'applicazione Twelve-Factor, discusso in precedenza nel capitolo.

Il fattore n. 6 specifica che “Ogni microservizio deve essere eseguito nel proprio processo, isolato da altri servizi in esecuzione. Esternalizza lo stato necessario a un servizio di supporto, ad esempio una cache distribuita o un archivio dati.”

I servizi di backup sono descritti in Modelli di dati nativi del cloud e Modelli di comunicazione nativi del cloud.

Automazione

Come si è visto, i sistemi nativi del cloud adottano microservizi, contenitori e progettazione moderna del sistema per ottenere velocità e agilità. Tuttavia, questa è solo parte della storia. Come si effettua il provisioning degli ambienti cloud su cui vengono eseguiti questi sistemi? Come si distribuiscono rapidamente le funzionalità e gli aggiornamenti delle app? Come si completa il quadro?

Immetti la pratica ampiamente accettata dell'infrastruttura come codice, o IaC.

Con IaC, è possibile automatizzare il provisioning di piattaforme e la distribuzione di applicazioni. Sostanzialmente, si applicano procedure di progettazione software, ad esempio test e controllo delle versioni alle procedure DevOps. L'infrastruttura e le distribuzioni sono automatizzate, coerenti e ripetibili.

Automazione dell'infrastruttura

Strumenti come Azure Resource Manager, Azure Bicep, Terraform da HashiCorp e l'interfaccia della riga di comando di Azure consentono di creare uno script dichiarativo dell'infrastruttura cloud necessaria. I nomi delle risorse, le posizioni, le capacità e i segreti sono parametrizzati e dinamici. Lo script viene sottoposto a controllo delle versioni e archiviato nel controllo del codice sorgente come artefatto del progetto. Puoi richiamare lo script per effettuare il provisioning di un'infrastruttura coerente e ripetibile in ambienti di sistema, ad esempio controllo di qualità, staging e produzione.

Dietro le quinte, IaC è idempotente, vale a dire che è possibile eseguire lo stesso script ripetutamente, senza effetti collaterali. Se il team deve apportare una modifica, modifica e riesegue lo script. Sono interessate solo le risorse aggiornate.

Nell'articolo Che cos'è l'infrastruttura come codice, l’autore Sam Guckheimer spiega che "I team che implementano IaC può offrire ambienti stabili e su larga scala. Evitano la configurazione manuale degli ambienti e applicano la coerenza rappresentando lo stato desiderato degli ambienti tramite codice. Le distribuzioni dell'infrastruttura con IaC sono ripetibili ed evitano i problemi di runtime causati dalla deriva delle configurazioni o da dipendenze mancanti. I team DevOps possono collaborare con un set unificato di procedure e strumenti per distribuire applicazioni e l'infrastruttura di supporto rapidamente, in modo affidabile e su larga scala".

Automatizzazione delle distribuzioni

L'applicazione Twelve-Factor, illustrata in precedenza, richiede passaggi separati quando si trasforma il codice completato in un'applicazione in esecuzione.

Il fattore n. 5 specifica che "Ogni versione deve applicare una separazione rigorosa tra le fasi di compilazione, rilascio ed esecuzione. Ognuna deve essere contrassegnata con un ID univoco e deve supportare la possibilità di eseguire il rollback.”

I sistemi CI/CD moderni consentono di soddisfare questo principio. Forniscono passaggi di compilazione e consegna separati che consentono di garantire codice coerente e di qualità facilmente disponibile per gli utenti.

La figura 1-9 mostra la separazione nel processo di distribuzione.

Passaggi delle distribuzioni nella pipeline CI/CD

Figura 1-9. Passaggi di distribuzione in una pipeline CI/CD

Nella figura precedente, presta particolare attenzione alla separazione delle attività:

  1. Lo sviluppatore costruisce una funzionalità nell'ambiente di sviluppo, iterando il cosiddetto "ciclo interno" di codice, esecuzione e debug.
  2. Al termine, viene eseguito il push del codice in un repository di codice, ad esempio GitHub, Azure DevOps o BitBucket.
  3. Il push attiva una fase di compilazione che trasforma il codice in un artefatto binario. Il lavoro viene implementato con una pipeline di integrazione continua (CI). Compila, testa e crea pacchetti dell'applicazione in maniera automatica.
  4. La fase di rilascio preleva l'artefatto binario, applica informazioni di configurazione dell'applicazione e dell'ambiente esterne e produce una versione non modificabile. La versione viene distribuita in un ambiente specificato. Il lavoro viene implementato con una pipeline di recapito continuo (CD). Ogni versione deve essere identificabile. Si può dire: "Questa distribuzione esegue la versione 2.1.1 dell'applicazione".
  5. Infine, la funzionalità rilasciata viene eseguita nell'ambiente di esecuzione di destinazione. Le versioni non sono modificabili, ovvero qualsiasi modifica deve creare una nuova versione.

Con l'applicazione di queste procedure, le organizzazioni hanno radicalmente evoluto il modo di distribuire i software. Molte sono passate da versioni trimestrali ad aggiornamenti on demand. L'obiettivo è rilevare i problemi all'inizio del ciclo di sviluppo, quando sono meno costosi da risolvere. Più lunga è la durata tra le integrazioni, più i problemi diventano costosi da risolvere. Con coerenza nel processo di integrazione, i team possono eseguire il commit delle modifiche al codice più frequentemente, con conseguente miglioramento della collaborazione e della qualità del software.

L'infrastruttura come codice e l’automazione della distribuzione, insieme a GitHub e Azure DevOps, è descritta in dettaglio in DevOps.