Ansible: automazione IT, KISS

di Andrea Scarpino


Linux Day Bari 2016 - 22/10/2016

“Ansible is Simple IT Automation”
“AUTOMATION FOR EVERYONE
“Deploy apps. Manage systems. Crush complexity

“Automazione”, ovvero?

  • Provisioning
  • Gestione dele configurazioni
  • Deploy delle applicazioni
  • Continuous delivery
  • Aggiornamenti di sicurezza
  • Orchestring

Perché Ansible?

  • Free and Open Source Software
  • Nessun agente sui server
  • Bassa curva d'apprendimento
  • 774 moduli di default
  • Forte community (Ansible Galaxy)

Installazione

Ubuntu/Debian:

$ sudo apt-get install ansible
CentOS/Fedora:
# yum install ansible
Arch Linux:
# pacman -S ansible
tramite pip:
# pip install ansible

Requisiti dei server

Linux:
Python 2.7.x; connessione tramite SSH

Windows:
PowerShell >= 3; connessione tramite WinRM

Test della connessione

$ cat inventory
linux.local ansible_user=andrea
day.local ansible_port=2016
bari.local ansible_password=winzoz ansible_connection=winrm
$ ansible all -i inventory -m ping
linux.local | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
day.local | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh.",
    "unreachable": true
}

Installare un pacchetto

ansible -i inventory all -b -m yum -a name=nginx
linux.local | SUCCESS => {
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed:\n  nginx.x86_64 1:1.10.1-1.el7\nComplete!"
    ]
}
ansible -i inventory all -b -m yum -a name=nginx
linux.local | SUCCESS => {
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "nginx-1.10.1-1.el7.x86_64 providing nginx is already installed"
    ]
}

I playbook

- hosts: all
  tasks:
    - name: Assicurati che nginx sia installato
      package: name=nginx
    - name: Assicurati che nginx sia avviato
      service: name=nginx enabled=yes state=started
    - name: Check if firewalld is used
      stat: path=/usr/sbin/firewalld
      register: firewalld
    - name: Assicurati che la porta 80 sia aperta
      firewalld: port=80/tcp state=enabled immediate=yes permanent=yes
      when: firewalld.stat.exists
    - name: Assicurati che la porta 80 sia aperta
      iptables: chain=INPUT protocol=tcp match=tcp destination_port=80 jump=ACCEPT
      when: not firewalld.stat.exists

I playbook (continua)

$ ansible-playbook -i inventory nginx.yml
PLAY [all] ****************************************
TASK [setup] **************************************
ok: [linux.local]
TASK [Assicurati che nginx sia installato] ********
ok: [linux.local]
TASK [Assicurati che nginx sia avviato] ***********
ok: [linux.local]
TASK [Check if firewalld is used] *****************
ok: [linux.local]
TASK [Assicurati che la porta 80 sia aperta] ******
changed: [linux.local]
TASK [Assicurati che la porta 80 sia aperta] ******
skipping: [linux.local]
PLAY RECAP ****************************************
linux.local : ok=5 changed=1 unreachable=0 failed=0

Variabili

- hosts: all
  vars:
    users:
     - nome: nicola
       ruolo: "Full stack developer"
     - nome: vito
       ruolo: "Frontend developer"
  tasks:
   - name: Crea gli utenti e aggiungili al gruppo developers
     user: name="{{ item.nome }}" comment="{{ item.ruolo | default() }}"
     with_items: "{{ users }}"
$ cat host_vars/linux.local.yml
users:
 - nome: nicola
   ruolo: "Full stack developer"
$ cat group_vars/all.yml
users:
 - nome: nicola
   ruolo: "Full stack developer"

Templates

- name: Installa la configurazione nginx
  template: src=nginx.conf.j2 dest="/etc/nginx/conf.d/{{ item.nome }}"
  with_items: "{{ users }}"
$ cat templates/nginx.conf.j2
server {
    listen 80;

    location / {
        root   /srv/http/{{ item.nome }};
        index  index.html;
    }
}

Handlers

 handlers:
- name: Riavvia nginx
  service: name=nginx state=restarted
- name: Installa la pagina di default
  copy: src=index.html dest="/srv/http/{{ item.nome }}"
  with_items: "{{ users }}"
  notify: Riavvia nginx

Filtri Jinja2

  • {{ variable | mandatory }}
  • {{ variable | default("foo") }}
  • {{ variable | to_json }}
  • {{ lista | min }}
  • {{ lista | random }}
  • {{ path | basename }}
  • {{ path | splitext }}
  • {%for u in users%}{{u}}{%endfor%}

Gestione degli errori

  • - name: Installa nginx con yum
      yum: name=nginx
      ignore_errors: True
  • - name: Installa nginx con yum
      yum: name=nginx
      register: comando
      failed_when: "'Failed' in comando.stdout"
  • tasks:
     - block:
       - name: Installa nginx con yum
         yum: name=nginx
       rescue:
       - name: Trova da solo il package manager
         package: name=nginx

I ruoli

$ cat playbook.yml
- hosts: all
  roles:
   - nginx
$ tree nginx
nginx
├── defaults
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars

References




Andrea Scarpino

Software Developer involved in FOSS

https://andreascarpino.it

@ilpianista_ | git{hub,lab}.com/ilpianista