Premier Training & Business Partner Red Hat

Ansible per l’automazione IT (terza parte)

Andrea Manzini
Ti piacerebbe diventare anche tu uno di noi e
pubblicare i tuoi articoli nel blog degli RHCE italiani?

Ansible

Dopo aver preso confidenza con l’ambiente Ansible, cominciamo ad usarlo per automatizzare i compiti di ogni giorno.
A titolo didattico scriveremo un playbook per installare un ambiente apache+php su un nuovo server e per provare il funzionamento faremo il deploy di una semplice pagina web.
Attiviamo quindi la macchina virtuale di cui avevamo fatto il provisioning nello scorso articolo:

$ vagrant up

e apriamo un editor per iniziare a scrivere il nostro playbook :

---
- name: installa apache+php e una pagina di esempio
  remote_user: root
  sudo: yes
  hosts: web
  tasks:
    - name: installazione Apache
      yum: name=httpd state=present

    - name: installazione PHP 
      yum: name=php state=present

    - name: avvio servizio http 
      service: name=httpd state=running enabled=yes

    - name: deploy script PHP 
      copy: src=index.php dest=/var/www/html/index.php mode=0664

possiamo notare nel playbook una lista di task, uno per ogni “step” del nostro compito: è come dire a qualcuno di eseguire queste azioni passo-passo.

prima di lanciare il playbook, prepariamo il file da copiare…

$ echo "<?php phpinfo(); ?>" > index.php

se usiamo virtualbox come hypervisor, dobbiamo aggiungere una riga al file di configurazione di Vagrant perché attivi il forwarding della porta 80 della guest sulla porta 8000 del nostro pc
(vedi https://docs.vagrantup.com/v2/networking/forwarded_ports.html)

config.vm.network "forwarded_port", guest: 80, host: 8000

e dare il comando per ricaricare la virtual machine con la nuova configurazione:

vagrant reload

Ora possiamo lanciare il playbook

$ ansible-playbook apache_php.yml
 
PLAY [installa apache+php e una pagina di esempio] **************************** 
 
GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]
 
TASK: [installazione Apache] ************************************************** 
changed: [127.0.0.1]
 
TASK: [installazione PHP] ***************************************************** 
changed: [127.0.0.1]
 
TASK: [avvio servizio http] *************************************************** 
changed: [127.0.0.1]
 
TASK: [deploy script PHP] ****************************************************** 
changed: [127.0.0.1]
 
PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=5    changed=4    unreachable=0    failed=0

ansible ci dice che è andato tutto bene… Possiamo controllare l’esito aprendo il browser su http://localhost:8000 e… Non funziona 🙂
Sulla guest Centos è attivo iptables, che blocca la comunicazione verso la porta 80. Potremmo semplicemente fermare il servizio firewall, ma ne approfitteremo per scrivere un nuovo playbook generico, che configuri iptables secondo le nostre esigenze. In prima istanza potremmo pensare che basterebbe aggiungere al playbook un task come questo

- name: Apache | add apache iptable rule
  command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "Apache"
  sudo: true

però sarebbe un errore, perché violerebbe il principio di idempotenza: eseguendo più volte lo stesso task, continueremo ad accodare la stessa regola, cosa da evitare.
Per risolvere ci sono varie alternative, tra cui la seguente:

- hosts: all
  tasks:
    - name: Open the correct IPTables ports
      lineinfile: dest=/etc/sysconfig/iptables
                  regexp="^-A INPUT -m state --state NEW -m {{item.protocol}} -p {{item.protocol}} --dport {{item.port}} -j ACCEPT$"
                  line="-A INPUT -m state --state NEW -m {{item.protocol}} -p {{item.protocol}} --dport {{item.port}} -j ACCEPT"
                  insertafter="^:OUTPUT ACCEPT \[\d*:\d*\]$"
      with_items:
        - { protocol: tcp, port: 80 }
        - { protocol: tcp, port: 22 }
      notify:
        - restart iptables
 
  handlers:
      - name: restart iptables
        action: service name=iptables state=restarted

come funziona ? usiamo il modulo lineinfile per identificare tutte le linee di

/etc/sysconfig/iptables

che soddisfino la regexp, e la sostituiamo con un valore parametrico, il cui contenuto cioè è specificato tramite variabili.
Ne approfittiamo per introdurre il concetto di handlers, che a livello di sintassi sono normali task ma hanno la caratteristica di venire invocati quando in un task è presenta la direttiva “notify” e quando il task notifica che è stato cambiato qualcosa. L’esempio tipico è la necessità di riavviare un servizio solo quando il file di configurazione è stato effettivamente modificato.
Salviamo il playbook come iptables.yml e lo includiamo nel nostro script iniziale:

---
- name: installa apache+php e una pagina di esempio
  remote_user: root
  sudo: yes
  hosts: web
  tasks:
    - name: installazione Apache
      yum: name=httpd state=present
 
    - name: installazione PHP 
      yum: name=php state=present
 
    - name: avvio servizio http 
      service: name=httpd state=running enabled=yes
 
    - name: deploy script PHP 
      copy: src=index.php dest=/var/www/index.php mode=0664
 
- include: iptables.yml

e dopo averlo lanciato godiamoci il risultato, il nostro server è pronto per ospitare pagine php:
php_info

Al di là dell’attività tutto sommato semplice, abbiamo ottenuto due cose molto importanti:

  • una “descrizione” di come è configurato il server
  • un setup riproducibile a piacimento in maniera pressochè automatica partendo da un server appena installato

Questa è solo una introduzione al mondo di Ansible, e prima di concludere invito i lettori a visitare qualche sito per approfondirne la conoscenza.
Anzitutto Ansible non è solo linea di comando ma presso il sito ufficiale è disponibile una web dashboard che permette di controllare i job, avere report, statistiche e così via:

ansible_tower_sshot1

Ansible Galaxy è invece un repository comunitario di “ricette”, playbooks, task moduli e tutto quello che si può immaginare … Se dovete installare e configurare software come Tomcat, Oracle, mongodb, jenkins, nginx, Drupal, rabbitmq e tanti altri trovate già tutto pronto, di sicuro una base di partenza molto comoda per le vostre personalizzazioni!

Se ciò non bastasse, Ansible ha una API estremamente chiara e flessibile per scrivere moduli custom in Python o qualsiasi altro linguaggio, un esempio concreto qui: http://www.rohit.io/blog/contributing-to-ansible-is-super-easy.html

Ultimo link ma più importante di tutti, l’ottima documentazione, reperibile su http://docs.ansible.com/

Buona automazione!

Info about author

Andrea Manzini