Automatización de backups diarios de bases de datos MySQL con Ansible

Automatización de backups diarios de bases de datos MySQL con Ansible

Si gestionas varios servidores MySQL, sabes que los backups regulares no solo son recomendables, son vitales.
Hoy traigo un playbook Ansible que automatiza completamente la generación y almacenamiento ordenado de copias de seguridad de todas tus bases de datos MySQL.
Este ejemplo, de dificultad intermedia, permite ejecutar copias diarias, personalizar horarios, y emparejarlo fácilmente con políticas de retención.

¿Por qué automatizar backups de bases de datos con Ansible?

  • Consistencia. No volverás a olvidar un backup ni depender de tareas manuales o scripts desperdigados.
  • Control centralizado. Gestiona desde un punto común todos los servidores con una sola orden.
  • Fácil integración. Puedes hacer que los backups formen parte de flujos de CI/CD, o combinarlos con otras tareas Ansible (actualizaciones, hardening, rotación de logs, etc).
  • Recuperación rápida ante imprevistos. Disponer de copias frescas y ordenadas por fecha lo cambia todo el día que se rompe algo.

Código completo del playbook

Este playbook realiza, para todos los hosts definidos como mysql_servers, los siguientes pasos:

  1. Instalar mysqldump si es necesario.
  2. Crear el directorio de backups local en el servidor, añadiendo la fecha al nombre (ejemplo: /var/backups/mysql/2025-07-30/).
  3. Descubrir automáticamente todas las bases de datos y, salvo las de sistema (information_schema, mysql, …), sacar su volcado con mysqldump.
  4. Almacenar todos los backups individualmente, uno por base de datos, comprimidos con gzip.
  5. (Opcional: puedes añadir pasos de rotación/eliminación de backups antiguos según tus políticas).

Repositorio ansible_mysql_backup.yml

---
- name: Backup programado de todas las bases de datos MySQL
  hosts: mysql_servers
  become: true
  vars:
    backup_dir: "/var/backups/mysql/{{ ansible_date_time.date }}"
    mysql_user: "backup_user"
    mysql_password: "mi_password_backup"
    exclude_dbs:
      - information_schema
      - mysql
      - performance_schema
      - sys

  tasks:
    - name: Instalar cliente MySQL si falta
      apt:
        name: mysql-client
        state: present

    - name: Crear directorio de backups con fecha
      file:
        path: "{{ backup_dir }}"
        state: directory
        mode: '0750'

    - name: Obtener lista de bases de datos
      mysql_db:
        login_user: "{{ mysql_user }}"
        login_password: "{{ mysql_password }}"
        state: list
      register: dbs

    - name: Definir lista de bases a copiar (sin bases de sistema)
      set_fact:
        user_databases: "{{ dbs.databases | difference(exclude_dbs) }}"

    - name: Dump de cada base de datos en archivos comprimidos
      loop: "{{ user_databases }}"
      vars:
        db_name: "{{ item }}"
      shell: |
        mysqldump -u {{ mysql_user }} -p'{{ mysql_password }}' {{ db_name }} | gzip > "{{ backup_dir }}/{{ db_name }}.sql.gz"
      args:
        creates: "{{ backup_dir }}/{{ db_name }}.sql.gz"
      environment:
        MYSQL_PWD: "{{ mysql_password }}"

    - name: (Opcional) Rotar/eliminar backups antiguos (más de 7 días)
      find:
        paths: /var/backups/mysql
        age: 7d
        age_stamp: mtime
        recurse: yes
        patterns: "*.gz"
      register: old_backups

    - name: (Opcional) Borrar dumps antiguos
      file:
        path: "{{ item.path }}"
        state: absent
      with_items: "{{ old_backups.files }}"
      when: old_backups.matched > 0

¿Cómo uso este playbook?

  1. Asegúrate de tener creado el usuario backup_user con privilegios de sólo lectura en MySQL.
  2. Consulta tus hosts o inventory y pon todos tus servidores MySQL en el grupo mysql_servers.
  3. Puedes programar la ejecución diaria con cron en el servidor donde ejecutas Ansible, apuntando al ansible-playbook.
  4. Personaliza la variable backup_dir o la retención de backups si lo deseas.

Consejos finales y troubleshooting rápido

  • ¿Error de permisos para escribir en /var/backups/mysql? Usa become: true y revisa la configuración de sudo.
  • Protege las credenciales: puedes usar Ansible Vault para cifrar el archivo que contiene mysql_password.
  • ¿Tu servidor tiene muchos datos? Comprime los dumps en tiempo real, como en el ejemplo, para ocupar mucho menos.
  • Revisión de logs: si algo falla, repasa el output de ansible-playbook para saber en qué base de datos ha saltado el error.

Automatizar los backups no sustituye revisar si realmente se están generando y restauran bien. Haz pruebas de restauración periódicas.

Si tienes dudas, sugerencias o peticiones de playbooks complejos, ¡déjalas en comentarios!

Avatar

Por Mid