Files
learning/ansible/003-playbook.md
2025-09-02 20:52:10 +02:00

10 KiB
Raw Blame History

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 eseguire
  • hosts: indica i nodi sui quali il play sarà eseguito
  • tasks: 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
  • lopzione become: true indica 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:

  • linventory 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 con ansible-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 target
  • registered variables: variabili che contengono il risultato di task precedenti. È possibile condizionare in questo modo lesecuzione di un task in base allesito di un task già eseguito
  • variabili definite nel playbook o nell'inventory

Un semplice esempio di condizione when:

---
- name: playbooks with conditions
  hosts: db
  become: true

  tasks:
    - name: install postgres
      apt:
        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
      apt:
        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 apt 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:

  • Liste
  • Liste di hash
  • Dizionari

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 lesecuzione 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 errore
  • always: contiene i task che vengono eseguiti indipendentemente dallesito 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.

Handlers

Gli handler in Ansible consentono l'esecuzione condizionale di specifiche operazioni, attivate solo quando un task determina modifiche su un nodo target.

---
- name: playbook with handlers
  hosts: db
  become: true

  tasks:
    - name: install httpd
      apt:
        name: httpd
        state: present
      notify:
        - Start httpd

    handlers:
      - name: Start httpd
        service:
          name: httpd
          state: started

La parola chiave notify serve a richiamare lhandler specificato. Durante la prima esecuzione, una volta installato il software httpd, lhandler verrà attivato e avvierà il servizio. Nelle esecuzioni successive, qualora il pacchetto sia già presente e non subisca modifiche, il task non verrà eseguito e, di conseguenza, neppure lhandler associato verrà richiamato.

Per impostazione predefinita, gli handlers vengono eseguiti solo dopo che tutti i task del playbook sono stati completati. Questo significa che, anche se più task notificano lo stesso handler, questultimo verrà eseguito una sola volta.

Tags

I tag consentono di contrassegnare specifici task, offrendo la possibilità di selezionare quali parti eseguire di un playbook.

Per aggiungere un tag a un task, è sufficiente utilizzare la direttiva tags seguita da un elenco di etichette. Ogni task può essere associato a uno o più tag, come illustrato nellesempio seguente:

---
- name: playbook with tags
  hosts: db
  become: true

  tasks:
    - name: install httpd
      apt:
        name: httpd
        state: present
      tags:
        - http
        
    - name: install postgres
      apt:
        name: postgresql
        state: present
      tags:
        - db

In questo esempio, ogni task è associato a un tag specifico, rispettivamente http e db. In questo modo, è possibile eseguire solo i task contrassegnati da un determinato tag.

Tag speciali

Ansible offre due tag speciali, always e never: un task contrassegnato con il tag always verrà sempre eseguito, indipendentemente dai tag specificati nella riga di comando. Al contrario, un task contrassegnato con il tag never non verrà mai eseguito, a meno che non venga esplicitamente richiesto tramite lopzione --tags.

Esecuzione tramite riga di comando

Utilizzando l'opzione --tags, è possibile specificare i task da eseguire:

ansible-playbook playbook.yml --tags "http"

Questo comando eseguirà solo i task contrassegnati con il tag http.

Al contrario, per escludere task specifici dall'esecuzione, si utilizza l'opzione --skip-tags:

ansible-playbook playbook.yml --skip-tags "db"

Questo comando salterà l'esecuzione di tutti i task contrassegnati con il tag db.