Introduzione
Per sfruttare al meglio le opportunità di mercato, le esigenze di business richiedono all’IT una capacità di rilascio del software sempre più frequente. Questa necessità mette a dura prova la capacità di ogni azienda di provisionare, configurare, scalare orizzontalmente i componenti applicativi e infrastrutturali che compongono un prodotto software complesso. Ciò diventa ancora più evidente nelle aziende che hanno adottato metodologie di sviluppo Agile in quanto i team di sviluppo richiedono frequenze ancora maggiori di rilascio e test del loro nuovo codice.
La pratica Infrastructure as Code (IaC) si pone l’obiettivo di rispondere a queste esigenze per la gestione dell’infrastruttura. IaC è un approccio per la costruzione e il mantenimento automatizzato e dinamico di infrastrutture software.
Gli aspetti fondamentali di IaC
L’approccio basato su Iac
- definisce l’infrastruttura software tramite linguaggi di alto livello o dichiarativi;
- basa il ciclo di vita degli elementi infrastrutturali su un sistema di versionamento, pratiche di integrazione, testing e rilascio continuo;
- automatizza il provisioning di intere infrastrutture.
Infrastructure as Code realizza i principi di tracciabilità e shif-left che, per la gestione dell’infrastruttura software, si declinano nella capacità di standardizzare tutti gli ambienti della pipeline di deploy e di riprodurre in modo deterministico ambienti sostanzialmente analoghi a quelli di produzione (production-like) anticipando il prima possibile eventuali errori dipendenti dall’ambiente di produzione.
Molti test ed errori di deploy si verificano infatti in ambiente di produzione proprio a causa di differenze applicative e infrastrutturali con gli ambienti di test e sviluppo. Standardizzare la definizione degli ambienti, porli su un sistema di controllo delle versioni, e automatizzare configurazioni e rilasci, utilizzando codice sorgente versionato, diminuisce il rischio di incidenti di questo tipo.
Ritrovarsi con gli ambienti della pipeline disallineati è una conseguenza di cattive abitudini che portano ad un processo di rilascio inefficiente.
Dal caos ad IaC
Effettuare configurazioni degli ambienti con un mix di istruzioni da linea di comando, comandi da GUI e modifica di file di testo e proprietà porta a uno scenario critico in cui si perde la storia delle modifiche applicate e in cui ambienti pensati per la stessa filiera di deployment producono comportamenti diversi sulle applicazioni. Oltretutto diventa anche difficile riprodurre le condizioni che hanno creato il problema…
Alla base di uno scenario di questo tipo che porta a una infrastruttura ingestibile, e di conseguenza a una capacità di rilascio insufficiente, c’è un processo di gestione dell’infrastruttura che prevede task di routine ed esecuzione di script svolti manualmente e puntualmente sui singoli ambienti. La documentazione prodotta viene fatta in maniera eterogenea, “a piacere”; e anche quando viene condivisa in repository centrali, ci si imbatte in documenti che, a distanza di tempo, risultano di difficile comprensione persino per chi li ha scritti… Il rischio di ripetere passi su passi che introducono ulteriori errori e differenze tra gli ambienti è elevatissimo. Tradotto in un linguaggio meno enterprise e più da “smanettoni”: chi non ha avuto mai problemi seguendo il classico tutorial, fatto da altri, per l’installazione di un ambiente?
Uscire dal caos
IaC viene in aiuto a queste problematiche grazie a linguaggi dichiarativi con i quali è possibile trattare le configurazioni come codice sorgente, condividerle su un Configuration Registry e distribuirle consistentemente e in modo automatizzato applicandole ad ambienti diversi. Piuttosto che documentare una procedura, quest’ultima viene implementata e distribuita.
I principi a cui attenersi per applicare correttamente il paradigma IaC sono: riproducibilità, consistenza, ripetibilità, eleminabilità e service continuity, self-testing systems, self-documenting systems, versioning generale. Vediamoli di seguito nel dettaglio.
Riproducibilità
Ogni elemento dell’infrastruttura deve essere ricostruibile in maniera affidabile senza prendere nessuna decisione significativa sul come ricostruire un elemento. Decisioni come software e versioni da installare, scelta di hostname etc. devono essere prese dagli script e tool di provisioning. IaC abilita la capacità di costruire e ri-costruire ogni parte dell’infrastruttura senza sforzo.
Consistenza
De elementi infrastrutturali che forniscono un servizio simile dovranno essere identici eccetto per piccole differenze obbligatorie, come i loro indirizzi IP.
Ripetibilità
Ogni azione apportata all’infrastruttura deve essere ripetibile.
Eliminabilità e service continuity
Ogni elemento infrastrutturale può essere distrutto in ogni momento senza alcuna notifica. Se progettiamo i nostri servizi in modo che un elemento infrastrutturale possa sparire senza drammi, saremo liberi di distruggere o rimpiazzare liberamente elementi quando avremo bisogno di aggiornamenti. La possibilità che i server possano scomparire è una feature non un bug. D’altra parte l’infrastruttura deve essere in grado di eseguire una nuova istanza di un elemento infrastrutturale qualora questo sparisca, ad esempio a causa di un fallimento. Per avere un servizio continuamente disponibile sopra dei componenti infrastrutturali “usa e getta” dobbiamo identificare quali cose sono assolutamente necessarie per il servizio e assicurarci di averle disaccoppiate dall’infrastruttura. Approcci utili ad ottenere un design applicativo di questo tipo si possono trovare nella metodologia twelve-factory [4] e, per grandi sistemi enteprise, nell’architettura a microservizi.
Self-testing systems
L’approccio del Continuous Testing e Integration è particolarmente efficace anche per l’automatizzazione dell’infrastruttura e, probabilmente, ancora più necessario, in quanto un piccolo cambiamento può potenzialmente provocare un danno molto più critico che nel campo applicativo. Questa base inoltre permette di superare la paura di affidarsi alle automazioni.
Self-documenting systems
La definizione dell’infrastuttura avviene tramite linguaggi dichiarativi. Il codice è la documentazione.
Versioning generale
Le configurazioni sono definite tramite codice che andrà versionato in modo da ottenere:
- tracciabilità: si è sempre a conoscenza di quale configurazione è stata applicata ad un ambiente;
- rollback: quando un cambiamento rompe qualcosa, è possibile ristabilire lo stato precedente;
- correlazione: quando script, configurazioni, artefatti vengono versionati e correlati da tags o numeri di versioni può tornare utile per sistemare problemi più complessi;
- visibilità: ognuno può vedere i cambiamenti, questo incrementa la consapevolezza del team;
- azionabilità: i VCS supportano azioni di trigger automatici quando un commit cambia; questa è la chiave per abilitare la catena di Continuous Integration e Continuous Delivery.
La differenza si vede
La figura 1 mostra il passaggio da uno scenario critico con interventi puntuali e manuali sugli ambienti e con una documentazione eterogenea a uno che adotta IaC, in cui le configurazioni sono versionate su git sotto forma di codice e distribuite uniformemente e in modo automatico tramite tool di gestione della configurazione.
Collaborazione tra Dev e Ops
Con IaC i team di Ops acquisiscono una visione sul ciclo di vita degli artefatti simile a quella solitamente adottata dal team Dev. Ciò permette di costruire un linguaggio comune tra i due team, di favorire la collaborazione e lo scambio di competenze.
La tendenza suggerita da DevOps è infatti quella di abbattere una visione di separazione netta tra i due team a favore di una visione che considera un unico team composto da più ingegneri del software, ognuno con una parte di competenze specifiche e una parte di competenze comuni, che collaborano a stretto contatto per raggiungere un obiettivo condiviso: il rilascio del software.
La figura 2 mostra i risultati di interviste di uno studio Forrester [2] a team di Dev e Ops che hanno adottato IaC. La collaborazione tra i team è il beneficio maggiormente percepito.
Un esempio di soluzione tecnica
Facciamo riferimento alla soluzione proposta da Chef per illustrare una possibile soluzione tecnica. Chef [3] è un tool per l’automatizzazione del processo di installazione e configurazione di componenti software che, oltre a permetterci di applicare i principi IaC di tracciabilità, riproducibilità e testabilità dell’infrastruttura software, fornisce un’architettura e dei tool di supporto per la realizzazione di un modello dell’Infrastruttura IT a gestione centralizzata e automatizzata.
La figura 3 mostra quanto detto. Gli ambienti (nodi) saranno registrati, tramite un agente chef-client installato in ogni nodo, a un server centrale chef-sever. Tramite un’interfaccia di amministrazione si accede allo chef-server per eseguire un provisioning: ad esempio per distribuire un fix di configurazione in tutti i nodi della pipeline di deployment. In particolare il fix di configurazione sarà un pezzo di codice sorgente: nel caso di Chef sarà in linguaggio Ruby, versionato nel sistema di versionamento. Chef mette a disposizione anche un’interfaccia centralizzata per monitorare lo stato di tutti i nodi.
Come introdurre la IaC in un contesto Enterprise “classico”?
Facendo riferimento a realtà IT molto strutturate, bisogna avere una roadmap ben definita in modo da introdurre i concetti IaC in maniera modulare e facendo attenzione a non perdere l’obiettivo finale di questo approccio.
Una prima valutazione del processo corrente di provisioning delle infrastrutture è essenziale per trovare i punti di attrito tra la parte Operations e la parte Development.
Bisogna per prima cosa identificare gli obiettivi comuni, quali sono i linguaggi dichiarativi di riferimento insieme ai tool che li governano in modo da implementare IaC smussando i vari gap tra i due dipartimenti.
Prevedere il giusto tempo e budget per la formazione in termini di IaC è un aspetto fondamentale. La formazione corretta dei team in ottica DevOps verso IaC, evita lo scetticismo e quel senso di “perdita di tempo” iniziale di un processo imposto dall’alto.
Il provisioning automatico governato da script autocontenuti e versionati funziona solo se sia gli sviluppatori che i sistemisti ne avvertono le potenzialità e sono confidenti di avere le giuste competenze senza aver paura di scontrarsi con la loro controparte nel team “antagonista”.
Il processo di adozione di IaC non è indolore, in quanto sfida sia la parte di sviluppo sia la parte di operation: per la prima, i componenti dei vari team, dovranno accrescere le loro competenze in ambito infrastrutturale, avere più consapevolezza di dove e come gira il loro codice; per la seconda, i responsabili di esercibilità del software dovranno imparare a governare l’infrastruttura, applicando i principi del rilascio del software, avvicinandosi a un linguaggio di programmazione che gli permette di tenere sotto controllo tutti i vari moduli infrastrutturali in maniera ripetibile e automatizzata.
I benefici saranno tangibili per entrambi sia in termini di qualità del software che di governo dell’infrastruttura che lo ospita.
Per iniziare il percorso IaC è meglio cominciare dal basso con delle attività “piccole”, facendo il provisioning di componenti più vicini allo sviluppo che alla produzione, in modo da continuare ad ingrandire il perimetro di IaC man mano che i team diventano confidenti con questa nuova metodologia di sviluppo.
Conclusioni
L’insieme di principi, pratiche e tool che risiedono sotto il paradigma IaC permettono la realizzazione di una gestione dell’ infrastruttura robusta, automatizzata, reattiva alle richieste di business e alle esigenze del team di sviluppo. L’adozione di un unico processo di sviluppo valido sia per la parte applicativa che per quella infrastrutturale crea una visione e un linguaggio comune tra i team di Dev e Ops con l’implicito effetto “collaterale” di avere un’organizzazione più collaborativa e proattiva.
Tutte queste considerazioni fanno pensare che, tra le pratiche DevOps, IaC sia quella più incisiva, quella di cui sempre meno organizzazioni IT possono fare a meno.