Continuous Delivery & Continuous Deployment: dal rilascio manuale a docker

da | Dic 5, 2022

Si sente parlare sempre più spesso di Devops e di quanto questa cultura possa influenzare i processi aziendali nello sviluppo di un prodotto digitale. Le definizioni continuous deployment e continuous delivery sono termini nati da questo mondo, ma qual è la differenza tra le due? E quali sono i reali impatti sul processo di sviluppo e rilascio del nostro software?

La differenza tra Continuous Deployment e Continuous Delivery

In questo articolo tratterò il processo di trasformazione del deploy di un’applicazione da manuale a completamente automatico, mostrando 2 differenti soluzioni.

L’immagine è chiara: nel primo caso il processo di rilascio viene applicato manualmente, nel secondo caso invece ogni nuova modifica al codice genera automaticamente un processo automatico di rilascio.

La differenza tra i due risulta essere l’attore che genera il trigger che fa scaturire il processo di rilascio. Quando usare il primo e quando il secondo è solo una scelta stabilita dalle necessità sia del cliente che del software che dobbiamo sviluppare.

Il continuous delivery è comodo quando non abbiamo certezza su quando il cliente voglia una nuova versione; il continuous deployment invece è più utile quando vogliamo vedere ogni nuova modifica pronta per essere usata, in modo da avere feedback continui.

Non è poi così strano utilizzare entrambi i modelli di rilascio in uno stesso progetto: possiamo avere un ambiente di test, in cui vogliamo avere costantemente ogni nuova modifica, e contemporaneamente un ambiente di produzione, che poiché deve essere utilizzabile in un intervallo di tempo definito non necessita il rilascio di ogni nuova versione.

Cosa serve per attuare un workflow

Come ogni progetto che si rispetti è necessario utilizzare un version control system in modo da tenere traccia delle nuove modifiche, in aggiunta ad una pipeline ci/cd che consente di processare il codice ed eseguire determinate azioni, dal semplice check del code coverage fino all’esecuzione degli integration tests.

Esistono molti tool che consentono tutte queste operazioni, da quelli integrati nel server di hosting del codice a quelli esterni. Nel caso che riporterò di seguito sarà usato gitlab ci/cd, che è l’ambiente di devops integrato con il servizio di gitlab.

“La scelta tra le due varia solo il tipo di trigger da impostare nel workflow del rilascio. Possiamo farlo attivare ogni volta che viene aggiornato il branch di sviluppo o solo quando vengono rilasciati nuovi tag nella repository centrale, oppure attivarli manualmente.”

Un caso reale: il rilascio manuale

Il progetto che andiamo ad esaminare è una classica Web Application, con framework Spring per la parte backend ed Angular per il frontend; il tutto è orchestrato dal tool Maven, con rilasci da effettuare ogni nuova versione per effettuare test manuali in un server di staging.

L’intero codice e tutte le configurazioni vengono mantenute in un repository Git con hosting gitlab, consentendo di sfruttare tutti i benefici di un ambiente di questo tipo: merge requests, code review, protezione dei branch di sviluppo, ticket tracker e molto altro, tra cui l’importantissima possibilità di inserire una pipeline per l’orchestrazione di alcune automazioni.

L’utilizzo di una pipeline di continuous integration è necessario per mantenere il software sviluppato sotto controllo, rendendolo solido e resiliente in caso di errori.

Il punto dolente di questo software è da sempre stato il numero di rilasci da fare su diversi server, sia interni che dal cliente, che fin dal primo rilascio venivano fatti manualmente.

Il workflow che veniva seguito in fase di rilascio risulta molto macchinoso anche con l’utilizzo di diversi script per rendere il processo semi-automatico. Scendendo nei particolari, il processo è questo: modifica della versione del software nei vari file di configurazione, creazione di un tag di riferimento della versione, esecuzione di una push del tag creato nel remoto relativo al server dove vogliamo rilasciare la versione, collegamento ssh al server, esecuzione di una kill del processo associato al nostro software, esecuzione della nuova versione.

Il risultato dell’intero processo è complessivamente rilevante in termini di tempo e di possibili errori; automatizzare tutto il processo diventa necessario per rendere l’effort di un deploy il più semplice, veloce ed estraneo da errori possibile.

Un caso reale: introduzione di una prima forma di CD

Trasformare il workflow precedentemente descritto è relativamente semplice considerando che già il progetto aveva a disposizione una pipeline per la continuous integration. Per fare questo è necessario aggiungere uno workflow in cui orchestrare l’automatismo e sfruttare script bash, compressione zip e una connessione ssh.

Automatizzare il workflow descritto nella sezione sopra è semplice, quello che è necessario fare è aggiungere un potenziale job nella pipeline che vada a eseguire al posto nostro i vari steps per il rilascio.

In questo caso bastava comprimere il progetto in uno zip, copiarlo tramite ssh nel server per poi far eseguire al server stesso un bash che procedeva con l’aggiornamento e l’esecuzione della nuova versione del software.

In termini di configurazione, i comandi da far eseguire alla pipeline sono i seguenti:

• zip -r concorsi.zip .

• scp concorsi.zip <utente>@<indirizzo_server>:<directory>

• scp scripts/release.sh <utente>@<indirizzo_server>:<home>

• ssh <utente>@<indirizzo_server> “bash release.sh”

In ordine: tramite il comando zip impacchettiamo l’intero progetto in un file compresso, facciamo una copia di questo file direttamente nella directory in cui si trova il progetto sul server, copiamo lo script usato per eseguire effettivamente il rilascio nella home del server e infine eseguiamo lo script che apporta le nuove modifiche.

Il runner su cui eseguiamo questi comandi ha necessità di avere installati i pacchetti per la connessione ssh, per la compressione zip e per l’esecuzione di script bash.

Lo script release.sh permette di eseguire tutti i passi necessari per aggiornare l’applicativo: trovare il processo che occupa la porta relativa al nostro applicativo e terminarlo, scompattare lo zip contenente la nuova versione del nostro codice ed eseguire nuovamente l’applicativo.

Niente di più difficile, solo un paio di comandi shell per rendere tutto automatizzato. Sussistono comunque dei problemi di consistenza del processo di rilascio, che si vedono molto facilmente nel caso in cui fosse necessario fare un rollback di versione.

Un caso reale: trasformazione del processo usando docker

Prima di spiegare come è stato possibile rafforzare la nostra applicazione anche in fase di rilascio e rollback, è necessario sfruttare uno strumento chiamato docker.

Docker è un virtualizzatore di risorse che permette di impacchettare un intero software per poterlo eseguire isolato all’interno di un container. Questo strumento consente di impacchettare ogni versione mantenendola in uno storage, rendendo l’architettura più flessibile ai cambiamenti e riducendo al minimo i problemi derivanti da aggiornamenti del software e rollback.

Per usare questo strumento è necessario implementare un nuovo step nella pipeline che esegue il lavoro di generazione dell’immagine, andando ad inserirla in uno storage dove sono contenute tutte le versioni del software.

Usando Maven come strumento di build automation viene facile la creazione di questo contenitore del nostro software. A questo punto, basterà dire al server in cui rilasciamo il nostro software come poter utilizzare questa risorsa. Anche in questo caso un requisito essenziale è che lato server sia installato il pacchetto docker, altrimenti non sarà possibile utilizzare questo strumento.

Modifichiamo la configurazione della pipeline definita nel paragrafo sopra con i seguenti comandi:

• ssh <user>@<indirizzo_server> “docker login <registry> –password <password_registry> –username <username_registry>”Docker Docker

• ssh <user>@<indirizzo_server> “docker stop app ; docker rm app”

• ssh <user>@<indirizzo_server> “docker run –name=app -d -p 8080:8080 <nome_app>”

In ordine: la prima esecuzione di docker serve a eseguire il login allo storage in cui sono contenute le immagini del nostro software; il secondo provvede a stoppare il container che

attualmente sta girando nel server; infine, il terzo serve a eseguire la nuova versione della nostra applicazione.

Nel caso di rollback basterà eseguire un run dell’immagine con una versione precedente senza ulteriori effort.

Quale CD scegliere

La scelta su come rilasciare la nostra applicazione, se sotto forma di delivery o di deployment, sta interamente al team del progetto.

La scelta tra le due varia solo il tipo di trigger da impostare nel workflow del rilascio. Possiamo farlo attivare ogni volta che viene aggiornato il branch di sviluppo o solo quando vengono rilasciati nuovi tag nella repository centrale, oppure attivarli manualmente.

Conclusioni

Una trasformazione di questo tipo può variare in base alle tecnologie usate, ma il risparmio in termini di risorse e di tempo risulta essere rilevante.

L’introduzione di docker non è da considerarsi gratuita in termini di conoscenze, perché l’argomento è molto ampio e non adatto a chi non è addetto ai lavori o non ha già qualche conoscenza dell’ambiente di gitops/devops.

Non deve essere tuttavia un pretesto per abbandonare da subito l’idea di modernizzare le modalità di rilascio di un’applicazione.

Sandro Pinna
Sandro Pinna
Dopo la laurea in Governo d’Impresa mi sono dedicato a molte attività, tutte di diversa tipologia, ma alla fine mi sono dedicato a quello che più mi appassionava: il digital marketing.

Potrebbe piacerti anche