DBAtlas · Atlas für Datenbankbetrieb

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_replica

2. 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.yml

MySQL

collections:
  - name: community.mysql

MongoDB

collections:
  - name: community.mongodb

3. 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-pass

4. 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.yml

5. 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: restarted

MySQL

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

6. 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: present

MySQL

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

7. 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"
In DBAtlas öffnen →