Ansible Playbooks: Tutorial p2

Bienvenido a la segunda parte y final de este tutorial. En la primera parte hicimos una introducción a lo que eran los Playbooks, en este artículo veremos opciones más avanzadas para usar todo el poder de los Playbooks.

Escribiendo Playbooks

Variables

Hay varias formas en que se pueden definir variables en Ansible. La forma más simple es usar la sección vars de un playbook. El siguiente ejemplo define una variable llamada package que posteriormente usamos en una task:

1
2
3
4
5
6
7
8
---
- hosts: all
  become: true
  vars:
     package: vim
  tasks:
     - name: Install Package
       apt: name= state=latest

La variable package se puede usar en cualquier punto del provisionamiento, incluso en archivos y templates.

Loops

Loops se usan para ejecutar una tarea que se repite usando diferente valores de entrada. Por ejemplo en vez de crear 10 tasks para instalar 10 paquetes diferentes, puedes crear una sola task y luego usar un loop para repetir la tarea con todos los paquetes diferentes que necesitas instalar.

Para crear un loop en una tarea, se debe usar la opción with_items con un arreglo de valores. El contenido del arreglo se usa en el loop con la variable llamada item, como se muestra en el siguiente ejemplo:

1
2
3
4
5
6
- name: Install Packages
  apt: name= state=latest
  with_items:
     - vim
     - git
     - curl  

También puedes usar una variable para el array para definir los ítemes:

1
2
3
4
5
6
7
8
9
---
- hosts: all
  sudo: true
  vars:
     packages: [ 'vim', 'git', 'curl' ]
  tasks:
     - name: Install Package
       apt: name= state=latest
       with_items: packages

Condicionales

Los condicionales se pueden usar para decidir de forma dinámica si una tarea se debe ejecutar o no, basado en el valor de una variable o del resultado de un comando.

En el siguiente ejemplo se muestra una task que sólo se ejecutará en sistemas Debian:

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

El condicional when recibe un argumento o una expresión que se debe evaluar. La task solo se ejecuta en caso de que la expresión sea verdadera. En el ejemplo, nosotros revisamos el fact de que el sistema operativo fuera de la familia Debian.

Un uso común de los condicionales en automatización TI es cuando la ejecución de una task depende del resultado de un comando. Con Ansible, la forma de implementar esto es registrando una variable para contener el resultado de la ejecuión del comando, y luego revisar esta variable en las siguientes tasks. Se puede revisar el estado de salida del comando (si falló o se ejecutó bien). También podemos revisar por contenidos específicos del resultado del comando , lo cual puede necesitar que usemos regex.

El siguiente ejeplo muestra dos tareas condicionales que dependen del resultado del comando php -v. Comprobaremos el status de ejecución, ya que fallará si PHP no está instalado en el servidor. La opción ignore_errors se necesita para asegurarnos que el provisionamiento continue incluso cuando el comando falla su ejecución.

1
2
3
4
5
6
7
8
9
10
11
12
- 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

El módulo debug es útil para mostrar los contenidos de una variable o mensajes de depuración. Puede imprimir un texto (cuando se usa el argumento msg) o imprimir en contenido de una variable (cuando se usa el argumento var).

Templates

Los templates se usan típicamente para archivos de configuración, permitiendo el uso de variables y otras características que permiten hacer estos archivos más versátiles y re-utilizables. Ansible usa el motor Jinja2.

Abajo hay un ejemplo del uso de un template para configurar un host virtual en Apache, usando una variable para configurar el document root:

1
2
3
4
5
6
7
8
9
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot 

    <Directory >
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

El módulo template se usa para aplicar el template desde una task. Si llamamos el archivo de template vhost.tpl, y lo dejas en el mismo directorio del playbook, se aplica como se muestra a continuación:

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

Triggers Handlers

Handlers se usan para ejecutar un cambio en el estado de un servicio, como iniciar o detener. Los Handlers funcionan de forma similar a las tasks, ejecutándose en el mismo orden en que se definieron, aunque sólo se ejecutan si y sólo si se gatillan usando la directiva notify en una task. Los Handlers generalmente se definen como un arreglo en la sección handlers de un playbook.

Vamos a usar el ejemplo anterior de templates, donde configuramos un hos virtual de Apache. Si te quieres asegurar de que Apache es re-iniciado cada vez que se cambia un host virtual, lo primero que necesitas es crear un handler para el servicio Apache. Así se definen los handlers en el playbook:

1
2
3
4
5
6
handlers:
    - name: restart apache
      service: name=apache2 state=restarted

    - name: other handler
      service: name=other state=restarted

La directiva name es importante porque es el único identificador de este handler. Para gatillar este handler desde una task, debes usar la opción notify:

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

Playbook de ejemplo

Ahora vamos a revisar un playbook que automatizará la instalación del servidor web Apache en un sistema Ubuntu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---
- hosts: all
  become: true
  vars:
    doc_root: /var/www/example
  tasks:
    - name: Update apt
      apt: update_cache=yes

    - name: Install Apache
      apt: name=apache2 state=latest

    - name: Create custom document root
      file: path= state=directory owner=www-data group=www-data

    - name: Set up HTML file
      copy: src=index.html dest=/index.html owner=www-data group=www-data mode=0644

    - name: Set up Apache virtual host file
      template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
      notify: restart apache
  handlers:
    - name: restart apache
      service: name=apache2 state=restarted

Explicación del Playbook

hosts: all

El playbook comienza indicando que se debe ejecutar en todos (all) los hosts de tu inventario. Es posible segmentarlo a un grupo o host específico.

become: true

Esto le dice a Ansible que use sudo para ejecutar todas las tareas del playbook.to use privilege escalation (sudo) for executing all the tasks in this playbook.

vars

Define una variable, doc_root, que más tarde se usa en una tarea. Esta sección puede tener múltiples variables.

tasks

Esta sección es donde las tareas son definidas. La primera actualiza el caché de apt, y la segunda instala el paquete apache2.

La tercera tarea usa el módulo file para crear el directorio que se usará como document root. Este módulo se usa para administrar tanto archivos como directorios.

La cuarta tarea usa el módulo copy para copiar un archivo local al servidor remoto. Estamos copiando un simple archivo HTML.

handlers

Finalmente tenemos la sección handlers, donde se declaran los servicios. Aqui definimos un handler que reinicia apache cuando se notifica en la cuarta tarea, donde se aplica el template.

Conclusión

Ansible es una herramienta minimalista de automaticación que tiene una muy baja curva de aprendizaje y entrega muchos beneficios con un muy bajo costo.

En IT Linux usamos Ansible para todo, desde la administración de nuestros servidores, pasando por el soporte de nuestros clientes hasta la configuración de nuestros propios equipos.

Esperamos que le saques provecho ha estas guías.

Comentarios