7.4 KiB
Playbook
Un playbook Ansible è un file testuale, scritto in formato YAML, che definisce una sequenza di operazioni (task) da eseguire su uno o più nodi.
Un playbook può contenere uno o più Play. Ogni Play è composto da una serie di task, che a loro volta possono richiamare uno o più moduli.
Struttura di un playbook
Di seguito è riportato un esempio di playbook:
---
- name: install and start httpd
hosts: databases
tasks:
- name: install httpd
apt:
name: httpd
state: latest
become: true
- name: start httpd
service:
name: httpd
state: started
become: true
name: specifica il nome del play, che descrive l'azione da eseguirehosts: indica i nodi sui quali il play sarà eseguitotasks: contiene un elenco di operazioni da eseguire
In questo esempio:
- il playbook contiene un unico play
- il play ha il compito di installare e avviare il servizio httpd su un gruppo di host denominato databases
- sono definiti due task: il primo installa il pacchetto httpd tramite il modulo apt, mentre il secondo avvia il servizio httpd utilizzando il modulo service
- l’opzione
become: trueindica che i task devono essere eseguite con privilegi elevati, tipicamente utilizzando sudo
Un esempio di playbook con due play:
---
- name: install and start apache
hosts: webservers
tasks:
- name: install apache
apt:
name: apache2
state: latest
become: true
- name: start apache
service:
name: apache2
state: started
become: true
- name: install and start mysql
hosts: databases
tasks:
- name: install mysql
apt:
name: mysql-server
state: latest
become: true
- name: start mysql
service:
name: mysql
state: started
become: true
Esecuzione di un playbook
Per eseguire un playbook, è necessario utilizzare il comando ansible-playbook, specificando:
- l’inventory file, se custom, con l'opzione
-i - il percorso del playbook
- eventuali opzioni aggiuntive, come
-ask-vault-pass, che richiede la password per decifrare i file crittografati conansible-vault
ansible-playbook -i inventory playbook/my-playbook.yml -K --ask-vault-pass
Conditionals
Le istruzioni condizionali consentono di modificare il comportamento di un playbook in base a specifiche condizioni.
L'istruzione condizionale più semplice si applica a un singolo task, utilizzando la parola chiave when. In questo caso, il task verrà eseguito solo sui nodi in cui la condizione specificata è soddisfatta.
Tipologie di condizioni
Le condizioni possono basarsi su diversi tipi di dati:
ansible_facts: attributi specifici di ogni host, messi a disposizione da Ansible. Questi fanno riferimento a caratteristiche del nodo, come il tipo sistema operativo, le caratteristiche hardware e altre proprietà rilevanti. Sono utili per adattare il comportamento del playbook in base alle caratteristiche del nodo targetregistered variables: variabili che contengono il risultato di task precedenti. È possibile condizionare in questo modo l’esecuzione di un task in base all’esito di un task già eseguitovariabilidefinite nel playbook o nell'inventory
Un semplice esempio di condizione when:
---
- name: playbooks with conditions
hosts: db
become: true
tasks:
- name: install postgres
yum:
name: postgresql
state: latest
when: ansible_distribution == 'Ubuntu'
Un esempio di registered variables:
---
- name: Install and Start HTTPD Service
hosts: webservers
become: true
tasks:
- name: Install the httpd package
yum:
name: httpd
state: present
register: httpd_installation
- name: Start the httpd service
service:
name: httpd
state: started
when: httpd_installation.changed == true
Questo task utilizza il modulo yum per installare il pacchetto httpd. Durante l'esecuzione, il risultato dell'installazione viene registrato nella variabile httpd_installation. Avvia infine il servizio httpd, ma solo se l'installazione del pacchetto è stata completata con successo.
Loops
I loop in Ansible consentono di ripetere un task più volte all'interno di un playbook, evitando la necessità di riscrivere blocchi di codice che eseguono la stessa operazione.
I tre tipi principali di loop sono:
ListeListe di hashDizionari
Liste
Per i loop di liste, si utilizza la parola chiave loop, seguita da una lista di stringhe. Il task verrà eseguito tante volte quante sono le stringhe nella lista, e {{ item }}, nel task, assumerà il valore dell'elemento iesimo.
---
- name: playbook with loop
hosts: db
become: true
tasks:
- name: add users
user:
name: "{{ item }}"
loop:
- userOne
- userTwo
Liste di hash
Per i loop di liste di hash, si utilizza la medesima parola chiave loop, ma la lista contiene elementi chiavi: valore. In questo caso, si può accedere ai valori usando la sintassi {{ item.key }}.
---
- name: Playbook con loop su lista di hash
hosts: db
become: true
tasks:
- name: add users
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
shell: "{{ item.shell }}"
loop:
- { name: 'userOne', uid: 1001, shell: '/bin/bash' }
- { name: 'userTwo', uid: 1002, shell: '/bin/zsh' }
Blocks
I blocchi in Ansible vengono impiegati per due finalità principali:
- raggruppare task correlati tra loro, in modo da applicare direttive comuni a un insieme di operazioni
- gestire gli errori che possono verificarsi durante l’esecuzione dei task, consentendo di definire azioni specifiche in caso di fallimento o di successo
Tutte le direttive associate a un blocco vengono automaticamente ereditate da tutti i task contenuti al suo interno.
I blocchi offrono due sezioni dedicate alla gestione degli errori:
rescue: contiene i task che vengono eseguiti immediatamente nel caso in cui almeno uno dei task all'interno del blocco generi un errorealways: contiene i task che vengono eseguiti indipendentemente dall’esito dei task nel blocco, sia in caso di successo che di fallimento
Un esempio di raggruppamento:
---
- name: block
hosts: db
tasks:
- block:
- name: list user
command: ls -l /usr/
- name: list root
command: ls -l /root/
- name: list bin
command: ls -l /bin/
- name: list home
command: ls -l ~/
become: yes
- name: list home
command: "ls -l ~/"
La direttiva become: yes è associata al blocco e viene applicata a tutti i task al suo interno, semplificando la gestione delle operazioni correlate.
Un esempio di gestione di errori:
---
- name: Error handling example
hosts: db
tasks:
- block:
- name: Execute a command that fail
command: /bin/false
rescue:
- name: Handle the error
debug:
msg: "The command failed, executing an alternative action."
always:
- name: Always execute this command
debug:
msg: "This action is executed regardless of the block's result."
In questo caso, il task nella sezione rescue viene eseguito solo se il comando /bin/false fallisce, mentre il task nella sezione always viene eseguito in ogni circostanza.