Manual Completo de Ansible

1. Introducción a Ansible

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.

1.1 Características principales

1.2 Arquitectura de Ansible

Ansible sigue una arquitectura cliente-servidor sin agentes:

Arquitectura de Ansible

Nota: Ansible se comunica con los nodos gestionados a través de SSH (para sistemas Unix/Linux) o WinRM (para Windows).

2. Instalación de Ansible

2.1 Requisitos del sistema

2.2 Instalación en diferentes sistemas operativos

En Ubuntu/Debian:

sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

En CentOS/RHEL:

sudo yum install epel-release
sudo yum install ansible

Usando pip (para cualquier sistema):

python3 -m pip install --user ansible

2.3 Verificar la instalación

ansible --version

Deberías ver información sobre la versión instalada.

3. Gestión de Inventarios

El inventario es un archivo que define los hosts y grupos de hosts que Ansible gestionará.

3.1 Archivo de inventario básico

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

3.2 Variables de inventario

Puedes asignar variables a hosts o grupos:

[webservers:vars]
http_port=80
max_connections=200

[dbservers:vars]
db_port=3306

3.3 Inventario dinámico

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))

4. Comandos Ad-Hoc

Los comandos ad-hoc permiten ejecutar tareas simples sin necesidad de crear un playbook.

4.1 Sintaxis básica

ansible [grupo] -m [modulo] -a "[argumentos]"

4.2 Ejemplos comunes

Revisar conectividad con todos los hosts

ansible all -m ping

Recoger información de los hosts

ansible all -m setup

Instalar un paquete en servidores web

ansible webservers -m apt -a "name=nginx state=present" --become

Reiniciar servidores

ansible dbservers -m command -a "/sbin/reboot" --become

Copiar archivos

ansible webservers -m copy -a "src=/local/path/file.conf dest=/remote/path/file.conf"

5. Playbooks de Ansible

Los playbooks son archivos YAML que describen políticas de configuración y pasos de implementación.

5.1 Estructura básica de un playbook

---
- 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

5.2 Componentes principales

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)

5.3 Ejecutar un playbook

ansible-playbook playbook.yml

Opciones comunes:

6. Manejo de Variables

6.1 Tipos de variables

6.2 Prioridad de variables

Ansible sigue este orden de precedencia (de menor a mayor):

  1. Valores por defecto
  2. Inventario (group_vars/all)
  3. Inventario (group_vars/*)
  4. Inventario (host_vars/*)
  5. Variables de playbook
  6. Variables de rol
  7. Variables de bloque
  8. Variables de tarea
  9. Variables extras (con -e)

6.3 Ejemplos de definición de variables

En playbooks:

vars:
  http_port: 80
  db_settings:
    host: db.example.com
    port: 3306

En archivos externos (group_vars/webservers):

---
service_name: nginx
config_file: /etc/nginx/nginx.conf

Variables de registro:

- name: Obtener versión del kernel
  command: uname -r
  register: kernel_version
  
- name: Mostrar versión del kernel
  debug:
    var: kernel_version.stdout

7. Plantillas (Templates) con Jinja2

Ansible usa el motor de plantillas Jinja2 para crear archivos de configuración dinámicos.

7.1 Sintaxis básica de Jinja2

7.2 Ejemplo de plantilla

Ejemplo 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 %}
}

7.3 Uso en playbooks

- name: Configurar Nginx
  template:
    src: templates/nginx.conf.j2
    dest: /etc/nginx/sites-available/default
    owner: root
    group: root
    mode: '0644'

7.4 Filtros comunes

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 }}

8. Roles en Ansible

Los roles son una forma de organizar playbooks en estructuras predefinidas para facilitar la reutilización.

8.1 Estructura de un rol

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

8.2 Crear un rol

ansible-galaxy init nombre_rol

8.3 Ejemplo de rol para Nginx

roles/nginx/tasks/main.yml:

---
- name: Instalar Nginx
  apt:
    name: nginx
    state: present
    
- name: Configurar Nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: reiniciar nginx

roles/nginx/handlers/main.yml:

---
- name: reiniciar nginx
  service:
    name: nginx
    state: restarted

roles/nginx/defaults/main.yml:

---
nginx_port: 80
nginx_user: www-data

8.4 Usar roles en playbooks

---
- name: Configurar servidor web
  hosts: webservers
  roles:
    - nginx
    - { role: mysql, db_name: 'app_db', db_user: 'app_user' }

9. Módulos Comunes de Ansible

9.1 Módulos de sistema

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

9.2 Módulos de nube

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

9.3 Módulos de red

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 }}"

10. Mejores Prácticas con Ansible

10.1 Estructura de directorios recomendada

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

10.2 Consejos para playbooks

10.3 Seguridad

10.4 Optimización

11. Ansible Vault

Ansible Vault permite encriptar datos sensibles como contraseñas y claves API.

11.1 Crear un archivo encriptado

ansible-vault create secrets.yml

11.2 Editar un archivo encriptado

ansible-vault edit secrets.yml

11.3 Encriptar un archivo existente

ansible-vault encrypt existing.yml

11.4 Desencriptar un archivo

ansible-vault decrypt secrets.yml

11.5 Usar archivos encriptados en playbooks

ansible-playbook site.yml --ask-vault-pass

O usando un archivo de contraseña:

ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt

11.6 Variables encriptadas

Puedes encriptar variables individuales:

db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66386439653236336462626566653063336164663966303231363934653563363965613833353661
          6431626536303530376334333832656537303264396136310a393835656135373935343763326236
          35613665383461656137636565656433616531333766376365313938386563613531376335303262
          3839636434396664340a383266653836613763663266353835313963626362363864663736373739
          3031

12. Ejemplos Avanzados

12.1 Despliegue de aplicación web

---
- 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

12.2 Configuración de balanceador de carga

---
- 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

12.3 Automatización multi-etapa

---
- 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 }

13. Conclusión

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.