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_replica2. 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.ymlMySQL
collections:
- name: community.mysqlMongoDB
collections:
- name: community.mongodb3. 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-pass4. 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.yml5. É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: restartedMySQL
- name: my.cnf template
ansible.builtin.template:
src: my.cnf.j2
dest: /etc/mysql/my.cnf
notify: restart mysql6. 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: presentMySQL
- name: application user
community.mysql.mysql_user:
name: app_user
password: "{{ vault_app_password }}"
priv: 'appdb.*:ALL'
state: present7. 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"