DBAtlas · Atlas d'exploitation des bases de données

Automatisation des bases de données avec Ansible

Symptôme

Objectif : rendre les tâches d'installation, de configuration, d'utilisateurs et de sauvegarde des bases reproductibles et idempotentes (relancer le même playbook ne casse pas le système) avec Ansible.

1. Définissez l'inventaire et les groupes

Regroupez les serveurs dans l'inventaire par rôle de base ; placez les serveurs primaires, réplicas et de sauvegarde dans des groupes distincts. Utilisez un inventaire statique INI/YAML ou un inventaire dynamique pour le cloud (aws_ec2, gcp_compute). Placez les variables de groupe sous group_vars/ et celles propres à un hôte sous host_vars/.

PostgreSQL

[pg_primary]
db1.example.local

[pg_replica]
db2.example.local

[postgres:children]
pg_primary
pg_replica

2. Installez la bonne collection (community.postgresql / community.mysql / community.mongodb)

Ansible core fournit désormais les modules de base de données dans des collections séparées ; installez la collection de votre moteur via requirements.yml. Utilisez community.postgresql (postgresql_db, postgresql_user, postgresql_privs) pour PostgreSQL, community.mysql (mysql_db, mysql_user) pour MySQL/MariaDB et community.mongodb pour MongoDB. Le client Python correspondant (psycopg2, PyMySQL, pymongo) doit être installé sur l'hôte cible.

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. Chiffrez les secrets avec Ansible Vault

Ne laissez pas en clair les mots de passe des bases, les secrets de réplication et les identifiants superuser ; conservez-les dans un fichier de variables chiffré avec ansible-vault. Déchiffrez à l'exécution avec --ask-vault-pass ou --vault-password-file. Les secrets peuvent alors être stockés en toute sécurité dans Git et le playbook reste idempotent.

PostgreSQL

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

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

4. Mettez en place la structure de rôles (roles/postgres, roles/mysql)

Créez un rôle par moteur et répartissez la logique dans les sous-dossiers tasks/, defaults/, templates/ et handlers/. Cette structure améliore la réutilisabilité : defaults/main.yml pour les valeurs par défaut, templates/ pour les modèles de configuration jinja2, handlers/ pour la logique « redémarrer uniquement si quelque chose a changé ». Vous pouvez générer le squelette du rôle avec 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. Écrivez les tâches d'installation et de configuration de manière idempotente

Installez le paquet, initialisez le répertoire de données et générez postgresql.conf/my.cnf à partir d'un modèle ; redémarrez le service via un handler lorsque la configuration change. Les modules sont idempotents : un paquet déjà installé n'est pas réinstallé et le handler n'est pas déclenché si le fichier n'a pas changé. Générez le modèle de configuration avec le module template et reliez-le au handler avec '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. Définissez les tâches de base et d'utilisateurs

Créez la base, les utilisateurs et les privilèges avec des modules ; prenez le mot de passe dans une variable Vault. Les modules community.postgresql sont idempotents : si l'utilisateur/la base existe, ils ne le recréent pas et n'appliquent que la différence. Accordez les privilèges séparément avec postgresql_privs ; dans MySQL, on utilise le champ 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. Ajoutez la tâche de sauvegarde et sa planification

Déployez le script de sauvegarde à partir d'un modèle et planifiez-le avec ansible.builtin.cron ; le job de sauvegarde est alors lui aussi géré comme du code. Faites du répertoire cible, de la durée de rétention et de la planification des variables. Le module cron est idempotent et identifie l'entrée par 'name', une relance ne la duplique donc pas.

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"
Ouvrir dans DBAtlas →