Hace aproximadamente dos años que empecé a trabajar con Ansible. Desde ese día después de usar algo de chef/puppet y darme cabezazos contra la pared (dada su complejidad), este stack se ha convertido en mi preferido, por lo sencillo que es. No es tan completo como los anteriormente comentados, pero para mis necesidades cumple perfectamente.
Durante este tiempo han sido muchas las cosas que he aprendido, de las cuales me parece bueno salientar:
Registro de variables
Cada tarea tiene un resultado, muchas veces creemos que no nos dan un resultado que no sea True/False. Pero muchos módulos devuelven mucha información en un objeto json. En el código fuente de los módulos se pueden buscar que info es la que exporta. Para poder utilizarla solo debemos hacer lo siguiente en nuestro playbook:
- command: cat /etc/hostname register: my_var - debug: msg="Hostname == {{my_var.stdout}} Command start at {{my_var.start}}"
Condicionales
Las condiciones es una de las partes más sencillas de Ansible. Pero lo mejor que este sistema tiene es la capacidad de hacer condicionales con expresiones de python, lo que nos permite validar en una sola línea:
Usando variables internas de ansible:
- include: debian.yml when: ansible_os_family == "Debian" - include: network.yml when: ansible_eth0.active
Usando expresiones string de python:
- include: debian.yml when: "'Debian' in my_var.stdout" - include: debian.yml when: my_var.stdout.find("Debian") =>= 1 - include: debian.yml when: my_var.stdout.lower() == 'debian'
Debug
Suele ser útil mostrar debug en un formato legible. La función debug es una gran desconocida pero hace justo lo que deseamos:
- debug: msg="System {{ inventory_hostname }} with IP: {{ansible_eth0.ipv4}} is ready"
pre_task y post_task
Nosotros por ejemplo tenemos muchos roles en repositorios separados y usamos git-submodules. De esta manera compartimos muchos de los roles (Asterisk, Kamailio, Postgresql) por lo que muchas veces antes de ejecutar el rol, tenemos que ejecutar una serie de tareas propias del proyecto, para ello nuestros playbooks lucen así:
- name: apply asterisk config hosts: prod gather_facts: yes user: root vars_files: - vars/prod.yml - vars/ha.yml roles: - asterisk post_task: - name: Add configs template: src=src/{{item}}.j2 dest=/etc/asterisk/{{item}}.conf mode=0444 with_items: - extensions - sip - features
Callbacks
Personalmente esta es una de las funciones más interesantes que hay en Ansible. Cada vez que el playbook o tarea acaba podemos definir una serie de callbacks y obtener información de la misma.Yo las suelo usar para enviar un resumen a nuestro xmpp de cuantas tareas se ejecutaron con cambios, la hora de los cambios y el resultado:
class CallbackModule(object): def playbook_on_stats(self, stats): do_stuff()
Test
Una de las cosas que me falta en Ansible es una solución 100% opensource como Tower. Tower no es caro, pero en nuestro caso, no es necesario este sistema. Una de las mejoras que hemos implementado es cada vez que se hace un push al server, Jenkins ejecuta un dry-run y ver el resultado de la siguiente manera:
ansible-playbook -i host playbook.yml -C
Con lo que tenemos una lista de resultados que se van a ejecutar en la máquina. En el caso de que existan cambios tengo una mini APP que nos notifica que estan pendiente cambios sin aplicar.
Finalmente estas son las funciones que nunca ves en los ejemplos pero que son muy útiles a la hora de desarrollar y hacer despliegues en entornos de producción, pruebas y desarrollo. Yo tengo el 90% de mis servidores basados en Ansible y cada día que pasa estoy más alegre de utilizarlo. ;-)