Datenbankautomatisierung mit Ansible
Symptom
Ziel: Installation, Konfiguration, Benutzer- und Backup-Aufgaben der Datenbank mit Ansible wiederholbar und idempotent machen (das erneute Ausführen desselben Playbooks beschädigt das System nicht).
1. Inventory und Gruppen definieren
Gruppiere die Server im Inventory nach Datenbankrolle; lege Primary-, Replica- und Backup-Server in getrennte Gruppen. Verwende ein statisches INI-/YAML-Inventory oder für die Cloud ein dynamisches Inventory (aws_ec2, gcp_compute). Lege Gruppenvariablen unter group_vars/ und hostspezifische unter host_vars/ ab.
PostgreSQL
[pg_primary]
db1.example.local
[pg_replica]
db2.example.local
[postgres:children]
pg_primary
pg_replica2. Die passende Collection installieren (community.postgresql / community.mysql / community.mongodb)
Ansible Core liefert Datenbankmodule inzwischen in separaten Collections aus; installiere die Collection für deine Engine über requirements.yml. Verwende community.postgresql (postgresql_db, postgresql_user, postgresql_privs) für PostgreSQL, community.mysql (mysql_db, mysql_user) für MySQL/MariaDB und community.mongodb für MongoDB. Auf dem Zielhost muss der passende Python-Client (psycopg2, PyMySQL, pymongo) installiert sein.
PostgreSQL
# requirements.yml
collections:
- name: community.postgresql
# install:
ansible-galaxy collection install -r requirements.ymlMySQL
collections:
- name: community.mysqlMongoDB
collections:
- name: community.mongodb3. Secrets mit Ansible Vault verschlüsseln
Lass Datenbankpasswörter, Replikations-Secrets und Superuser-Zugangsdaten nicht im Klartext liegen; halte sie mit ansible-vault in einer verschlüsselten Variablendatei. Entschlüssele zur Laufzeit mit --ask-vault-pass oder --vault-password-file. Secrets lassen sich so sicher in Git speichern, und das Playbook bleibt idempotent.
PostgreSQL
ansible-vault create group_vars/postgres/vault.yml
# contents:
vault_pg_admin_password: "S3cret!"
# run:
ansible-playbook site.yml --ask-vault-pass4. Rollenstruktur aufbauen (roles/postgres, roles/mysql)
Lege pro Engine eine Rolle an und teile die Logik in die Unterordner tasks/, defaults/, templates/ und handlers/ auf. Diese Struktur verbessert die Wiederverwendbarkeit: defaults/main.yml für Standardwerte, templates/ für Jinja2-Konfigurationsvorlagen, handlers/ für die Logik 'nur neu starten, wenn sich etwas geändert hat'. Das Gerüst der Rolle erzeugst du mit 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. Installations- und Konfigurations-Tasks idempotent schreiben
Installiere das Paket, initialisiere das Datenverzeichnis und erzeuge postgresql.conf/my.cnf aus einer Vorlage; starte den Dienst über einen Handler neu, wenn sich die Konfiguration ändert. Module sind idempotent: Ein bereits installiertes Paket wird nicht erneut installiert, und der Handler wird nicht ausgelöst, wenn sich die Datei nicht geändert hat. Erzeuge die Konfigurationsvorlage mit dem Modul template und verknüpfe sie per 'notify' mit dem Handler.
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. Datenbank- und Benutzer-Tasks definieren
Lege Datenbank, Benutzer und Rechte mit Modulen an; das Passwort stammt aus einer Vault-Variable. Die Module von community.postgresql sind idempotent: Existiert der Benutzer bzw. die DB, werden sie nicht neu angelegt, sondern nur die Differenz angewendet. Vergib Rechte separat mit postgresql_privs; in MySQL wird das Feld priv von mysql_user verwendet.
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. Backup-Task und Zeitplan hinzufügen
Verteile das Backup-Skript aus einer Vorlage und plane es mit ansible.builtin.cron; so wird auch der Backup-Job als Code verwaltet. Mache Backup-Zielverzeichnis, Aufbewahrungsdauer und Zeitplan zu Variablen. Das Modul cron ist idempotent und erkennt den Eintrag am 'name', sodass erneutes Ausführen ihn nicht dupliziert.
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"