Gestione della Configurazione 101: Scrittura di Playbook Ansible

Introduzione

In poche parole, la gestione della configurazione del server (anche popolarmente indicata come Automazione IT) è una soluzione per trasformare la tua amministrazione dell’infrastruttura in un codice, descrivendo tutti i processi necessari per distribuire un server in un insieme di script di provisioning che possono essere versionati e riutilizzati facilmente. Può migliorare notevolmente l’integrità di qualsiasi infrastruttura server nel tempo.

In una guida precedente, abbiamo parlato dei principali vantaggi nell’implementare una strategia di gestione della configurazione per la tua infrastruttura server, di come funzionano gli strumenti di gestione della configurazione e di quali caratteristiche comuni hanno tipicamente questi strumenti.

Questa parte della serie ti guiderà attraverso il processo di automazione del provisioning del server utilizzando Ansible, uno strumento di gestione della configurazione che fornisce un completo framework di automazione e capacità di orchestrare, mantenendo l’obiettivo della massima semplicità e minimalismo. Ci concentreremo sulla terminologia del linguaggio, la sintassi e le funzionalità necessarie per creare un esempio semplificato per automatizzare completamente il rilascio di un server web Ubuntu 18.04 utilizzando Apache.

L’elenco seguente contiene tutti i passaggi che dobbiamo automatizzare per raggiungere il nostro obiettivo:

  1. Aggiornare la cache di apt
  2. Installare Apache
  3. Creare una directory di root del documento personalizzata
  4. Posizionare un file index.html nella radice del documento personalizzato
  5. Applicare un modello per configurare il nostro host virtuale personalizzato
  6. Riavviare Apache

Cominceremo dando un’occhiata alla terminologia utilizzata da Ansible, seguita da una panoramica delle principali caratteristiche del linguaggio che possono essere utilizzate per scrivere i playbook. Alla fine della guida, troverai il contenuto di un esempio completo di provisioning per automatizzare i passaggi descritti per la configurazione di Apache su Ubuntu 18.04.

Nota: questa guida è destinata a introdurti al linguaggio di Ansible e a come scrivere i playbook per automatizzare la configurazione del tuo server. Per una visione più introduttiva di Ansible, compresi i passaggi necessari per l’installazione e per iniziare con questo strumento, così come per eseguire comandi e playbook di Ansible, controlla la nostra guida Come Installare e Configurare Ansible su Ubuntu 18.04.

Primi Passi

Prima di poter passare a una visione più pratica di Ansible, è importante che ci familiarizziamo con la terminologia e i concetti importanti introdotti da questo strumento.

Terminologia

La seguente lista contiene una panoramica rapida dei termini più rilevanti utilizzati da Ansible:

  • Nodo di Controllo: la macchina dove è installato Ansible, responsabile dell’esecuzione della fornitura sui server che si stanno gestendo.
  • Inventario: un file INI che contiene informazioni sui server che si stanno gestendo.
  • Playbook: un file YAML che contiene una serie di procedure che dovrebbero essere automatizzate.
  • Task: un blocco che definisce una singola procedura da eseguire, ad esempio: installare un pacchetto.
  • Modulo: un modulo astrae tipicamente un compito di sistema, come gestire pacchetti o creare e modificare file. Ansible ha una moltitudine di moduli integrati, ma è anche possibile crearne di personalizzati.
  • Ruolo: un insieme di playbook, modelli e altri file correlati, organizzati in modo predefinito per facilitare il riutilizzo e la condivisione.
  • Provisioning: una fornitura eseguita dall’inizio alla fine è chiamata un provisioning.
  • Facts: variabili globali contenenti informazioni sul sistema, come le interfacce di rete o il sistema operativo.
  • Handlers: utilizzati per attivare cambiamenti dello stato del servizio, come riavviare o ricaricare un servizio.

Formato del Task

A task defines a single automated step that should be executed by Ansible. It typically involves the usage of a module or the execution of a raw command. This is how a task looks:

- name: This is a task
  apt: name=vim state=latest

La parte name è effettivamente facoltativa, ma consigliata, poiché compare nell’output della configurazione quando il compito viene eseguito. La parte apt è un modulo integrato di Ansible che astrae la gestione dei pacchetti nelle distribuzioni basate su Debian. Questo esempio di compito indica ad Ansible che il pacchetto vim dovrebbe avere il suo stato cambiato in latest, il che farà sì che il gestore dei pacchetti installi questo pacchetto nel caso in cui non sia ancora installato.

Formato del Playbook

I playbook sono file YAML che contengono una serie di direttive per automatizzare la configurazione di un server. L’esempio seguente è un playbook semplice che esegue due compiti: aggiorna la cache di apt e successivamente installa vim:

---
- hosts: all
  become: true
  tasks:
     - name: Update apt-cache 
       apt: update_cache=yes

     - name: Install Vim
       apt: name=vim state=latest

YAML si basa sull’indentazione per serializzare le strutture dei dati. Per questo motivo, quando si scrivono playbook e soprattutto quando si copiano esempi, è necessario prestare particolare attenzione a mantenere l’indentazione corretta.

Prima della fine di questa guida vedremo un esempio più realistico di playbook, spiegato in dettaglio. La prossima sezione ti fornirà una panoramica degli elementi e delle funzionalità più importanti che possono essere utilizzati per scrivere playbook Ansible.

Scrittura dei Playbook

Ora che sei familiare con la terminologia di base e il formato generale dei playbook e dei task in Ansible, impareremo alcune caratteristiche dei playbook che possono aiutarci a creare automazioni più versatili.

Lavorare con le Variabili

Esistono diversi modi per definire le variabili in Ansible. Il modo più semplice è utilizzando la sezione vars di un playbook. L’esempio seguente definisce una variabile package che successivamente viene utilizzata all’interno di un task:

---
- hosts: all
  become: true
  vars:
     package: vim
  tasks:
     - name: Install Package
       apt: name={{ package }} state=latest

La variabile package ha un ambito globale, il che significa che può essere accessa da qualsiasi punto del provisioning, anche da file e modelli inclusi.

Utilizzo dei Cicli

I cicli vengono tipicamente utilizzati per ripetere un task utilizzando valori di input diversi. Ad esempio, invece di creare 10 task per installare 10 pacchetti diversi, puoi creare un singolo task e utilizzare un ciclo per ripetere il task con tutti i pacchetti diversi che desideri installare.

Per creare un ciclo all’interno di un task, includi l’opzione with_items con un array di valori. Il contenuto può essere accesso attraverso la variabile di ciclo item, come mostrato nell’esempio seguente:

- name: Install Packages
  apt: name={{ item }} state=latest
  with_items:
     - vim
     - git
     - curl  

Puoi anche utilizzare una variabile di array per definire i tuoi elementi:

---
- hosts: all
  become: true
  vars:
     packages: [ 'vim', 'git', 'curl' ]
  tasks:
     - name: Install Package
       apt: name={{ item }} state=latest
       with_items: "{{ packages }}"

Utilizzo dei condizionali

I condizionali possono essere utilizzati per decidere dinamicamente se eseguire o meno un’attività, basandosi su una variabile o un output da un comando, ad esempio.

Nell’esempio seguente verrà eseguito solo lo spegnimento dei sistemi basati su Debian:

- name: Shutdown Debian Based Systems
  command: /sbin/shutdown -t now
  when: ansible_os_family == "Debian"

Il condizionale when riceve come argomento un’espressione da valutare. L’attività viene eseguita solo nel caso in cui l’espressione venga valutata come true. Nel nostro esempio, abbiamo testato un fatto per verificare se il sistema operativo appartiene alla famiglia Debian.

A common use case for conditionals in IT automation is when the execution of a task depends on the output of a command. With Ansible, the way we implement this is by registering a variable to hold the results of a command execution, and then testing this variable in a subsequent task. We can test for the command’s exit status (if failed or successful). We can also check for specific contents inside the output, although this might require the usage of regex expressions and string parsing commands.

Nell’esempio successivo sono mostrate due attività condizionali basate sull’output di un comando php -v. Testeremo lo stato di uscita del comando, poiché sappiamo che fallirà l’esecuzione nel caso PHP non sia installato su questo server. La parte ignore_errors dell’attività è importante per assicurare che il provisioning continui anche quando il comando fallisce nell’esecuzione.

- name: Check if PHP is installed
  register: php_installed
  command: php -v
  ignore_errors: true

- name: This task is only executed if PHP is installed
  debug: var=php_install
  when: php_installed|success
  
- name: This task is only executed if PHP is NOT installed
  debug: msg='PHP is NOT installed'
  when: php_installed|failed

Il modulo debug utilizzato qui è un modulo utile per mostrare i contenuti delle variabili o messaggi di debug. Può stampare una stringa (quando si utilizza l’argomento msg) o stampare i contenuti di una variabile (quando si utilizza l’argomento var).

Lavorare con i modelli

I modelli vengono tipicamente utilizzati per configurare file di configurazione, consentendo l’uso di variabili e altre funzionalità destinate a rendere questi file più versatili e riutilizzabili. Ansible utilizza il motore di template Jinja2.

Il seguente esempio è un modello per configurare un host virtuale Apache, utilizzando una variabile per impostare la directory dei documenti per questo host:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot {{ doc_root }}

    <Directory {{ doc_root }}>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Il modulo integrato template viene utilizzato per applicare il modello da un compito. Se hai nominato il file del modello sopra vhost.tpl, e l’hai posizionato nella stessa directory del tuo playbook, ecco come applicheresti il modello per sostituire l’host virtuale Apache predefinito:

- name: Change default Apache virtual host
  template: 
    src: vhost.tpl
    dest: /etc/apache2/sites-available/000-default.conf

Definizione e Attivazione degli Handler

Gli handler vengono utilizzati per attivare un cambiamento di stato in un servizio, come un riavvio o uno stop. Anche se potrebbero sembrare abbastanza simili ai compiti regolari, gli handler vengono eseguiti solo quando precedentemente attivati da una direttiva notify in un compito. Di solito vengono definiti come un array in una sezione handlers del playbook, ma possono anche risiedere in file separati.

Consideriamo il nostro precedente esempio di utilizzo del modello, dove abbiamo configurato un host virtuale Apache. Se vuoi assicurarti che Apache venga riavviato dopo una modifica all’host virtuale, prima devi creare un handler per il servizio Apache. Ecco come gli handler vengono definiti all’interno di un playbook:

handlers:
    - name: restart apache
      service: name=apache2 state=restarted
    
    - name: other handler
      service: name=other state=restarted

La direttiva name qui è importante perché sarà l’identificatore unico di questo gestore. Per attivare questo gestore da un compito, dovresti usare l’opzione notify:

- name: Change default Apache virtual host
  template: 
    src: vhost.tpl
    dest: /etc/apache2/sites-available/000-default.conf
  notify: restart apache

Abbiamo visto alcune delle caratteristiche più importanti che puoi utilizzare per iniziare a scrivere playbook di Ansible. Nella prossima sezione, esamineremo un esempio più concreto di un playbook che automatizzerà l’installazione e la configurazione di Apache su Ubuntu.

Playbook di Esempio

Adesso diamo un’occhiata a un playbook che automatizzerà l’installazione di un server web Apache in un sistema Ubuntu 18.04, come discusso nell’introduzione di questa guida.

L’esempio completo, incluso il file di modello per la configurazione di Apache e un file HTML da servire tramite il server web, può essere trovato su Github. La cartella contiene anche un Vagrantfile che ti permette di testare il playbook in una configurazione semplificata, utilizzando una macchina virtuale gestita da Vagrant.

Contenuti del Playbook

I contenuti completi del playbook sono disponibili qui per tua comodità:

playbook.yml
  1. ---
  2. - hosts: all
  3. become: true
  4. vars:
  5. doc_root: /var/www/example
  6. tasks:
  7. - name: Update apt
  8. apt: update_cache=yes
  9. - name: Install Apache
  10. apt: name=apache2 state=latest
  11. - name: Create custom document root
  12. file: path={{ doc_root }} state=directory owner=www-data group=www-data
  13. - name: Set up HTML file
  14. copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
  15. - name: Set up Apache virtual host file
  16. template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
  17. notify: restart apache
  18. handlers:
  19. - name: restart apache
  20. service: name=apache2 state=restarted

Esaminiamo ogni parte di questo playbook in maggior dettaglio:

hosts: all
Il playbook inizia specificando che dovrebbe essere applicato a tutti gli host nel tuo inventario (hosts: all). È possibile limitare l’esecuzione del playbook a un host specifico o a un gruppo di host. Questa opzione può essere sovrascritta durante l’esecuzione.

become: true
La parte become: true indica ad Ansible di utilizzare l’escalation dei privilegi (sudo) per eseguire tutti i compiti in questo playbook. Questa opzione può essere sovrascritta caso per caso.

vars
Definisce una variabile, doc_root, che viene poi utilizzata in un compito. Questa sezione potrebbe contenere più variabili.

tasks
La sezione in cui sono definiti i compiti effettivi. Il primo compito aggiorna la cache di apt, e il secondo compito installa il pacchetto apache2.

Il terzo compito utilizza il modulo integrato file per creare una directory da utilizzare come nostra root dei documenti. Questo modulo può essere utilizzato per gestire file e directory.

Il quarto compito utilizza il modulo copy per copiare un file locale sul server remoto. Stiamo copiando un semplice file HTML da servire come nostro sito web ospitato da Apache.

handlers
Infine, abbiamo la sezione handlers, dove vengono dichiarati i servizi. Definiamo il gestore restart apache che viene notificato dal quarto compito, dove viene applicato il modello di Apache.

Eseguire un playbook

Una volta che hai scaricato i contenuti di questo playbook sul tuo nodo di controllo di Ansible, puoi utilizzare ansible-playbook per eseguirlo su uno o più nodi del tuo inventario. Il comando seguente eseguirà il playbook su tutti gli host dal file di inventario predefinito, utilizzando l’autenticazione della chiave SSH per connettersi come utente di sistema corrente:

  1. ansible-playbook playbook.yml

Puoi anche utilizzare -l per limitare l’esecuzione a un singolo host o a un gruppo di host dal tuo inventario:

  1. ansible-playbook -l host_or_group playbook.yml

Se hai bisogno di specificare un utente SSH diverso per connettersi al server remoto, puoi includere l’argomento -u utente in quel comando:

  1. ansible-playbook -l host_or_group playbook.yml -u remote-user

Per ulteriori informazioni su come eseguire comandi e playbooks di Ansible, consulta la nostra guida su Come Installare e Configurare Ansible su Ubuntu 18.04.

Conclusione

Ansible è uno strumento di automazione IT minimalista che ha una curva di apprendimento bassa, utilizzando YAML per i suoi script di provisioning. Ha un gran numero di moduli incorporati che possono essere utilizzati per astratte le attività come l’installazione di pacchetti e il lavoro con i modelli. I suoi requisiti semplificati di infrastruttura e il linguaggio semplice possono essere adatti a coloro che stanno iniziando con la gestione della configurazione. Tuttavia, potrebbe mancare di alcune funzionalità avanzate che si possono trovare con strumenti più complessi come Puppet e Chef.

Nella prossima parte di questa serie, vedremo una panoramica pratica di Puppet, uno strumento popolare e ben consolidato per la gestione della configurazione che utilizza un DSL personalizzato espressivo e potente basato su Ruby per scrivere script di provisioning.

Source:
https://www.digitalocean.com/community/tutorials/configuration-management-101-writing-ansible-playbooks