DBAtlas · Atlas de operações de banco de dados

Automação de bancos com Ansible

Sintoma

Objetivo: tornar repetíveis e idempotentes (rodar o mesmo playbook de novo não quebra o sistema) as tarefas de instalação, configuração, usuários e backup de bancos com Ansible.

1. Defina o inventário e os grupos

Agrupe os servidores no inventário por papel no banco; coloque servidores primários, réplicas e de backup em grupos separados. Use um inventário estático INI/YAML ou um inventário dinâmico para a nuvem (aws_ec2, gcp_compute). Coloque as variáveis de grupo em group_vars/ e as específicas de host em host_vars/.

PostgreSQL

[pg_primary]
db1.example.local

[pg_replica]
db2.example.local

[postgres:children]
pg_primary
pg_replica

2. Instale a collection certa (community.postgresql / community.mysql / community.mongodb)

O Ansible core agora distribui os módulos de banco em collections separadas; instale a collection do seu engine via requirements.yml. Use community.postgresql (postgresql_db, postgresql_user, postgresql_privs) para PostgreSQL, community.mysql (mysql_db, mysql_user) para MySQL/MariaDB e community.mongodb para MongoDB. O cliente Python correspondente (psycopg2, PyMySQL, pymongo) precisa estar instalado no 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. Criptografe os segredos com Ansible Vault

Não deixe senhas de banco, segredos de replicação e credenciais de superusuário em texto puro; mantenha-os em um arquivo de variáveis criptografado com ansible-vault. Descriptografe em tempo de execução com --ask-vault-pass ou --vault-password-file. Assim os segredos podem ficar com segurança no Git e o playbook continua 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. Monte a estrutura de roles (roles/postgres, roles/mysql)

Crie uma role por engine e divida a lógica nas subpastas tasks/, defaults/, templates/ e handlers/. Essa estrutura melhora a reutilização: defaults/main.yml para valores padrão, templates/ para templates de configuração jinja2, handlers/ para a lógica 'reiniciar só se algo mudou'. Você pode criar o esqueleto da role com 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. Escreva as tarefas de instalação e configuração de forma idempotente

Instale o pacote, inicialize o diretório de dados e gere postgresql.conf/my.cnf a partir de um template; reinicie o serviço via handler quando a configuração mudar. Os módulos são idempotentes: um pacote já instalado não é reinstalado, e o handler não é disparado se o arquivo não mudou. Gere o template de configuração com o módulo template e ligue-o ao handler com '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 as tarefas de banco e de usuários

Crie o banco, os usuários e os privilégios com módulos; pegue a senha de uma variável do Vault. Os módulos community.postgresql são idempotentes: se o usuário/banco existir, não o recriam, aplicam só a diferença. Conceda privilégios à parte com postgresql_privs; no MySQL usa-se o campo priv do 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. Adicione a tarefa de backup e o agendamento

Implante o script de backup a partir de um template e agende-o com ansible.builtin.cron; assim o job de backup também é gerenciado como código. Transforme em variáveis o diretório de destino do backup, o período de retenção e o agendamento. O módulo cron é idempotente e identifica a entrada pelo 'name', então rodar de novo não a 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 no DBAtlas →