Introducción a Ansible 2 – vol.2

Ansible

Avanzando con Ansible

Variables

En el post anterior pudimos ver cómo un playbook era capaz de instalar y configurar un servidor Apache, y abrir los puertos necesarios en el firewall. Si quisieramos instalar un servidor ftp tendríamos que crear un nuevo playbook; pero gracias a las variables vamos a ver como reaprovechar nuestro playbook.

Este es el playbook original:

$ cat playbooks/prepare-WebServers.yaml
---
- name: Install and configure webservers services
  hosts: webservers
  remote_user: centos
  become: True
  tasks:

  - block:
    - name: Install Apache package
      yum:
        name: httpd 
        state: installed
    - name: Install Firewalld package
      yum:
        name: firewalld
        state: installed

  - block:
    - name: Start and enable Apache service
      service:
        name: httpd
        enabled: true
        state: started
    - name: Start and enable Firewalld service
      service:
        name: firewalld
        enabled: true
        state: started

  - block:
    - name: Enable firewall rules for Apache
      firewalld:
        state: enabled
        service: http
        permanent: true
        immediate: true

  - block:
    - name: create index file
      shell: echo 'Hello World!' > /var/www/html/index.html
...

VARIABLES

Gracias al uso de variables podemos externalizar los valores de ciertos componentes. Por ejemplo, es posible que en lugar del servidor web basado en Apache, queramos optar por instalar NGINX.

Para evitar modificar el playbook, podemos hacer uso de variables. Estas variables pueden estar definidas a distintos niveles, que aquí expongo en orden de precedencia, desde el más bajo, al más alto. NOTA: No todos los nivele están aquí definidos, sólo los más importantes:

  • inventory_dir/group_vars/all
  • playbook_dir/group_vars/all
  • inventory_dir/group_vars/*
  • playbook_dir/group_vars/*
  • inventory_dir/host_vars/*
  • playbook_dir/host_vars/*
  • play vars
  • play vars_files
  • role vars
  • block vars
  • task vars
  • include_vars
  • extra vars (opción –extra-vars|-e en la línea de comandos)
GROUP_VARS y HOST_VARS

Los directorios group_vars y host_vars, definidos a nivel de inventario o playbook, permiten especificar un conjunto de variables que se aplicarán a hosts o grupos de hosts respectivamente. La idea principal es definir en estos directorios aquellas variables “estándar” tanto para un host como para un grupo. Ansible define como buena práctica:

A lot of folks may ask about how variables override another. Ultimately it’s Ansible’s philosophy that it’s better you know where to put a variable, and then you have to think about it a lot less.

Avoid defining the variable “x” in 47 places and then ask the question “which x gets used”. Why? Because that’s not Ansible’s Zen philosophy of doing things.

There is only one Empire State Building. One Mona Lisa, etc. Figure out where to define a variable, and don’t make it complicated.

O lo que es lo mismo, evita definir una variable en multiples sitios, defínela sólamente donde tenga que afectar!!

Por tanto vamos a configurar la posibilidad de que el paquete del webserver esté en una variable, y así cambiar su valor sin modificar el playbook

$ cat playbooks/group_vars/webservers.yaml
---
packages: nginx
services: http
...
$ cat playbooks/prepare-WebServers.yaml
---
- name: Install and configure webservers services
  hosts: webservers
  remote_user: centos
  become: True
  tasks:

  - block:
    - name: Install WebServer package
      yum:
        name: "{{ package }}"
        state: installed
    - name: Install Firewalld package
      yum:
        name: firewalld
        state: installed

  - block:
    - name: Start and enable Apache service
      service:
        name: "{{ services }}"
        enabled: true
        state: started
    - name: Start and enable Firewalld service
      service:
        name: firewalld
        enabled: true
        state: started

  - block:
    - name: Enable firewall rules for Apache
      firewalld:
        state: enabled
        service: http
        permanent: true
        immediate: true

  - block:
    - name: create index file
      shell: echo 'Hello World!' > /var/www/html/index.html
...

Iteraciones básicas

Otra de las funcionalidades que podemos encontrar en los playbooks de Ansible son las iteraciones, que nos permitiarán ejecutar una tarea n veces, con valores distintos. Para ello usaremos la instrucción with_items que recibirá una lista por la cual iterar, y generará una variable item, con ámbito de tarea, que tendrá el valor de la iteración.

En este ejemplo tomaré sólo la task de instalar paquetes, y realizaré una iteración sobre dos paquetes, httpdfirewalld. De ese modo evitaremos escribir una task repetida, facilitando la lectura y simplificación del playbook.

    - name: Install packages
      yum:
        name: "{{ item }}"
        state: installed
      with_items:
        - httpd
        - firewalld

También es posible pasar variables como los elementos de la iteración:

$ cat playbooks/group_vars/webservers
---
packages:
  - httpd
  - firewalld
...

$ cat playbooks/prepare-WebServers.yaml
    - name: Install packages
      yum: 
        name: "{{ item }}" 
        state: installed 
      with_items: 
        - "{{ packages }}"

Registrando variables

Ansible permite registrar los valores retornados por una tarea en una variable, de ese modo podemos trabajar con ellos desde otra tarea. Dependiendo de el módulo de ansible usado, la variable guardará distintos valores. La palabra clave en este caso es register

Veamos el siguiente ejemplo y posteriormente lo analizamos.

$ cat playbooks/test-Register.yaml
 tasks:
 - block:
   - name: Register date
     command: date
     register: date_registered
 
 - block:
   - name: Check
     debug:
       var: date_registered

El resultado sería este.

ok: [localhost] => {
"date_registered": {
"changed": true,
"cmd": [
"date"
],
"delta": "0:00:00.106724",
"end": "2017-04-07 08:03:11.264052",
"rc": 0,
"start": "2017-04-07 08:03:11.157328",
"stderr": "",
"stdout": "Fri Apr 7 08:03:11 UTC 2017",
"stdout_lines": [
"Fri Apr 7 08:03:11 UTC 2017"
],
"warnings": []
}
}

Analizando el resultado, podremos usar los valores  en otras tareas, ya que estarán definidos como elementos dentro de un objeto.

Un ejemplo, muy simple, sería mostrar sólo la fecha del sistema, por ello usaré el elemento stdout_lines del objeto date_registered.

$ cat playbooks/test-Register.yaml
 tasks:
 - block:
   - name: Register date
     command: date
     register: date_registered
 
 - block:
   - name: Check
     debug:
       var: date_registered.stdout_lines

Condicionales

No sólo podemos usar las variables parametrizando el valor de ciertos elementos de las tareas, también podemos usar las variables para condicionar la ejecución de otras tareas. Para ello usaremos la directiva when

Por ejemplo, podemos tener una tarea que cree el fichero index.html si hemos decidido instalar el paquete httpd.

$ cat playbooks/group_vars/webservers
---
packages:
  - httpd
  - firewalld
...
$ cat playbooks/prepare-WebServers.yaml
    - name: Create index.html if httpd is in packages
      copy: 
        dest: /var/www/html/index.html
        force: no
        content: |
          <html>
            <body>
              <h1>Hello World!</h1>
            </body>
          </html> 
      with_items: "{{ packages }}"
      when: item == 'httpd'

 

 

Y hasta aquí. Creo que para ser el Volumen 2 de este tutorial, he avanzado bastante. Nos vemos!!

One thought on “Introducción a Ansible 2 – vol.2

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.