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, httpd y firewalld. 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!!
Fácil, escueto y didáctico, así da gusto leer, y aprender un poco, muchas gracias