Ansible によるデータベース自動化
症状
目標: Ansible により、データベースのインストール、構成、ユーザー、バックアップのタスクを再現可能かつ冪等にする (同じプレイブックを再実行してもシステムが壊れない)。
1. インベントリとグループを定義する
インベントリ内でサーバーをデータベースのロールごとにグループ化し、プライマリ、レプリカ、バックアップサーバーを別々のグループに入れる。静的な INI/YAML インベントリ、またはクラウド用の動的インベントリ (aws_ec2、gcp_compute) を使う。グループ変数は group_vars/ に、ホスト固有の変数は host_vars/ に置く。
PostgreSQL
[pg_primary]
db1.example.local
[pg_replica]
db2.example.local
[postgres:children]
pg_primary
pg_replica2. 適切なコレクションをインストールする (community.postgresql / community.mysql / community.mongodb)
現在の Ansible core はデータベースモジュールを個別のコレクションで提供している。使用するエンジンのコレクションを requirements.yml でインストールする。PostgreSQL には community.postgresql (postgresql_db、postgresql_user、postgresql_privs)、MySQL/MariaDB には community.mysql (mysql_db、mysql_user)、MongoDB には community.mongodb を使う。ターゲットホストには対応する Python クライアント (psycopg2、PyMySQL、pymongo) がインストールされている必要がある。
PostgreSQL
# requirements.yml
collections:
- name: community.postgresql
# install:
ansible-galaxy collection install -r requirements.ymlMySQL
collections:
- name: community.mysqlMongoDB
collections:
- name: community.mongodb3. Ansible Vault でシークレットを暗号化する
データベースのパスワード、レプリケーションのシークレット、スーパーユーザーの認証情報を平文のまま放置せず、ansible-vault で暗号化された変数ファイルに保持する。実行時に --ask-vault-pass または --vault-password-file で復号する。これによりシークレットを Git に安全に保存でき、プレイブックは冪等のまま保たれる。
PostgreSQL
ansible-vault create group_vars/postgres/vault.yml
# contents:
vault_pg_admin_password: "S3cret!"
# run:
ansible-playbook site.yml --ask-vault-pass4. ロール構造を構築する (roles/postgres、roles/mysql)
エンジンごとに 1 つのロールを作成し、ロジックを tasks/、defaults/、templates/、handlers/ のサブフォルダに分割する。この構造は再利用性を高める: デフォルト値は defaults/main.yml、jinja2 の構成テンプレートは templates/、「変更があった場合のみ再起動」のロジックは handlers/ に置く。ロールの雛形は 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. インストールと構成のタスクを冪等に書く
パッケージをインストールし、データディレクトリを初期化し、postgresql.conf/my.cnf をテンプレートから生成する。構成が変わった場合はハンドラー経由でサービスを再起動する。モジュールは冪等である: インストール済みのパッケージは再インストールされず、ファイルが変わっていなければハンドラーは起動されない。template モジュールで構成テンプレートを生成し、'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. データベースとユーザーのタスクを定義する
モジュールでデータベース、ユーザー、権限を作成し、パスワードは Vault の変数から取得する。community.postgresql のモジュールは冪等である: ユーザー/DB が存在すれば再作成せず、差分のみを適用する。権限は postgresql_privs で別途付与する。MySQL では mysql_user の priv フィールドを使う。
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. バックアップタスクとスケジュールを追加する
バックアップスクリプトをテンプレートからデプロイし、ansible.builtin.cron でスケジュールする。これによりバックアップジョブもコードとして管理される。バックアップ先ディレクトリ、保持期間、スケジュールは変数にする。cron モジュールは冪等で、エントリを 'name' で識別するため、再実行しても重複しない。
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"