No results found
di Yefry Figueroa
Ansible è uno strumento per la gestione delle configurazioni e di orchestrazione, scritto in python, che permette di automatizzare tutti i processi di una infrastruttura IT.
Questo corso è rivolto principalmente a chi non conosce tale tecnologia o a chi ne ha sentito parlare e vuole approfondire l’argomento.
Ansible è un software free che consente di automatizzare le procedure di configurazione e gestione sui sistemi unix e derivati. Il nome "Ansible" deriva da un oggetto della fantascienza che consente di comunicare più velocemente della luce. Si tratta di qualcosa di molto potente ma al contempo semplice, che si impara in poco tempo.

Come per la maggior parte dei software di configurazione, Ansible sfrutta due tipi di server:
La macchina controllore è quella che orchestra il tutto eseguendo determinati comandi sui nodi, cui si connette una chiave di accesso SSH.
Ansible è di semplice utilizzo perché rappresenta una forma di automazione leggibile da un umano, non richiede particolari competenze di codice, i task vengono eseguiti in ordine e quindi consente di ottenere rapidamente produttività dal proprio sistema.
È potente, perché consente il deployment delle applicazioni, la gestione della configurazione e l’orchestrazione del workflow.
Diversamente dai più conosciuti software “concorrenti” (Chef, Puppet e CFEngine, per esempio) Ansible utilizza un'architettura agentless, ossia che non richiede agenti software, ossia programmi tipicamente servizi e demoni, che girano su un computer con l’obiettivo di raccogliere informazioni e inviarle attraverso la rete a un sistema centrale o pubblicarli nuovamente in formato standard come l’SNMP. Quindi l’approccio agentless risparmia l’installazione di agenti software su tutti i computer che necessitano dei dati, comportando costi proporzionali al numero di elementi coinvolti.
L’approccio agentless prevede che i dati siano raccolti senza agenti software e il principale vantaggio di ciò è che non diviene necessario preoccuparsi di installare, aggiornare e manutenere tool software specifici; altro vantaggio è la rapidità di sviluppo e conseguente riduzione dei costi. Questo riduce di molto l'ipotetico traffico di rete necessario per utilizzare questo programma.
Ansible utilizza OpenSSH e WinRM, non richiede agenti che possano esporre al rischio di exploit o alle problematiche di aggiornamento. Ansible non richiede agenti da installare sui nodi ma è richiesto solo il server OpenSSH.
Le specifiche di configurazione in Ansible sono scritte in documenti YAML che vengono chiamati Playbook; YAML è un linguaggio molto elementare basato principalmente sull'indentazione. Le specifiche di configurazione operano attraverso dei task o gestori di eventi che spiegheremo più avanti. Ad esempio, un task può essere quello di aggiornare file di configurazione di un database server e un gestore di eventi chiuderebbe il database al termine dell’esecuzione del task. Questo concetto sarà chiarito più avanti.
Ansible è affidabile: se scritto con la dovuta accuratezza un Playbook può essere in grado di gestire anche situazioni inaspettate che potrebbero verificarsi sui nodi.
Ansible Core è la versione open-source, ma di Ansible esiste una versione enterprise chiamata Ansible Tower: è un enterprise framework che tra le altre caratteristiche mette a disposizione un pannello di controllo per gestire i nodi, le automazioni (attraverso interfaccia utente e RESTfulAPI) e le API. Ma Ansible Tower è a pagamento.
Ansible è semplice e il linguaggio nel quale configuriamo i playbook è molto intuitivo. I task sono eseguibili in ordine, ossia in sequenza. Con Ansible si può fare un deploy in modo molto veloce e il deploy può essere effettuato in ogni momento e così la configurazione di centinaia di nodi. Consente di gestire l’intero ciclo di vita delle applicazioni.
Un altro aspetto positivo di Ansible è che si tratta di un pacchetto completo (vedere immagine seguente) ossia contiene tool per il deployment delle applicazioni ai nodi, il gestore delle configurazioni dei server, oltre che per il provisioning.

Abbiamo innanzitutto configuration management, dove possiamo configurare server remoti come installazione di pacchetti, update sistemi, specifica chiavi e servizi;
Sicurezza e compliance, mantenere server remoti sempre aggiornati e risolvere vulnerabilità in modo centralizzato
Application deployment, ossia pushare codice e deployment su server remoti, su uno o più server.
Orchestration, permette gestione e organizzazione nodi nella nostra rete.
Continuos delivery: i playbook permettono delivery delle nostre applicazioni.
Provisioning: Ansible dispone per la maggior parte dei cloud provider dei moduli per fare il provisioning di nuovi server e nuove istanze. Per esempio per Amazon ha decine di moduli che permettono di integrarsi con esso e fare deployment automatico molto facilmente.
Installare Ansible è molto semplice, anche se dipende dalla distribuzione del sistema operativo di cui si dispone sul computer utilizzato. La figura seguente mostra una lista di comandi da impartire per l’installazione da CLI (interfaccia a riga di comando).

Per l’installazione è necessario avere sul computer i necessari pacchetti di installazione, scaricabili dal web e in particolare quello di Ansible, ottenibile da www.ansible.com.
Bene, vediamo adesso come funziona Ansible: il computer sul quale viene installato e dal quale operiamo si chiama Ansible Management Node e in pratica su di esso l’utente crea un playbook, che è un file di YAML; ricordiamo che i task vengono eseguiti in sequenza. Possiamo creare dei moduli o dei plugin per estendere le funzionalità di Ansible. L’interfaccia utente di Ansible è mostrata qui di seguito.

I playbook e i moduli verranno eseguiti sui nodi riepilogati nell’Inventory (l’inventario che raccoglie gli estremi di tutti i nodi su cui opereremo); sostanzialmente, quando creiamo un playbook facciamo uso sempre di moduli e talvolta di plugin, quindi richiamando i nodi dall’Inventory (nell’interfaccia utente di Ansible) verrà eseguito il deployment su ciascuno di essi. I nodi destinatari del deployment vengono chiamati “nodi target” (vedere figura seguente).

I moduli sono pezzi di codice che vengono trasferiti ai nodi e lì eseguiti per soddisfare la dichiarazione di un determinato task e possono essere usati da CLI o automatizzati in un task all’interno di un playbook.
Sul sito www.ansible.com trovate una completa documentazione on-line che descrive tutti i moduli disponibili, che in Ansible sono divisi per categorie: moduli per Windows, per la rete, per il web, di sistema, di comando e di utilità. Di seguito è riportata la lista delle categorie:
La documentazione dei moduli è fondamentale perché descrive per ciascun modulo i parametri e la configurazione per assicurare il corretto funzionamento.
Alcuni moduli sono quelli visualizzati qui di seguito e riguardano la categoria Network.
Se tra le categorie di moduli di Ansible non trovate quella che serve alla vostra applicazione, non è un problema: potete costruire moduli specifici partendo dalla categoria Command, che eseguono un comando e sono di quattro tipi:
- Command; prende un comando e lo esegue sull’host (è il più sicuro e dall’esito prevedibile);

- Shell; esegue il comando da una shell come /bin o /sh così che si possa utilizzare pipe, tuttavia richiede cautela;
- Script; esegue uno script locale sul nodo remoto prima di trasferirlo ad esso;
- Raw; esegue un comando senza passare dai moduli di Ansible (in sostanza non passa dall’ambiente Ansible).
A differenza degli altri moduli Ansible, i Run Commands non hanno alcun concetto di stato desiderato, quindi devono essere utilizzati come soluzione estrema.
INVENTORY: è una collezione di nodi e gruppi ai quali Ansible può connettersi e gestire.
TASK: sono le istruzioni che Ansible esegue, in ordine, sui nodi target.
HANDLER: sono istruzioni che vanno eseguite come conseguenza di una determinata azione.
PLAY E PLAYBOOK: i Play sono una serie di task ordinati da eseguire sui nodi selezionati dall’inventario. Un Playbook è un file che contiene uno o più play.
ROLE: rappresentano una serie di contenuti strettamente correlati che permetto di gestire meglio e mantenere una serie di playbook.
L’inventario di Ansible è una collezione di nodi (host) con determinate caratteristiche e gruppi di nodi che possono essere connessi e gestiti tutti insieme, singolarmente o per gruppo. Abbiamo quindi una struttura con:
- Host (nodi);
- Gruppi;
- Dati specifici Inventory (variabili);
- Sorgenti statiche o dinamiche.
Un esempio di Inventory è quello riportato qui di seguito e riguarda due server e un database:
[web]
webserver1.example.com
webserver2.example.com
[db]
dbserver1.example.com
Qui abbiamo un gruppo [web] comprendente due nodi (webserver1.example.com e webserver2.example.com) e un gruppo [db] con un solo nodo. I nodi sono quelli su cui andremo a distribuire il codice.
In Ansible troviamo gli ad-hoc commands, che sono comandi eseguibili liberamente senza che sia necessario salvarli e ripeterli in un secondo momento. I comandi ad hoc possono essere digitati senza vincoli e al bisogno, quindi senza collocare le rispettive operazioni in un playbook.
Un esempio è riportato qui di seguito, dove sono riportati tre comandi.

Il comando $ ansible all –m ping ordina l’esecuzione di Ansible su tutti i nodi presenti nell’Inventory ordinando l’esecuzione del modulo ping, cui i nodi risponderanno (almeno quelli “alive” cioè attivi).
Vediamo il secondo dei comandi della figura, $ ansible all –m command -a “uptime” che esegue sui nodi del gruppo [web] il modulo comando con l’attributo uptime, allo scopo di effettuare l’uptime di tutti i server del gruppo stesso.
Passiamo adesso alla Sidebar dell’interfaccia di Ansible e ai Facts: i facts (anche noti come Discovered Facts) sono porzioni di informazioni fornite dagli host (i nodi…) che possono essere memorizzate come variabili per un successivo utilizzo nei playbook. Sono utili in molti casi, principalmente, ad esempio quando vogliamo conoscere gli attributi dei sistemi sui quali stiamo lavorando. Un esempio riguardante i Fact è visibile nell’immagine seguente.

Qui, dalla schermata mostrata abbiamo lanciato Ansible sul computer dal quale lavoriamo (localhost) avviando il modulo setup (-m setup), che esegue un retrieve (ricerca e recupero) delle informazioni tecniche dell’host, che riepiloga in modo che possano essere utilizzate, ad esempio in un playbook; tali informazioni sono poi i Facts di Ansible, che potremmo considerare variabili discovered da richiamare dai Playbook per effettuare le configurazioni.
I Facts non sono l’unico tipo di variabili, infatti in Ansible queste sono genericamente chiamate Variables; allo scopo va detto che Ansible può lavorare con i metadati provenienti da varie fonti e gestire i loro contesti sotto forma di variabili. Le variabili di Ansible possono essere presenti in:
Altro concetto importante di Ansible sono i task, ossia le le istruzioni che Ansible esegue, in ordine, sui nodi target; in breve un task è l’applicazione di un modulo di Ansible finalizzata a eseguire una certa operazione.
Ogni playbook contiene una lista di task che vengono eseguiti in sequenza su tutte le macchine target. Tra i moduli più usati abbiamo:
L’immagine seguente mostra un task all’interno di un play.

Nel primo task in ordine installiamo un pacchetto di nome httpd che è già presente nel sistema e per sovrascriverlo utilizziamo state: latest, a indicare di installare l’ultima versione (se il package è lo stesso l’operazione non sarà eseguita). Nello specifico, il pacchetto è Apache. Notate che tutti i task hanno un nome: esso non è necessario ma è utile per evitare di fare confusione e per trovare subito il task interessato in una lunga lista.
Nel secondo task carichiamo un file (quello il cui nome e percorso seguono src:) dalla macchina locale e con il modulo copy lo scriviamo nei server il cui percorso che segue dest: ,ovvero, nel caso specifico, var, www, html.
L’ultimo task riavvia un servizio, il cui nome è httpd, riavvia Apache; lo stato (state) è restarted perché dev’essere riavviato.
Già da qui si comincia a vedere la potenza e comodità di Ansible, perché con una decina di righe di istruzioni abbiamo installato un pacchetto su un server, abbiamo copiato dei file ed abbiamo riavviato il servizio corrispondente al pacchetto Apache installato.
Fare ciò su, ad esempio, 100 server, tra configurazione e deployment richiederà una decina di minuti; facendolo con metodi tradizionali richiederebbe ore!
Passiamo adesso agli handler, i quali sono istruzioni che vanno eseguite come conseguenza di una determinata azione. Gli handler sono speciali task eseguiti alla fine di un play se notificato da un altro task, al verificarsi di un cambiamento.
Per esempio, se un task esegue l’aggiornamento di un database o di un file di configurazione, essendo stata eseguita una modifica lo stesso task notifica a un apposito handler task di riavviare il servizio affinché la modifica abbia effetto. La figura seguente chiarisce il concetto e in essa riprendiamo l’esempio del task aggiungendo l’istruzione notify:restart httpd che rimanda all’handler restart httpd.

La cosa da notare è che l’handler viene chiamato solo se si verifica la condizione di notify.
Play e playbook: differenza?
Quando si parla di Ansible si tende a utilizzare molto il termine playbook, tuttavia esistono anche i play ed è quindi necessario evidenziare la differenza tra i due, che in realtà a volte possono coincidere: i play sono una serie di task ordinati da eseguire sui nodi selezionati dall’inventario, mentre il playbook è un file Ansible che contiene uno o più play.
Come dice il termine, playbook è un raccoglitore o album di play.
Un esempio di playbook è riportato nell’immagine qui di seguito, nella quale si vede il contenuto del file YAML costituente il playbook stesso. Questo particolare playbook contiene in realtà un solo play, quindi siamo di fronte al caso tipico in cui playbook e play coincidono.

Nello specifico, il play contiene due task: notate ancora il nome dei task, la definizione degli host destinatari (hosts: web) che in questo caso sono quelli del gruppo [web], il comando become: dove il parametro yes indica che gli host divengono tali dopo l’installazione, quindi le variabili che definiamo (var:) e che in particolare sono la porta http (http_port: 80).
Il primo task da eseguire per attuare il play è quello già visto negli altri esempi e fa uso del modulo yum, quindi abbiamo l’aggiornamento del package e il caricamento del file (quello il cui nome e percorso seguono src:) dalla macchina locale, quindi con il modulo copy lo scriviamo nei server il cui percorso che segue dest: ,ovvero, nel caso specifico, var, www, html.
Esistono numerose funzionalità essenziali associate ai playbook, quali Templates, Loops, Conditionals, Tags e Blocks.
I Template sono file che vengono costruiti dinamicamente sulla base di variabili quando viene eseguito un playbook. Per esempio se bisogna installare php, al posto di creare tanti playbook quante sono le versioni disponibili basta crearne uno solo come Template, contenente come variabile la versione da installare e ogni volta che si deve eseguire, gli si passa come variabile la versione da installare.
Quindi i template sono modelli di playbook che consentono, dinamicamente, di settare e modificare variabili dei play, generare file come quelli di configurazione partendo da variabili, gestire Conditional logic.
La costruzione dei template avviene attraverso un motore chiamato Jinja2 templating engine che è integrato in Ansible.
I loop possono eseguire un task o operazioni multiple come, ad esempio, creare un sacco di utenti su un server, installare tantissimi pacchetti software o ripetere uno step di polling verso gli host fino al raggiungimento di un determinato risultato.
Per esempio, nell’immagine seguente creiamo un loop per installare un certo numero di pacchetti su un nodo utilizzando un unico task invece di tanti; il pacchetto è httpd (la sua ultima versione). Il nome del task (che fa uso del solito modulo yum) è virgolettato e tra parentesi abbiamo item, che rimanda alla descrizione degli oggetti da installare. In altre parole il comando in cui il nome non è univoco ma contiene “{{item}} avrà per parametri quelli specificabili nell’apposita sezione che segue e che vedete chiamata with_tems: dove in questo caso è possibile elencare, ciascuno preceduto su un trattino e su una riga (perché l’esecuzione è sequenziale, come già spiegato…), i nomi dei pacchetti.

Nell’esempio i pacchetti sono solo due, ovvero httpd e mod_wsgi ma avrebbero potrebbero potuto essere decine e decine; anche qui, un loop consente di automatizzare la procedura.
I conditionals sono in pratica l’esecuzione di task (attività) condizionata al verificarsi di certe condizioni valutate a run-time (ossia in corso d’esecuzione) come variabili, fact o il risultato di un task precedente. Un esempio di Conditional logico è:
- yum:
name: httpd
state: latest
when: ansible_os_family = = “RedHat”
dove la condizione segue when: e impone che il task sia eseguito solo se sul server remoto è installata una distribuzione di Linux RedHat. Questo permette di installare un certo pacchetto solo a condizione che il server remoto (il nodo) sia in grado di utilizzarlo.
I tag sono utili per eseguire un sottoinsieme di playbook su richiesta. Nell’immagine di seguito vedete dei tag, che sono richiamati all’interno del playbook: ne abbiamo inseriti due, che sono packages e configuration.

I Role in Ansible
I Role o ruoli, rappresentano una serie di contenuti strettamente correlati che possono essere condivisi più semplicemente che i play da soli e che permettono di gestire meglio e mantenere una serie di playbook complessi. I role raggruppano playbook, file, template ecc. e:
Nell’immagine di seguito vedete due role chiamati common/ e apache/ inseriti in un progetto Ansible.

Per ogni role, nell’esempio proposto abbiamo creato file, template, task ecc.
Le voci sotto common/ e apache/ sono delle directory indicate a titolo di esempio e in realtà al loro interno ci saranno poi file tipo playbook dentro files/ ecc.
Un servizio molto utile collegato ad Ansible è Galaxy (http://galaxy.ansible.com) ed è sostanzialmente un portale dove cercare, riutilizzare e condividere progetti Ansible. Questo consente di realizzare i propri progetti di automazione delle configurazioni partendo da contenuti esistenti elaborati da membri della comunità Ansible, con evidente risparmio nei tempi di sviluppo; permette anche agli sviluppatori di condividere i propri lavori a beneficio dei membri della community. Ad Ansible Galaxy ci si può loggare anche con l’account GitHub, per chi lo avesse.
Prima di iniziare a lavorare con Ansible è consigliabile dare un’occhiata a Galaxy perché fornisce molti spunti utili e progetti sviluppati sui quali fare pratica.
Bene, ora è il momento di iniziare con qualche esempio di utilizzo di Ansible, partendo proprio da Galaxy, dove già nella schermata principale troviamo degli esempi divisi per distribuzione Linux; se vogliamo qualcosa di particolare ci basta fare clic nella casella Search e scrivere le parole chiave, quindi cliccare sull’icona con la lente di ingrandimento o premere Invio.

Una volta trovato il progetto di nostro interesse, che si troverà in un repository GitHub, basta accedere al repository e cliccare sul nome, per eseguire il pull dell’interno repository sul nostro computer locale (vedere immagine seguente).

Il trasferimento e l’installazione si effettuano eseguendo il comando $ ansible-galaxy install seguito dal nome del progetto all’interno dell’ambiente Ansible.
Se vogliamo partire da zero, possiamo analizzare qualche comando, ricordando che Ansible si gestisce da riga di comando; immaginiamo quindi di creare un file ansible chiamato hosts dall’editor di testo e di introdurvi per esempio il contenuto mostrato nella figura seguente (qui l’editor è quello di MacOS).

Il nostro file hosts definisce la rete e, come preannuncia il nome, contiene i nomi dei nodi, che nello specifico sono tre divisi in due gruppi chiamati webservers e server03; al file abbiamo passato la variabile globale [all:vars] che stabilisce che l’utente del computer locale (su cui gira Ansible) autorizzato ad operare sui nodi è l’utente root. La variabile è globale perché è di tipo all.
Chiudiamo e salviamo questo file di configurazione, quindi torniamo alla riga di comando e impartiamo un classico comando Ansible: ansible all -i -m ping, che esegue il modulo ping verso tutti i nodi presenti nell’inventario (-i). La risposta dovrebbe essere quella visibile nell’immagine seguente, ossia contente tre risposte, ciascuna proveniente dagli host dei due gruppi.
Notate che se avessimo voluto effettuare il ping verso un solo gruppo di nodi, ad esempio del gruppo webservers, il comando avrebbe dovuto essere: ansible webservers -i -m ping.

Adesso immaginiamo di voler arrestare il servizio apache sull’unico nodo appartenente al gruppo server03: il comando da impartire è:
ansible server03 -i hosts -m service -a “name=apache state=stopped2”
dove -i definisce che il comando è per un nodo dell’inventario, -m indica il modulo service e -a il comando riguardante il servizio, che in questo caso riceve lo stato “stopped”. Per far ripartire tale servizio sullo stesso server è sufficiente impartire il comando:
ansible server03 -i hosts -m service -a “name=apache state=started2”
Vediamo ora come costruire un playbook; allo scopo occorre aprire l’interfaccia a riga di comando e da qui impartire il comando (che dipende dal sistema operativo) per creare il nostro file: nello specifico lo chiameremo apache.yml (l’estensione di YAML).
Aperto il file, la prima cosa che dobbiamo fare è dargli un nome: nello specifico, installa apache, visto che vogliamo che installi apache sui server specificati; inoltre, vogliamo sia installato htop. L’installazione dei pacchetti viene specificata dal comando with_items, cui segue l’elenco corrispondente e sarà eseguita su tutti i nodi (hosts: all) dall’utente remoto root. Notate che è fondamentale rispettare l’indentazione che vedete nell’esempio, altrimenti al momento dell’esecuzione il playbook restituirà dei messaggi d’errore e non sarà eseguito.
Il file che otteniamo è quello mostrato qui di seguito ed è poi il nostro playbook. Notate come tutte le parti siano indentate.

A questo punto se vogliamo eseguire il nostro playbook torniamo alla nostra interfaccia a riga di comando e impartiamo da essa il comando per l’esecuzione:
ansible-playbook -v apache.yml
seguito da Invio. Il playbook verrà quindi eseguito.