DBAtlas · Atlas de operaciones de bases de datos

Automatización de bases de datos con Ansible

Síntoma

Objetivo: hacer que las tareas de instalación, configuración, usuarios y backup de bases de datos sean repetibles e idempotentes (volver a ejecutar el mismo playbook no rompe el sistema) con Ansible.

1. Definir el inventario y los grupos

Agrupe los servidores en el inventario por rol de base de datos; coloque los servidores primarios, réplicas y de backup en grupos separados. Use un inventario estático INI/YAML o un inventario dinámico para la nube (aws_ec2, gcp_compute). Coloque las variables de grupo en group_vars/ y las específicas de cada host en host_vars/.

PostgreSQL

[pg_primary]
db1.example.local

[pg_replica]
db2.example.local

[postgres:children]
pg_primary
pg_replica

2. Instalar la colección correcta (community.postgresql / community.mysql / community.mongodb)

Ansible core ahora distribuye los módulos de bases de datos en colecciones separadas; instale la colección de su motor mediante requirements.yml. Use community.postgresql (postgresql_db, postgresql_user, postgresql_privs) para PostgreSQL, community.mysql (mysql_db, mysql_user) para MySQL/MariaDB y community.mongodb para MongoDB. El cliente Python correspondiente (psycopg2, PyMySQL, pymongo) debe estar instalado en el host de destino.

PostgreSQL

# requirements.yml
collections:
  - name: community.postgresql

# install:
ansible-galaxy collection install -r requirements.yml

MySQL

collections:
  - name: community.mysql

MongoDB

collections:
  - name: community.mongodb

3. Cifrar los secretos con Ansible Vault

No deje en texto plano las contraseñas de la base de datos, los secretos de replicación ni las credenciales de superusuario; guárdelos en un archivo de variables cifrado con ansible-vault. Descifre en tiempo de ejecución con --ask-vault-pass o --vault-password-file. Así los secretos pueden guardarse de forma segura en Git y el playbook sigue siendo idempotente.

PostgreSQL

ansible-vault create group_vars/postgres/vault.yml
# contents:
vault_pg_admin_password: "S3cret!"

# run:
ansible-playbook site.yml --ask-vault-pass

4. Configure la estructura de roles (roles/postgres, roles/mysql)

Cree un rol por motor y divida la lógica en las subcarpetas tasks/, defaults/, templates/ y handlers/. Esta estructura mejora la reutilización: defaults/main.yml para los valores predeterminados, templates/ para las plantillas de configuración jinja2, handlers/ para la lógica de 'reiniciar solo si algo cambió'. Puede generar el esqueleto del rol con ansible-galaxy init roles/postgres.

PostgreSQL

ansible-galaxy init roles/postgres
# roles/postgres/
#   defaults/main.yml
#   tasks/main.yml
#   templates/postgresql.conf.j2
#   handlers/main.yml

5. Escriba tareas de instalación y configuración idempotentes

Instale el paquete, inicialice el directorio de datos y genere postgresql.conf/my.cnf a partir de una plantilla; reinicie el servicio mediante un handler cuando cambie la configuración. Los módulos son idempotentes: un paquete ya instalado no se reinstala, y el handler no se dispara si el archivo no cambió. Genere la plantilla de configuración con el módulo template y vincúlela al handler con 'notify'.

PostgreSQL

- name: postgresql.conf template
  ansible.builtin.template:
    src: postgresql.conf.j2
    dest: /etc/postgresql/16/main/postgresql.conf
  notify: restart postgresql

# handlers/main.yml
- name: restart postgresql
  ansible.builtin.service:
    name: postgresql
    state: restarted

MySQL

- name: my.cnf template
  ansible.builtin.template:
    src: my.cnf.j2
    dest: /etc/mysql/my.cnf
  notify: restart mysql

6. Defina las tareas de base de datos y usuarios

Cree la base de datos, los usuarios y los privilegios con módulos; tome la contraseña de una variable de Vault. Los módulos community.postgresql son idempotentes: si el usuario/la BD existe, no lo recrean, solo aplican la diferencia. Otorgue los privilegios por separado con postgresql_privs; en MySQL se usa el campo priv de mysql_user.

PostgreSQL

- name: application database
  community.postgresql.postgresql_db:
    name: appdb
    state: present

- name: application user
  community.postgresql.postgresql_user:
    name: app_user
    password: "{{ vault_app_password }}"
    db: appdb
    state: present

MySQL

- name: application user
  community.mysql.mysql_user:
    name: app_user
    password: "{{ vault_app_password }}"
    priv: 'appdb.*:ALL'
    state: present

7. Agregue la tarea de backup y su programación

Despliegue el script de backup desde una plantilla y prográmelo con ansible.builtin.cron; así el job de backup también se gestiona como código. Convierta en variables el directorio destino del backup, el periodo de retención y la programación. El módulo cron es idempotente e identifica la entrada por 'name', por lo que volver a ejecutarlo no la duplica.

PostgreSQL

- name: nightly backup (cron)
  ansible.builtin.cron:
    name: "pg dump nightly"
    minute: "0"
    hour: "2"
    job: "pg_dump -Fc appdb > /backup/appdb_$(date +\\%F).dump"
Abrir en DBAtlas →