Variables y facts 📊
Haciendo nuestros playbooks dinámicos y reutilizables.
6.1. Definición de variables
Las variables son la clave para escribir playbooks que funcionen en cualquier entorno (desarrollo, staging, producción) sin cambiar ni una línea de código.
🚫 La regla de oro: no hardcodear
Nunca escribas valores fijos (IPs, nombres de usuario, rutas) directamente en tus tareas. Si lo haces, tendrás que editar el Playbook cada vez que algo cambie.
📂 Estructura de carpetas: group_vars y host_vars
Ansible busca automáticamente variables en carpetas específicas. Esta es la forma profesional de organizar tus datos.
Estructura recomendada del proyecto:
proyecto/
├── inventory.ini
├── playbook.yml
├── group_vars/
│ ├── all.yml # Variables para TODOS los servidores
│ ├── webservers.yml # Variables solo para el grupo webservers
│ └── dbservers.yml # Variables solo para el grupo dbservers
└── host_vars/
└── web01.empresa.com.yml # Variables específicas para UN host
Ejemplo Práctico
group_vars/webservers.yml:
http_port: 80
doc_root: /var/www/html
playbook.yml:
- hosts: webservers
tasks:
- name: Configurar VirtualHost
template:
src: vhost.j2
dest: "/etc/nginx/sites-available/default"
# Usamos la variable {{ http_port }} en lugar de escribir 80
6.2. Ansible Facts
Ansible no va a ciegas. Antes de ejecutar cualquier tarea, "interroga" al servidor para conocer su estado actual. Esta información se guarda en variables automáticas llamadas Facts.
🩺 La Analogía: El Chequeo Médico
Imagina que vas al médico. Antes de recetarte nada, la enfermera te toma la temperatura, la presión y el peso.
- Médico: Ansible.
- Paciente: Servidor.
- Signos Vitales: Facts (IP, Sistema Operativo, Memoria RAM, Discos).
El médico (Ansible) usa esos datos para decidir el tratamiento (Playbook). Si eres alérgico a la penicilina (es un servidor RedHat), te dará otro medicamento (yum en vez de apt).
Variables Mágicas Comunes
ansible_os_family: Debian, RedHat, Windows.ansible_processor_vcpus: Número de CPUs.ansible_memtotal_mb: Memoria total.ansible_default_ipv4.address: Dirección IP principal.ansible_hostname: Nombre del host.ansible_distribution: Distribución específica (Ubuntu, CentOS, etc.).ansible_distribution_version: Versión de la distribución.
🧪 Práctica: Playbook Inteligente (Cross-Platform)
Vamos a crear un Playbook que funcione tanto en Ubuntu (Debian) como en CentOS (RedHat) usando Facts y condicionales.
- name: Instalar Servidor Web Inteligente
hosts: all
become: yes
tasks:
- name: Mostrar familia del SO
debug:
msg: "Este servidor es de la familia: {{ ansible_os_family }}"
# Caso 1: Si es Debian/Ubuntu
- name: Instalar Apache en Debian/Ubuntu
apt:
name: apache2
state: present
when: ansible_os_family == "Debian"
# Caso 2: Si es RedHat/CentOS
- name: Instalar Apache en RedHat/CentOS
yum:
name: httpd
state: present
when: ansible_os_family == "RedHat"
6.3. Register: Capturando Resultados
La directiva register te permite capturar la salida de una tarea y guardarla en una variable para usarla después.
💾 ¿Para qué sirve?
- Guardar el resultado de un comando shell.
- Verificar si un servicio está corriendo.
- Tomar decisiones basadas en salidas previas.
Ejemplo Práctico
- name: Ejemplo de Register
hosts: localhost
tasks:
- name: Ejecutar comando y guardar resultado
shell: uptime
register: uptime_result
- name: Mostrar el resultado
debug:
msg: "Tiempo de actividad: {{ uptime_result.stdout }}"
- name: Verificar si un archivo existe
stat:
path: /etc/nginx/nginx.conf
register: nginx_config
- name: Tarea condicional según resultado
debug:
msg: "Nginx está configurado"
when: nginx_config.stat.exists
Estructura de una variable registrada
Una variable register contiene varios atributos útiles:
stdout: Salida estándar del comando.stderr: Salida de error.rc: Código de retorno (0 = éxito).changed: Indica si hubo cambios.failed: Indica si la tarea falló.
6.4. Variables Especiales
Ansible proporciona variables especiales que siempre están disponibles:
Variables de Inventario
inventory_hostname: Nombre del host según el inventario.inventory_hostname_short: Nombre del host sin el dominio.inventory_dir: Ruta del directorio del inventario.inventory_file: Nombre del archivo de inventario.groups: Diccionario con todos los grupos del inventario.group_names: Lista de grupos a los que pertenece el host actual.
Variables de Ansible
ansible_check_mode: True si se ejecuta en modo check (--check).ansible_play_hosts: Lista de hosts en el play actual.ansible_version: Información de la versión de Ansible.ansible_facts: Diccionario con todos los facts recopilados.
Ejemplo de Uso
- name: Variables Especiales en Acción
hosts: webservers
tasks:
- name: Mostrar información del host
debug:
msg: |
Host: {{ inventory_hostname }}
Grupos: {{ group_names }}
IP: {{ ansible_default_ipv4.address }}
SO: {{ ansible_distribution }} {{ ansible_distribution_version }}
- name: Listar todos los hosts del grupo
debug:
msg: "Hosts en webservers: {{ groups['webservers'] }}"
6.5. Precedencia de Variables
¿Qué pasa si defines la variable http_port en el inventario, en group_vars y además la pasas por línea de comandos? ¿Cuál gana?
🏆 La Pirámide de Poder
Ansible tiene una jerarquía estricta. La regla general es: "Lo más específico gana a lo más general".
El Ranking (Simplificado)
- Extra Vars (
-e): ¡GANADOR ABSOLUTO! Sobrescribe todo. - Playbook Vars: Variables definidas dentro del archivo
.yml. - Host Vars: Variables específicas de un host (
host_vars/). - Group Vars: Variables de grupo (
group_vars/). - Defaults: Valores por defecto en roles (los más débiles).
🥊 Ejemplo de Conflicto
1. En group_vars/webservers.yml:
http_port: 80
2. En playbook.yml:
vars:
http_port: 8080
3. Ejecución en terminal:
ansible-playbook site.yml -e "http_port=9090"
Resultado Final: El puerto será 9090.
- ¿Por qué? Porque
-e(Extra Vars) tiene la máxima prioridad. - Si no hubiéramos usado
-e, sería 8080 (Playbook gana a Group). - Si borramos la variable del Playbook, sería 80 (Group vars).
Resumen
Entender la precedencia te evitará horas de depuración preguntándote "¿Por qué no cambia este valor?". Usa group_vars para lo general, host_vars para excepciones, y -e solo para pruebas rápidas o overrides manuales en tiempo de ejecución.