DevOps

Ansible para sysadmins: casos prácticos que no están en el tutorial

TL;DR — Lo que vas a tener al final

  • Tiempo de setup: 30 minutos a 2 horas dependiendo de la complejidad del entorno.
  • Requisitos: Acceso root, Linux moderno, conexión a internet para descargar dependencias.
  • Resultado: Servicio funcional y estable, documentado paso a paso.
  • Troubleshooting: Logs estándar en /var/log/, comandos de verificación al final de cada sección.

Por qué este artículo y no el típico “Ansible desde cero”

Si buscas una introducción básica a Ansible, ya hay material en soylinux.com. Este artículo va un paso más allá: los casos prácticos reales que un sysadmin Linux termina usando una vez que ya pasó la fase “hello world” de los playbooks. Hablamos de idempotencia dura, Ansible Vault, módulos útiles que mucha gente pasa por alto, dynamic inventory, y patrones que evitan que tu playbook se rompa en producción a las 3 AM.

Ansible Vault: secretos sin filtrarlos en el repo

El error más común es dejar contraseñas en group_vars/all.yml en texto plano y commitear el repo. ansible-vault resuelve esto cifrando el archivo con AES256. El playbook queda ejecutable, pero el contenido es ilegible sin la clave maestra.

Crear un archivo cifrado:

ansible-vault create group_vars/production/vault.yml
# Te pide una contraseña maestra. Guárdala en tu gestor de claves
# (pass, Bitwarden, 1Password), NO en el repo.

Para editarlo después:

ansible-vault edit group_vars/production/vault.yml
ansible-vault view group_vars/production/vault.yml
ansible-vault rekey group_vars/production/vault.yml  # cambiar contraseña

Para usar las variables en el playbook, ejecutas con --ask-vault-pass o con un archivo de contraseña:

ansible-playbook site.yml --ask-vault-pass
# O mejor, archivo con permisos restrictivos:
echo 'mi_clave_maestra' > ~/.vault_pass && chmod 600 ~/.vault_pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass

Dentro del playbook referencias las variables con el prefijo vault_ para que quede claro que vienen del vault cifrado:

- hosts: webservers
  vars_files:
    - group_vars/production/vault.yml
  tasks:
    - name: Configurar base de datos
      mysql_user:
        name: "{{ vault_db_user }}"
        password: "{{ vault_db_password }}"
        priv: '*.*:ALL'
        state: present

Troubleshooting: si al ejecutar el playbook te aparece ERROR! Decryption failed, casi siempre es porque editaste el archivo con un editor que no respeta los finales de línea Unix. Usa siempre ansible-vault edit, no vi vault.yml directamente sobre el archivo cifrado.

Idempotencia: por qué command: es un antipatrón

El mantra de Ansible es “declarar el estado final, no los pasos para llegar”. Cuando escribes una task con command:, Ansible ejecuta ese comando siempre, sin importar si el estado deseado ya existe. Eso rompe la idempotencia y termina con efectos secundarios difíciles de debuggear.

Ejemplo MALO:

- name: Instalar nginx
  command: apt-get install -y nginx  # Se ejecuta cada vez, aunque ya esté instalado

Ejemplo BUENO:

- name: Instalar nginx
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: yes

El módulo apt primero chequea si el paquete está instalado, y solo ejecuta apt-get install si hace falta. Corre el playbook 10 veces seguidas: la primera tarda 30 segundos, las siguientes 2 segundos. Con command: tardaría 30 segundos las 10 veces.

Cuándo SÍ usar command:: cuando no existe un módulo dedicado para la tarea. Para esos casos, chequea primero el catálogo de collections oficiales, con cientos de módulos en ansible-core y miles más sumando todas las collections. Si no encuentras uno, recién ahí recurras a command o shell con creates o removes para simular idempotencia:

- name: Clonar repo si no existe
  ansible.builtin.git:
    repo: '[email protected]:mi-org/mi-app.git'
    dest: /opt/mi-app
    update: no

Módulos infrausados que te ahorran horas

Hay 3 módulos que aparecen poco en tutoriales pero resuelven problemas reales:

lineinfile: editar UNA línea de un archivo de configuración

El clásico “asegúrate que esta línea esté en /etc/ssh/sshd_config“. Lo contrario al antipatrón de reemplazar el archivo entero:

- name: Deshabilitar login root por SSH
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    line: 'PermitRootLogin no'
    state: present
  notify: restart_sshd

regexp busca la línea existente (con o sin comentar), y line la reemplaza o la agrega al final si no existe. Cero riesgo de romper el resto del archivo.

package vs apt vs dnf

Si tu playbook corre en Debian, Ubuntu, Fedora y RHEL mezclados, package detecta el gestor de paquetes automáticamente:

- name: Instalar htop universal
  ansible.builtin.package:
    name: htop
    state: present

Funciona en cualquier distro. Más portable que escribir tareas condicionales con when: ansible_os_family == 'Debian'.

assert: precondiciones que cortan el playbook

Antes de tocar nada, valida que el entorno cumple lo que asumís:

- name: Verificar versión mínima de Python
  ansible.builtin.assert:
    that:
      - ansible_python_version is version('3.8', '>=')
    fail_msg: "Este playbook requiere Python 3.8 o superior"
    success_msg: "Python OK, continuando"

Si falla, Ansible aborta inmediatamente con el mensaje que pusiste. Mejor que enterarte a mitad del playbook que el servidor tiene Python 2.7.

Handlers: tareas que se ejecutan UNA sola vez al final

Un handler es una task que solo se dispara cuando otra task la notifica con notify. Sirve para evitar reiniciar un servicio 20 veces cuando 20 tareas diferentes cambian su configuración.

- hosts: webservers
  tasks:
    - name: Configurar virtualhost 1
      ansible.builtin.template:
        src: vhost1.conf.j2
        dest: /etc/nginx/sites-enabled/vhost1.conf
      notify: reload_nginx
    - name: Configurar virtualhost 2
      ansible.builtin.template:
        src: vhost2.conf.j2
        dest: /etc/nginx/sites-enabled/vhost2.conf
      notify: reload_nginx
    - name: Configurar virtualhost 3
      ansible.builtin.template:
        src: vhost3.conf.j2
        dest: /etc/nginx/sites-enabled/vhost3.conf
      notify: reload_nginx
  handlers:
    - name: reload_nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded

Ansible agrupa las notificaciones y corre el handler UNA vez al final del playbook, no una vez por cada cambio. Más eficiente y evita ventanas de downtime innecesarias.

Gotcha importante: si una task falla DESPUÉS de notificar al handler pero antes de que se ejecute el handler, el handler igual corre. Si eso te molesta, usa force_handlers: false en el play (es el default en algunas versiones pero no en todas, validalo).

Dynamic inventory: nodos que aparecen y desaparecen

El inventory estático (inventory.ini) sirve para 10 servidores fijos. Cuando tienes Proxmox, AWS, Hetzner o cualquier cloud con VMs que se crean y destruyen, el dynamic inventory lee la fuente de verdad en tiempo de ejecución.

Ejemplo con Hetzner Cloud:

plugin: hetzner.hcloud.hcloud_inventory
hcloud_api_token: "{{ vault_hcloud_token }}"

Cada vez que corres el playbook, Ansible consulta la API de Hetzner, obtiene la lista actual de servidores, y aplica las tareas a esa lista. Borrás una VM en el panel, y Ansible deja de intentar configurarla en el próximo run.

Para Proxmox existe community.general.proxmox y para AWS el amazon.aws.aws_ec2. La mayoría de providers grandes tienen su collection oficial en Ansible Galaxy.

Ansible-pull: nodos que se autoconfiguran

El flujo clásico es “control node empuja a los managed nodes”. ansible-pull invierte la dirección: cada nodo corre un cron que hace git pull de sus playbooks y los aplica localmente.

Útil para:

  • Nodos detrás de NAT estricto donde no puedes llegar por SSH desde el control node
  • Fleet grande donde no quieres mantener un inventario central
  • Edge computing, IoT, kioskos
# En el nodo managed, vía SSH una sola vez para instalarlo:
sudo apt install ansible
sudo ansible-pull -U https://github.com/mi-org/ansible-pull-repo.git 
  -C main 
  playbook.yml 
  --vault-password-file /root/.vault_pass

Después lo agendás con cron cada 30 minutos:

echo '*/30 * * * * root /usr/bin/ansible-pull -U https://github.com/mi-org/ansible-pull-repo.git -C main playbook.yml --vault-password-file /root/.vault_pass' 
  | sudo tee /etc/cron.d/ansible-pull

Debugging: cómo entender qué está pasando

Tres flags que cambian todo cuando un playbook falla:

# Modo check: muestra QUÉ HARÍA sin tocar nada
ansible-playbook site.yml --check
# Modo diff: muestra QUÉ ARCHIVOS CAMBIARÍA línea por línea
ansible-playbook site.yml --check --diff
# Modo verbose: muestra la salida completa de los módulos
ansible-playbook site.yml -v    # verbose básico
ansible-playbook site.yml -vv   # más detalle
ansible-playbook site.yml -vvv  # muestra también el comando SSH ejecutado

Para una task específica que falla, agregale debug: al lado para ver qué valores tienen las variables en ese momento:

- name: Verificar variable
  ansible.builtin.debug:
    var: vault_db_password

Cuidado: debug: var: imprime la variable en pantalla. Si es un secreto, mejor filtralo antes:

- name: Verificar variable sin imprimir el secreto
  ansible.builtin.debug:
    msg: "Usuario: {{ vault_db_user }}, Password length: {{ vault_db_password | length }}"

Cuándo NO usar Ansible

Ansible no es la herramienta correcta para todo. Reconocé cuándo escalar a otra cosa:

  • Configuración de containers: si tu output es una imagen Docker o un chart de Helm, Ansible es el paso equivocado. usa Dockerfile + docker-compose, o Kubernetes manifests.
  • Estado continuo de aplicación: Ansible es imperativo-declarativo y converge al estado, pero no se queda corriendo. Para mantener un proceso vivo y reaccionando a eventos (Kubernetes Pod, systemd watchdog), usa la herramienta nativa de la plataforma.
  • Provisioning de infraestructura cloud nueva: Terraform o Pulumi están mejor diseñados para crear/destruir recursos. Ansible es mejor para configurar lo que ya existe.
  • Fleet de 100+ nodos con cambios constantes: el modelo push empieza a mostrar limitaciones. mira SaltStack, Puppet o Ansible Automation Platform (AWX) con su modelo de control plane.

Resumen

Ansible sigue siendo la herramienta más práctica para sysadmins Linux que necesitan automatizar configuraciones en 5-50 servidores. Los puntos clave que vimos:

  • Vault para secretos, sin excuses
  • Idempotencia dura: usa módulos dedicados, no command
  • Handlers para evitar reinicios redundantes
  • Dynamic inventory cuando los nodos cambian seguido
  • ansible-pull para nodos detrás de NAT o fleet grande
  • –check –diff -vvv como trío de debugging obligatorio

Si ya tienes Ansible instalado y jugaste con playbooks básicos, este artículo cubre los huecos que el tutorial típico se saltea. Si recién empezás, el artículo introductorio te da el contexto que acá asumimos.

Preguntas frecuentes

¿Por qué Ansible para sysadmins: casos prácticos que no están en el tutorial es relevante para sysadmins Linux?

Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.

¿Qué necesito para empezar con Ansible para sysadmins: casos prácticos?

Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.

¿Cuáles son los errores más comunes con Ansible para sysadmins: casos prácticos?

Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.

¿Cuándo usar Ansible para sysadmins: casos prácticos y cuándo una alternativa?

Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.

¿Cómo migro desde una configuración previa a Ansible para sysadmins: casos prácticos?

Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.

Lee también

Alfonso Moreno | Sysadmin Senior

Soy Alfonso, sysadmin senior con RHCE y más de 10 años administrando sistemas Linux para empresas y proyectos personales. Me especializo en infraestructura, redes, virtualización, monitoring, automation y self-hosting. Sobre SoyLinux.com SoyLinux.com es un blog técnico en español sobre Linux, software libre y self-hosting. Lo mantengo en mi tiempo libre. Áreas de expertise - Linux server administration: RHEL, CentOS, Rocky, Alma, Fedora, Debian, Ubuntu - Network services: Postfix, BIND, Samba, NFS, Squid - Virtualización y containers: KVM, Proxmox, Docker, Podman - Monitoring: Prometheus, Grafana, Zabbix - Automation: Ansible, Bash scripting - Self-hosting: Vaultwarden, Nextcloud, Jellyfin, Immich, Homelab Contacto - Email: [email protected]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *