Ansible es una herramienta de automatización de TI de código abierto que proporciona orquestación simple, gestión de configuraciones, implementación de aplicaciones y aprovisionamiento.
Ansible sigue una arquitectura cliente-servidor sin agentes:
Nota: Ansible se comunica con los nodos gestionados a través de SSH (para sistemas Unix/Linux) o WinRM (para Windows).
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
sudo yum install epel-release
sudo yum install ansible
python3 -m pip install --user ansible
ansible --version
Deberías ver información sobre la versión instalada.
El inventario es un archivo que define los hosts y grupos de hosts que Ansible gestionará.
Por defecto, Ansible busca el inventario en /etc/ansible/hosts
, pero puedes especificar otro archivo con la opción -i
.
[webservers]
web1.example.com
web2.example.com ansible_port=2222 ansible_user=admin
[dbservers]
db1.example.com
db2.example.com
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Puedes asignar variables a hosts o grupos:
[webservers:vars]
http_port=80
max_connections=200
[dbservers:vars]
db_port=3306
Ansible puede obtener inventarios de fuentes dinámicas como AWS EC2, Azure, etc.
# Ejemplo de script de inventario dinámico para AWS
#!/usr/bin/env python3
import json
import boto3
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
inventory = {
'webservers': {
'hosts': [],
'vars': {}
},
'_meta': {
'hostvars': {}
}
}
for instance in instances:
for tag in instance.tags or []:
if tag['Key'] == 'Role' and tag['Value'] == 'web':
inventory['webservers']['hosts'].append(instance.public_dns_name)
inventory['_meta']['hostvars'][instance.public_dns_name] = {
'ansible_user': 'ubuntu',
'ansible_ssh_private_key_file': '~/keys/web-key.pem'
}
print(json.dumps(inventory))
Los comandos ad-hoc permiten ejecutar tareas simples sin necesidad de crear un playbook.
ansible [grupo] -m [modulo] -a "[argumentos]"
ansible all -m ping
ansible all -m setup
ansible webservers -m apt -a "name=nginx state=present" --become
ansible dbservers -m command -a "/sbin/reboot" --become
ansible webservers -m copy -a "src=/local/path/file.conf dest=/remote/path/file.conf"
Los playbooks son archivos YAML que describen políticas de configuración y pasos de implementación.
---
- name: Configurar servidor web
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: Instalar paquete nginx
apt:
name: nginx
state: present
- name: Iniciar servicio nginx
service:
name: nginx
state: started
enabled: yes
- name: Configurar sitio web
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify:
- reiniciar nginx
handlers:
- name: reiniciar nginx
service:
name: nginx
state: restarted
Componente | Descripción |
---|---|
name | Descripción del playbook o tarea |
hosts | Grupo de hosts donde se ejecutará el playbook |
vars | Variables disponibles para el playbook |
tasks | Lista de tareas a ejecutar |
handlers | Tareas que se ejecutan solo cuando son notificadas |
become | Elevar privilegios (sudo) |
ansible-playbook playbook.yml
Opciones comunes:
--check
: Ejecuta en modo "dry-run"--limit
: Limita la ejecución a hosts específicos--tags
: Ejecuta solo tareas con ciertos tags--skip-tags
: Omite tareas con ciertos tagsvars
host_vars
group_vars
setup
)Ansible sigue este orden de precedencia (de menor a mayor):
vars:
http_port: 80
db_settings:
host: db.example.com
port: 3306
---
service_name: nginx
config_file: /etc/nginx/nginx.conf
- name: Obtener versión del kernel
command: uname -r
register: kernel_version
- name: Mostrar versión del kernel
debug:
var: kernel_version.stdout
Ansible usa el motor de plantillas Jinja2 para crear archivos de configuración dinámicos.
{{ variable }}
: Interpolación de variables{% for item in list %}
: Bucles{% if condition %}
: Condicionales{# comentario #}
: ComentariosEjemplo de plantilla para configuración de Nginx (templates/nginx.conf.j2):
server {
listen {{ http_port }};
server_name {{ server_name }};
root {{ web_root }};
{% if enable_ssl %}
listen 443 ssl;
ssl_certificate /etc/ssl/certs/{{ ssl_cert }};
ssl_certificate_key /etc/ssl/private/{{ ssl_key }};
{% endif %}
location / {
try_files $uri $uri/ =404;
}
{% for location in custom_locations %}
location {{ location.path }} {
proxy_pass {{ location.proxy }};
}
{% endfor %}
}
- name: Configurar Nginx
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/default
owner: root
group: root
mode: '0644'
Filtro | Descripción | Ejemplo |
---|---|---|
default | Valor por defecto si la variable no está definida | {{ variable | default('valor_por_defecto') }} |
lower | Convertir a minúsculas | {{ variable | lower }} |
upper | Convertir a mayúsculas | {{ variable | upper }} |
to_json | Convertir a JSON | {{ variable | to_json }} |
length | Longitud de una lista o cadena | {{ variable | length }} |
Los roles son una forma de organizar playbooks en estructuras predefinidas para facilitar la reutilización.
roles/ nombre_rol/ tasks/ # Archivos de tareas principales handlers/ # Handlers templates/ # Plantillas files/ # Archivos estáticos vars/ # Variables del rol defaults/ # Variables por defecto (baja prioridad) meta/ # Metadatos y dependencias
ansible-galaxy init nombre_rol
---
- name: Instalar Nginx
apt:
name: nginx
state: present
- name: Configurar Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: reiniciar nginx
---
- name: reiniciar nginx
service:
name: nginx
state: restarted
---
nginx_port: 80
nginx_user: www-data
---
- name: Configurar servidor web
hosts: webservers
roles:
- nginx
- { role: mysql, db_name: 'app_db', db_user: 'app_user' }
Módulo | Descripción | Ejemplo |
---|---|---|
apt/yum | Gestión de paquetes | apt: name=nginx state=present |
service | Gestión de servicios | service: name=nginx state=started |
user | Gestión de usuarios | user: name=johndoe group=admin |
copy | Copiar archivos | copy: src=file.conf dest=/etc/file.conf |
file | Gestión de archivos | file: path=/tmp/test state=directory |
Módulo | Descripción | Ejemplo |
---|---|---|
ec2 | Gestionar instancias AWS EC2 | ec2: instance_type=t2.micro image=ami-123456 |
azure_rm_virtualmachine | Gestionar máquinas virtuales Azure | azure_rm_virtualmachine: resource_group=mygroup name=vm1 |
gcp_compute_instance | Gestionar instancias GCP | gcp_compute_instance: name=instance1 machine_type=n1-standard-1 |
Módulo | Descripción | Ejemplo |
---|---|---|
ios_command | Ejecutar comandos en dispositivos Cisco IOS | ios_command: commands="show version" |
nxos_config | Gestionar configuración en dispositivos Cisco NX-OS | nxos_config: lines="hostname {{ inventory_hostname }}" |
production/ # Inventario de producción staging/ # Inventario de staging group_vars/ group1.yml # Variables de grupo group2.yml host_vars/ hostname1.yml # Variables específicas de host hostname2.yml library/ # Módulos personalizados module_utils/ # Utilidades para módulos filter_plugins/ # Plugins de filtro site.yml # Playbook principal roles/ common/ # Rol común webtier/ # Rol para servidores web monitoring/ # Rol para monitoreo fooapp/ # Rol para aplicación foo
async
para tareas largasforks
en ansible.cfg para paralelismolocal_action
para tareas en el nodo de controlfact_caching
Ansible Vault permite encriptar datos sensibles como contraseñas y claves API.
ansible-vault create secrets.yml
ansible-vault edit secrets.yml
ansible-vault encrypt existing.yml
ansible-vault decrypt secrets.yml
ansible-playbook site.yml --ask-vault-pass
O usando un archivo de contraseña:
ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt
Puedes encriptar variables individuales:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386439653236336462626566653063336164663966303231363934653563363965613833353661
6431626536303530376334333832656537303264396136310a393835656135373935343763326236
35613665383461656137636565656433616531333766376365313938386563613531376335303262
3839636434396664340a383266653836613763663266353835313963626362363864663736373739
3031
---
- name: Desplegar aplicación web
hosts: webservers
become: yes
vars:
app_repo: https://github.com/example/webapp.git
app_dir: /opt/webapp
app_port: 8080
tasks:
- name: Instalar dependencias
apt:
name: "{{ item }}"
state: present
loop:
- git
- python3
- python3-pip
- name: Clonar repositorio
git:
repo: "{{ app_repo }}"
dest: "{{ app_dir }}"
version: master
- name: Instalar dependencias de Python
pip:
requirements: "{{ app_dir }}/requirements.txt"
executable: pip3
- name: Configurar servicio systemd
template:
src: templates/webapp.service.j2
dest: /etc/systemd/system/webapp.service
- name: Habilitar e iniciar servicio
systemd:
name: webapp
state: started
enabled: yes
---
- name: Configurar HAProxy
hosts: loadbalancers
become: yes
vars:
backend_servers: "{{ groups['webservers'] }}"
tasks:
- name: Instalar HAProxy
apt:
name: haproxy
state: present
- name: Configurar HAProxy
template:
src: templates/haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
notify: reiniciar haproxy
handlers:
- name: reiniciar haproxy
service:
name: haproxy
state: restarted
---
- name: Configurar entorno de desarrollo
hosts: dev
roles:
- common
- { role: db, db_name: dev_db }
- { role: app, env: development }
- name: Configurar entorno de staging
hosts: staging
roles:
- common
- { role: db, db_name: staging_db }
- { role: app, env: staging }
- name: Configurar producción
hosts: production
serial: 3 # Actualizar en lotes de 3 servidores
roles:
- common
- { role: db, db_name: prod_db }
- { role: app, env: production }
Ansible es una herramienta poderosa para la automatización de infraestructura y despliegues. Este manual cubre los conceptos básicos y avanzados, pero Ansible tiene muchas más capacidades como:
Para más información, consulta la documentación oficial de Ansible.