Premier Training & Business Partner Red Hat

RUOLI: Ansible all’ennesima potenza

Pietro Ripamonti
RHCSA
Ti piacerebbe diventare anche tu uno di noi e
pubblicare i tuoi articoli nel blog degli RHCE italiani?

Ciao!

Lo scopo di questo brevissimo tutorial è introdurre all’utilizzo dei ruoli in Ansible in modo chiaro e conciso. Questi rappresentano la vera forza del tool di automazione, in quanto sono il metodo più efficiente in assoluto per non ri-scrivere del codice già fortemente riutilizzabile per sua natura.

La documentazione ufficiale definisce i ruoli come “Un modo di caricare automaticamente certi file di variabili, task e handlers, basandosi su una precisa struttura di dati”, facendo forza sulla possibilità di chiamare indirettamente da un singolo playbook, altri insiemi di playbook già definiti, con relativi file, dipendenze e contenuti correlati.

Se immaginiamo per esempio di dover aggiornare un applicativo web su più nodi contemporaneamente, oltre ovviamente a poter effettuare manualmente la procedure di deploy “come si è sempre fatto” oppure scrivere da zero il flusso di automazione per effettuarlo, possiamo prima cercare se esiste già un ruolo scritto che soddisfa i nostri requisiti.

Installando Ansible viene scaricato anche il tool ansible-galaxy, tramite il quale è possibile sia inizializzare le directory dei nuovi ruoli, sia cercare e scaricare ruoli ufficiali o forniti dalla community presenti sul repository pubblico. Nello snippet d’esempio seguente, cerchiamo ed installiamo un ruolo per installare Samba:

[ansible@cos1 roles]$ ansible-galaxy search samba | grep geerling
 geerlingguy.samba                        Samba for RHEL/CentOS.

[ansible@cos1 roles]$ ansible-galaxy install geerlingguy.samba
- downloading role 'samba', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-samba/archive/1.1.3.tar.gz
- extracting geerlingguy.samba to /home/ansible/.ansible/roles/geerlingguy.samba
- geerlingguy.samba (1.1.3) was installed successfully

Con questo approccio possiamo evitare di riscrivere grosse porzioni di codice complicato per eseguire compiti semplici. Teniamo a mente che è comuque buona prassi rivedere sempre il codice prima di utilizzarlo all’interno dei nostri progetti in quanto l’approccio dell’utente che l’ ha creato potrebbe essere molto diverso da quello al quale siamo abituati.

Analizziamo un semplice playbook per comprendere il concetto chiave della chiamata ad un ruolo. Prendiamo come esempio questa brevissima sezione di codice relativa ad un main.yml che funge da entrypoint per il riutilizzo di cui sopra, il quale utilizza la sintassi “classica” attraverso la keyword roles:

---
- hosts: webservers
  vars: service=httpd
  roles:
    - ruolo_esempio

Questo snippet, per il ruolo_esempio designato:

  • Si limita a definire gli host sui quali eseguire i ruoli
  • Chiama indirettamente il file ./ruolo_esempio/tasks/main.yml
  • Definisce la variabile “service” che verrà passata al ruolo caricato

Così facendo si avvia anche l’esecuzione di ogni handler legato al ruolo, che sia definito nel playbook caricato tra i tasks, o comunque presente nella specifica sottodirectory del ruolo. Si include ogni variabile, si carica ogni eventuale dipendenza, si validano tutte le referenze legate a files, template e tasks.

Notiamo che la direttiva “service” definita a monte verrà ereditata così come ogni altra variabile, seguendo le regole di erediterietà e overriding classiche dello strumento Ansible.

Teniamo inoltre presente che, utilizzando il sistema dei ruoli, diviene ancor più utile un flow-control minuzioso… “pre_tasks” e “post_tasks”, al fine di orchestrare l’esecuzione nel suo insieme. Eseguendo compiti rispettivamente prima e dopo i ruoli richiamati.

La struttura della cartella nella quale è inserito il playbook è il primo posto in cui Ansible cercherà di risolvere i riferimenti a contenuti esterni. Per predisporre questa directory ci viene in aiuto il comando ansible-galaxy.

#ansible-galaxy init ruolo_esempio

Esplodiamo la directory corrente per spiegare nel dettaglio come richiamare del codice già definito:

ansible@cos1 roles]$ tree
├── main.yml
└── ruolo_esempio
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml

Possiamo notare che alla radice della cartella vi è un file main.yml, la cui sintassi chiama il file ./ruolo_esempio/tasks/main.yml attraverso il tag specifico “roles”. L’utilizzo di questo tag è il cuore del presente tutorial:

--- 
 hosts: thiscomputer
 become: true
 roles:
   - ruolo_esempio

Riporto il contenuto del file richiamato:

---
    - name: Playbook evocato dal primo main
      yum:
        name: "{{ service }}"
        state: present

Del quale osserviamo l’esecuzione attraverso il lancio del solo main.yml presente nella directory radice:

[ansible@cos1 roles]$ ansible-playbook main.yml
 
PLAY [thiscomputer] ******************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [thiscomputer]
 
TASK [test2 : Playbook evocato dal primo main] ******************************************************************************
ok: [thiscomputer]
 
PLAY RECAP ******************************************************************************
thiscomputer: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Questo meccanismo, unito alla potenza del repository di ruoli ansible-galaxy, permette un forte riutilizzo del codice, venendoci in aiuto non solo nella definizione di automazione complesse, ma facendoci anche risparmiare molto tempo.

Valutiamo di contribuire al lavoro della community su Galaxy, così come noi possiamo beneficiare dello sforzo degli utenti, qualcuno potrebbe aver bisogno proprio del contenuti su cui stiamo lavorando.

Info about author

Pietro Ripamonti

Classe '96, sistemista dal 2016, il mio focus è sui sistemi operativi Linux-like e gli applicativi Red Hat. Per passione mi occupo anche di identità digitale e post-produzione audio.