Ansible¶
6. Un playbook real: despliegue de servidor web¶
6.1 Objetivo y planteamiento¶
En esta sección se construirá un playbook completo que instala Apache en los nodos gestionados, clona un sitio web desde un repositorio Git y lo deja sirviendo. El playbook se irá construyendo de forma incremental: cada apartado introduce un concepto nuevo que se integra en el mismo playbook. Al final se dispondrá de algo funcional y representativo de lo que se hace en entornos reales.
El punto de partida es el mínimo que cumple el objetivo: instalar Apache, clonar el repositorio y arrancar el servicio.
El módulo git
El módulo git clona el repositorio si el directorio de destino no existe o no es un repositorio
Git, y lo actualiza si ya está clonado. Con update: yes (valor por defecto) y force: true,
Ansible garantiza que el contenido del servidor siempre coincide con el repositorio,
descartando cualquier cambio local. Es necesario que git esté instalado en los nodos
gestionados, de ahí que se incluya en la tarea de instalación.
Este playbook ya funciona, pero tiene un problema evidente: las rutas, el nombre del servicio y la URL del repositorio están escritas literalmente en el código. Si mañana se quiere cambiar el repositorio o el directorio de destino, hay que editar el playbook buscando cada ocurrencia. Las variables resuelven esto.
6.2 Variables¶
Las variables permiten separar los valores concretos de la lógica del playbook. Se definen en la
sección vars del play y se referencian en las tareas usando la sintaxis de Jinja2: {{ nombre_variable }}.
El playbook hace exactamente lo mismo que antes, pero ahora cualquier cambio se hace en un único
lugar: la sección vars. Esto es especialmente valioso cuando el mismo valor aparece en varias tareas.
Las comillas con Jinja2
Cuando el valor de un argumento YAML empieza directamente por {{, hay que entrecomillarlo:
dest: "{{ web_root }}". Sin las comillas, YAML interpreta {{ como inicio de un
diccionario y produce un error. Si la variable va en medio de una cadena no es necesario:
dest: /srv/{{ web_root }}/html.
Otras fuentes de variables
Las variables pueden definirse en muchos otros sitios además de vars: en el inventario (como se
vio en el apartado 4.3), en archivos externos, pasadas por línea de comandos con -e, o generadas
automáticamente por Ansible como los facts. La precedencia entre todas estas fuentes tiene sus
reglas, que se verán más adelante.
6.3 Condicionales: when¶
A veces interesa que una tarea solo se ejecute si se cumple cierta condición. Para eso existe when,
que acepta una expresión Jinja2 que Ansible evalúa antes de ejecutar la tarea.
Un caso habitual es actuar sobre un servicio solo si se sabe que existe en el sistema. El módulo
service_facts recopila información sobre todos los servicios del nodo y la almacena en
ansible_facts.services. Combinado con when, permite tomar decisiones basadas en el estado real
del sistema:
La condición (servicio ~ '.service') in ansible_facts.services construye el nombre completo del
servicio (apache2.service) usando el operador de concatenación de Jinja2 (~), y comprueba si
existe en la lista de servicios conocidos. Solo si es así se ejecuta la tarea.
¿Por qué apache2.service y no apache2?
service_facts almacena los servicios con su nombre completo de systemd, incluyendo la extensión
.service. Buscar solo apache2 no encontraría ninguna coincidencia.
when acepta múltiples condiciones
when puede combinar varias condiciones mediante and y or:
También puede escribirse como una lista. En ese caso todas las condiciones deben cumplirse como un and implícito:
6.4 register y debug¶
register captura el resultado de una tarea en una variable, que luego puede consultarse, mostrarse
o usarse en condiciones. debug permite mostrar mensajes o el valor de variables durante la ejecución,
lo que resulta muy útil para entender qué está ocurriendo o para depurar.
Se añaden ambos al playbook para mostrar si el repositorio ha cambiado desde la última ejecución:
La variable resultado_git contiene toda la información que el módulo git devuelve sobre lo que
ha hecho. La propiedad .changed es común a todos los módulos: vale true si la tarea realizó
algún cambio, false si el sistema ya estaba en el estado correcto.
Explorar el contenido de register
Para ver todo lo que contiene una variable registrada, se puede usar debug con var en lugar
de msg:
6.5 Tags¶
Los tags permiten etiquetar tareas y ejecutar selectivamente solo las que tengan una etiqueta concreta. Son útiles cuando el playbook tiene muchas tareas y solo se quiere aplicar una parte: por ejemplo, solo el despliegue del código sin reinstalar paquetes.
Además, como se mencionó en el apartado anterior, el módulo git gestiona tanto la clonación
inicial como las actualizaciones posteriores. Sin embargo, puede darse la situación en que se
necesite partir de cero: borrar el contenido desplegado y volver a clonar desde el repositorio.
Para eso se añade una tarea con el tag especial never, que garantiza que no se ejecutará en
condiciones normales y solo cuando se pida explícitamente:
Para ejecutar solo las tareas con un tag concreto se usa --tags:
| Ejemplos | |
|---|---|
Para ejecutar todo excepto las tareas con un tag determinado, --skip-tags:
| Ejemplo | |
|---|---|
Y para forzar una reinstalación limpia, combinando el tag reset con despliegue:
| Reinstalación limpia | |
|---|---|
Tags especiales
Ansible reserva dos tags con comportamiento especial:
always: la tarea se ejecuta siempre, aunque se use--tagscon otro valor.never: la tarea nunca se ejecuta salvo que se pida explícitamente con--tags nevero con el nombre de otro tag que también tenga asignado, comoreseten el ejemplo anterior.
6.6 Handlers¶
Un handler es una tarea especial que solo se ejecuta si ha sido notificada por otra tarea, y
únicamente cuando esta ha producido un cambio. Se definen en la sección handlers del play, al
mismo nivel que tasks.
El caso de uso más habitual es reiniciar o recargar un servicio cuando cambia su configuración o
su contenido. Con un handler, la recarga solo ocurre cuando git detecta commits nuevos:
La palabra clave notify en la tarea git le dice a Ansible que, si esa tarea produce un cambio,
dispare el evento Recargar Apache. Todos los handlers que tengan ese nombre o lo escuchen mediante
listen se ejecutarán en orden al final del play.
La palabra clave listen permite a un handler suscribirse a un evento sin necesidad de llamarse
igual que el notify que lo dispara. En este caso el segundo handler usa listen: "Recargar Apache"
para ejecutarse junto al primero y confirmar mediante debug que la recarga ha tenido lugar.
Comportamiento de los handlers
Tres propiedades importantes a tener en cuenta:
- Si una tarea notifica un handler pero no produce ningún cambio (
changed=false), el handler no se ejecuta. - Si varias tareas notifican el mismo handler, este se ejecuta una sola vez al final, no una vez por cada notificación.
listenpermite agrupar varios handlers bajo un mismo evento, lo que en proyectos grandes ayuda a desacoplar quién notifica de quién reacciona.
6.7 El playbook completo¶
El resultado final, reproducido aquí como referencia:
Para ejecutarlo:
| Ejecución completa | |
|---|---|
| Solo instalar paquetes | |
|---|---|
| Solo desplegar o actualizar el sitio | |
|---|---|
| Reinstalación limpia desde cero | |
|---|---|
| Simulación sin aplicar cambios | |
|---|---|
📅 Documento escrito el 01/06/2026 · Última revisión: 02/07/2026 · Versión: v1.0