v2.0.0
This commit is contained in:
@@ -1,31 +1,87 @@
|
|||||||
- name: Wait for PostgreSQL socket
|
---
|
||||||
|
# Tworzenie bazy danych i użytkownika dla MailArchiver
|
||||||
|
# Ta rola uruchamia się TYLKO na primary
|
||||||
|
|
||||||
|
- name: Wait for PostgreSQL to be ready
|
||||||
wait_for:
|
wait_for:
|
||||||
path: "/var/run/postgresql/{{ pg_version }}-{{ pg_cluster }}/.s.PGSQL.5432"
|
path: "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
timeout: 60
|
timeout: 60
|
||||||
|
|
||||||
- name: Create db user
|
# --- Utworzenie użytkownika mailuser ---
|
||||||
become: true
|
- name: Create mailuser database user
|
||||||
become_user: postgres
|
|
||||||
postgresql_user:
|
postgresql_user:
|
||||||
name: mailuser
|
name: mailuser
|
||||||
password: "{{ mailuser_password }}"
|
password: "{{ mailuser_password }}"
|
||||||
login_host: "/var/run/postgresql/{{ pg_version }}-{{ pg_cluster }}/.s.PGSQL.5432"
|
role_attr_flags: CREATEDB
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
- name: Create database
|
db: postgres
|
||||||
become: true
|
become: true
|
||||||
become_user: postgres
|
become_user: postgres
|
||||||
|
|
||||||
|
# --- Utworzenie bazy mailarchiver ---
|
||||||
|
- name: Create mailarchiver database
|
||||||
postgresql_db:
|
postgresql_db:
|
||||||
name: mailarchiver
|
name: mailarchiver
|
||||||
owner: mailuser
|
owner: mailuser
|
||||||
login_host: "/var/run/postgresql/{{ pg_version }}-{{ pg_cluster }}/.s.PGSQL.5432"
|
encoding: UTF-8
|
||||||
|
lc_collate: en_US.UTF-8
|
||||||
- name: Grant schema rights
|
lc_ctype: en_US.UTF-8
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
become: true
|
become: true
|
||||||
become_user: postgres
|
become_user: postgres
|
||||||
|
|
||||||
|
# --- Przyznanie uprawnień ---
|
||||||
|
- name: Grant privileges on schema public
|
||||||
|
postgresql_query:
|
||||||
|
db: mailarchiver
|
||||||
|
query: |
|
||||||
|
GRANT USAGE ON SCHEMA public TO mailuser;
|
||||||
|
GRANT CREATE ON SCHEMA public TO mailuser;
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
# --- Default privileges dla tabel ---
|
||||||
|
- name: Set default privileges for tables
|
||||||
postgresql_query:
|
postgresql_query:
|
||||||
db: mailarchiver
|
db: mailarchiver
|
||||||
query: |
|
query: |
|
||||||
GRANT ALL ON SCHEMA public TO mailuser;
|
|
||||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
||||||
GRANT ALL ON TABLES TO mailuser;
|
GRANT ALL ON TABLES TO mailuser;
|
||||||
login_host: "/var/run/postgresql/{{ pg_version }}-{{ pg_cluster }}/.s.PGSQL.5432"
|
|
||||||
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
||||||
|
GRANT ALL ON SEQUENCES TO mailuser;
|
||||||
|
|
||||||
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
||||||
|
GRANT ALL ON FUNCTIONS TO mailuser;
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
|
||||||
|
# --- Sprawdzenie ---
|
||||||
|
- name: Verify mailarchiver database creation
|
||||||
|
postgresql_query:
|
||||||
|
db: mailarchiver
|
||||||
|
query: "SELECT datname, pg_database.datdba::regrole FROM pg_database WHERE datname = 'mailarchiver'"
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
register: db_verify
|
||||||
|
|
||||||
|
- name: Display database info
|
||||||
|
debug:
|
||||||
|
msg: "Database mailarchiver created: {{ db_verify.query_result }}"
|
||||||
|
|
||||||
|
- name: Verify mailuser permissions
|
||||||
|
postgresql_query:
|
||||||
|
db: mailarchiver
|
||||||
|
query: "SELECT * FROM information_schema.role_table_grants WHERE grantee='mailuser' LIMIT 5"
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
register: user_perms
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Display user permissions
|
||||||
|
debug:
|
||||||
|
msg: "Mailuser permissions: {{ user_perms.query_result | default('No permissions yet') }}"
|
||||||
|
|||||||
@@ -1,37 +1,92 @@
|
|||||||
- name: Install pgBackRest
|
---
|
||||||
apt:
|
# Instalacja i konfiguracja pgBackRest
|
||||||
name: pgbackrest
|
# Full backup: niedziela 2:00
|
||||||
state: present
|
# Incremental backup: codziennie 2:00 (oprócz niedzieli)
|
||||||
|
# Repozytorium backupu na pg2 (replica)
|
||||||
|
|
||||||
- name: Repo dir
|
# --- Auto-detect PostgreSQL version ---
|
||||||
|
- name: Detect PostgreSQL version
|
||||||
|
shell: "ls -d /etc/postgresql/*/ | head -1 | xargs basename"
|
||||||
|
register: pg_version_detect
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Set PostgreSQL variables from detection
|
||||||
|
set_fact:
|
||||||
|
pg_version: "{{ pg_version_detect.stdout | trim }}"
|
||||||
|
pg_cluster: "main"
|
||||||
|
pg_data: "/var/lib/postgresql/{{ pg_version_detect.stdout | trim }}/main"
|
||||||
|
pg_bin_path: "/usr/lib/postgresql/{{ pg_version_detect.stdout | trim }}/bin"
|
||||||
|
|
||||||
|
- name: Install pgBackRest and dependencies
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- pgbackrest
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
# --- Repozytorium backupu na replica ---
|
||||||
|
- name: Create backup repository directory (on replica)
|
||||||
file:
|
file:
|
||||||
path: /pgbackrest
|
path: /pgbackrest
|
||||||
state: directory
|
state: directory
|
||||||
owner: postgres
|
owner: postgres
|
||||||
mode: "750"
|
group: postgres
|
||||||
|
mode: "0750"
|
||||||
when: inventory_hostname in groups['replica']
|
when: inventory_hostname in groups['replica']
|
||||||
|
|
||||||
- name: Config
|
# --- Konfiguracja pgBackRest ---
|
||||||
|
- name: Deploy pgBackRest configuration
|
||||||
template:
|
template:
|
||||||
src: pgbackrest.conf.j2
|
src: pgbackrest.conf.j2
|
||||||
dest: /etc/pgbackrest.conf
|
dest: /etc/pgbackrest.conf
|
||||||
|
owner: postgres
|
||||||
|
group: postgres
|
||||||
|
mode: "0640"
|
||||||
|
|
||||||
- name: Create stanza
|
# --- Utworzenie stanza na primary ---
|
||||||
|
- name: Create pgBackRest stanza (on primary)
|
||||||
|
shell: pgbackrest --stanza=main stanza-create
|
||||||
|
become: true
|
||||||
become_user: postgres
|
become_user: postgres
|
||||||
command: pgbackrest --stanza=main stanza-create
|
when: inventory_hostname in groups['primary']
|
||||||
|
register: stanza_create
|
||||||
|
changed_when: "'CREATED' in stanza_create.stdout or 'already exists' not in stanza_create.stdout"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
# --- Full backup - niedziela 2:00 ---
|
||||||
|
- name: Schedule full backup weekly (Sunday 2:00 AM)
|
||||||
|
cron:
|
||||||
|
name: "pgBackRest full backup"
|
||||||
|
weekday: "0"
|
||||||
|
hour: "2"
|
||||||
|
minute: "0"
|
||||||
|
user: postgres
|
||||||
|
job: "pgbackrest --stanza=main backup --type=full"
|
||||||
|
state: present
|
||||||
when: inventory_hostname in groups['primary']
|
when: inventory_hostname in groups['primary']
|
||||||
|
|
||||||
- name: Full backup weekly
|
# --- Incremental backup - codziennie 2:00 (ale nie w niedzielę) ---
|
||||||
|
- name: Schedule incremental backup daily (Monday-Saturday 2:00 AM)
|
||||||
cron:
|
cron:
|
||||||
name: "pgbackrest full"
|
name: "pgBackRest incremental backup"
|
||||||
weekday: 0
|
weekday: "1-6"
|
||||||
hour: 2
|
hour: "2"
|
||||||
minute: 0
|
minute: "0"
|
||||||
job: "pgbackrest --stanza=main backup --type=full"
|
user: postgres
|
||||||
|
|
||||||
- name: Incremental backup daily
|
|
||||||
cron:
|
|
||||||
name: "pgbackrest incr"
|
|
||||||
hour: 2
|
|
||||||
minute: 0
|
|
||||||
job: "pgbackrest --stanza=main backup --type=incr"
|
job: "pgbackrest --stanza=main backup --type=incr"
|
||||||
|
state: present
|
||||||
|
when: inventory_hostname in groups['primary']
|
||||||
|
|
||||||
|
# --- Test configuration ---
|
||||||
|
- name: Test pgBackRest configuration (on primary)
|
||||||
|
shell: pgbackrest --stanza=main check
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
when: inventory_hostname in groups['primary']
|
||||||
|
register: pgbackrest_check
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Display pgBackRest check result
|
||||||
|
debug:
|
||||||
|
msg: "{{ pgbackrest_check.stdout }}"
|
||||||
|
when: inventory_hostname in groups['primary']
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
|
# pgBackRest Configuration
|
||||||
|
# Backup storage on replica (pg2)
|
||||||
|
# Archive destination: /pgbackrest
|
||||||
|
|
||||||
[main]
|
[main]
|
||||||
pg1-path=/var/lib/postgresql/16/main
|
pg1-path={{ pg_data }}
|
||||||
|
|
||||||
[global]
|
[global]
|
||||||
{% if inventory_hostname in groups['primary'] %}
|
|
||||||
repo1-host=pg2
|
|
||||||
{% endif %}
|
|
||||||
repo1-path=/pgbackrest
|
repo1-path=/pgbackrest
|
||||||
repo1-retention-full=2
|
repo1-retention-full=2
|
||||||
repo1-retention-diff=7
|
repo1-retention-diff=7
|
||||||
|
repo1-retention-incr=7
|
||||||
|
repo1-bundle=y
|
||||||
start-fast=y
|
start-fast=y
|
||||||
|
log-level-console=info
|
||||||
|
log-level-file=debug
|
||||||
|
archive-async=y
|
||||||
|
archive-timeout=60
|
||||||
|
check-strict=y
|
||||||
|
delta=y
|
||||||
|
recovery-option=recovery_target_timeline=latest
|
||||||
|
|
||||||
|
{% if inventory_hostname in groups['primary'] %}
|
||||||
|
repo1-host=pg2
|
||||||
|
repo1-host-user=postgres
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@@ -1,96 +1,111 @@
|
|||||||
- name: Install PostgreSQL packages
|
---
|
||||||
|
# Instalacja PostgreSQL (najnowsza wersja) i konfiguracja klastra
|
||||||
|
# Role: primary i replica
|
||||||
|
|
||||||
|
- name: Install PostgreSQL and contrib packages
|
||||||
apt:
|
apt:
|
||||||
name:
|
name:
|
||||||
- postgresql
|
- postgresql
|
||||||
- postgresql-contrib
|
- postgresql-contrib
|
||||||
|
- python3-psycopg2
|
||||||
update_cache: yes
|
update_cache: yes
|
||||||
|
state: present
|
||||||
|
|
||||||
# --- Detect PostgreSQL version and cluster ---
|
# --- Auto-detect PostgreSQL version ---
|
||||||
- name: Detect PostgreSQL version
|
- name: Detect installed PostgreSQL version
|
||||||
shell: "ls -d /etc/postgresql/*/ | head -n1 | xargs basename"
|
shell: "ls -d /etc/postgresql/*/ | head -1 | xargs basename"
|
||||||
register: pg_version_result
|
register: pg_version_detect
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
failed_when: pg_version_detect.rc != 0
|
||||||
|
|
||||||
- name: Detect cluster name
|
- name: Set PostgreSQL version variable
|
||||||
shell: "ls -d /var/lib/postgresql/*/main/ 2>/dev/null | head -n1 | xargs -I {} basename $(dirname {}) | tail -n1"
|
|
||||||
register: pg_cluster_result
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Set PostgreSQL version and cluster facts
|
|
||||||
set_fact:
|
set_fact:
|
||||||
pg_version: "{{ pg_version_result.stdout | trim }}"
|
pg_version: "{{ pg_version_detect.stdout | trim }}"
|
||||||
pg_cluster: "main"
|
pg_cluster: "main"
|
||||||
|
pg_data: "/var/lib/postgresql/{{ pg_version_detect.stdout | trim }}/main"
|
||||||
|
pg_config_path: "/etc/postgresql/{{ pg_version_detect.stdout | trim }}/main"
|
||||||
|
pg_bin_path: "/usr/lib/postgresql/{{ pg_version_detect.stdout | trim }}/bin"
|
||||||
|
|
||||||
- name: Define PostgreSQL cluster path
|
- name: Display detected PostgreSQL version
|
||||||
set_fact:
|
debug:
|
||||||
pg_cluster_path: "/etc/postgresql/{{ pg_version }}/{{ pg_cluster }}"
|
msg: "PostgreSQL {{ pg_version }} detected. Data path: {{ pg_data }}"
|
||||||
pg_data_path: "/var/lib/postgresql/{{ pg_version }}/{{ pg_cluster }}"
|
|
||||||
|
|
||||||
# --- Stop cluster before config ---
|
# --- Tworzenie logów PostgreSQL ---
|
||||||
- name: Stop PostgreSQL cluster
|
- name: Ensure log directory exists
|
||||||
shell: "pg_ctlcluster {{ pg_version }} {{ pg_cluster }} stop"
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
# --- Remove broken cluster configuration if exists ---
|
|
||||||
- name: Remove broken cluster configuration
|
|
||||||
shell: "rm -rf {{ pg_cluster_path }} {{ pg_data_path }}"
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
# --- Ensure data directory exists and is owned by postgres ---
|
|
||||||
- name: Create PostgreSQL data directory
|
|
||||||
file:
|
file:
|
||||||
path: "{{ pg_data_path }}"
|
path: /var/log/postgresql
|
||||||
|
state: directory
|
||||||
|
owner: postgres
|
||||||
|
group: postgres
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
# --- Inicjalizacja klastra ---
|
||||||
|
- name: Check if cluster data directory exists
|
||||||
|
stat:
|
||||||
|
path: "{{ pg_data }}"
|
||||||
|
register: pg_data_stat
|
||||||
|
|
||||||
|
- name: Create cluster data directory if not exists
|
||||||
|
file:
|
||||||
|
path: "{{ pg_data }}"
|
||||||
state: directory
|
state: directory
|
||||||
owner: postgres
|
owner: postgres
|
||||||
group: postgres
|
group: postgres
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
|
when: not pg_data_stat.stat.exists
|
||||||
|
|
||||||
# --- Initialize database cluster ---
|
|
||||||
- name: Initialize PostgreSQL cluster
|
- name: Initialize PostgreSQL cluster
|
||||||
shell: "sudo -u postgres /usr/lib/postgresql/{{ pg_version }}/bin/initdb -D {{ pg_data_path }} --encoding=UTF8 --locale=en_US.UTF-8"
|
shell: "{{ pg_bin_path }}/initdb -D {{ pg_data }} --encoding=UTF8 --locale=en_US.UTF-8"
|
||||||
ignore_errors: true
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
when: not pg_data_stat.stat.exists
|
||||||
|
register: initdb_result
|
||||||
|
|
||||||
# --- Ensure cluster config directory exists ---
|
- name: Create config directory for cluster
|
||||||
- name: Ensure cluster config directory exists
|
|
||||||
file:
|
file:
|
||||||
path: "{{ pg_cluster_path }}"
|
path: "{{ pg_config_path }}"
|
||||||
state: directory
|
state: directory
|
||||||
owner: postgres
|
owner: postgres
|
||||||
group: postgres
|
group: postgres
|
||||||
mode: "0700"
|
mode: "0755"
|
||||||
|
|
||||||
# --- Configure PostgreSQL ---
|
# --- Konfiguracja PostgreSQL ---
|
||||||
- name: postgresql.conf
|
- name: Deploy postgresql.conf
|
||||||
template:
|
template:
|
||||||
src: postgresql.conf.j2
|
src: postgresql.conf.j2
|
||||||
dest: "{{ pg_cluster_path }}/postgresql.conf"
|
dest: "{{ pg_config_path }}/postgresql.conf"
|
||||||
owner: postgres
|
owner: postgres
|
||||||
group: postgres
|
group: postgres
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
|
notify: restart postgresql
|
||||||
|
|
||||||
- name: pg_hba.conf
|
- name: Deploy pg_hba.conf
|
||||||
template:
|
template:
|
||||||
src: pg_hba.conf.j2
|
src: pg_hba.conf.j2
|
||||||
dest: "{{ pg_cluster_path }}/pg_hba.conf"
|
dest: "{{ pg_config_path }}/pg_hba.conf"
|
||||||
owner: postgres
|
owner: postgres
|
||||||
group: postgres
|
group: postgres
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
|
notify: restart postgresql
|
||||||
|
|
||||||
# --- Start cluster ---
|
# --- Uruchomienie PostgreSQL ---
|
||||||
- name: Start PostgreSQL cluster
|
- name: Enable and start PostgreSQL service
|
||||||
shell: "sudo -u postgres /usr/lib/postgresql/{{ pg_version }}/bin/pg_ctl -D {{ pg_data_path }} -l /var/log/postgresql/postgresql-{{ pg_version }}-{{ pg_cluster }}.log start"
|
systemd:
|
||||||
ignore_errors: true
|
name: postgresql
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
# --- Wait for socket to be ready ---
|
# --- Czekanie na socket ---
|
||||||
- name: Wait for PostgreSQL socket
|
- name: Wait for PostgreSQL socket to be ready
|
||||||
wait_for:
|
wait_for:
|
||||||
path: "/var/run/postgresql/{{ pg_version }}-{{ pg_cluster }}/.s.PGSQL.5432"
|
path: "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
timeout: 60
|
timeout: 60
|
||||||
|
|
||||||
# --- Install Python PostgreSQL libraries ---
|
|
||||||
- name: Install python postgres libraries
|
|
||||||
apt:
|
|
||||||
name:
|
|
||||||
- python3-psycopg2
|
|
||||||
state: present
|
state: present
|
||||||
update_cache: yes
|
|
||||||
|
# Handlery
|
||||||
|
- name: restart postgresql
|
||||||
|
systemd:
|
||||||
|
name: postgresql
|
||||||
|
state: restarted
|
||||||
|
listen: "restart postgresql"
|
||||||
|
|||||||
15
roles/postgres/templates/pg_hba.conf.j2
Normal file
15
roles/postgres/templates/pg_hba.conf.j2
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# PostgreSQL 16 pg_hba.conf - Host Based Authentication
|
||||||
|
# TYPE DATABASE USER ADDRESS METHOD
|
||||||
|
|
||||||
|
# Local connections
|
||||||
|
local all postgres peer
|
||||||
|
local all all peer
|
||||||
|
|
||||||
|
# Replication from pg2 (10.0.0.2)
|
||||||
|
host replication replicator 10.0.0.2/32 md5
|
||||||
|
|
||||||
|
# Applications and MailArchiver
|
||||||
|
host all all 10.0.0.0/24 md5
|
||||||
|
|
||||||
|
# IPv6 local
|
||||||
|
host all all ::1/128 md5
|
||||||
51
roles/postgres/templates/postgresql.conf.j2
Normal file
51
roles/postgres/templates/postgresql.conf.j2
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# PostgreSQL Configuration for Production
|
||||||
|
# Debian 13 - najnowsza dostępna wersja
|
||||||
|
# Primary: pg1, Replica: pg2
|
||||||
|
|
||||||
|
# --- Network ---
|
||||||
|
listen_addresses = '*'
|
||||||
|
max_connections = 200
|
||||||
|
port = 5432
|
||||||
|
|
||||||
|
# --- Memory (dla 8GB RAM) ---
|
||||||
|
shared_buffers = 2GB
|
||||||
|
effective_cache_size = 6GB
|
||||||
|
work_mem = 64MB
|
||||||
|
maintenance_work_mem = 1GB
|
||||||
|
|
||||||
|
# --- WAL and Logging ---
|
||||||
|
wal_level = replica
|
||||||
|
wal_compression = on
|
||||||
|
max_wal_senders = 10
|
||||||
|
max_replication_slots = 10
|
||||||
|
wal_keep_size = 10GB
|
||||||
|
|
||||||
|
# --- Archiving (dla pgBackRest) ---
|
||||||
|
archive_mode = on
|
||||||
|
archive_command = 'pgbackrest --stanza=main archive-push %p'
|
||||||
|
archive_timeout = 300
|
||||||
|
|
||||||
|
# --- Checkpoints ---
|
||||||
|
checkpoint_timeout = 15min
|
||||||
|
checkpoint_completion_target = 0.9
|
||||||
|
max_wal_size = 64GB
|
||||||
|
min_wal_size = 16GB
|
||||||
|
|
||||||
|
# --- Logging ---
|
||||||
|
log_directory = '/var/log/postgresql'
|
||||||
|
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
|
||||||
|
log_truncate_on_rotation = on
|
||||||
|
log_rotation_age = 1d
|
||||||
|
log_rotation_size = 100MB
|
||||||
|
log_min_duration_statement = 1000
|
||||||
|
log_connections = on
|
||||||
|
log_disconnections = on
|
||||||
|
log_duration = off
|
||||||
|
|
||||||
|
# --- Replication slots ---
|
||||||
|
max_replication_slots = 10
|
||||||
|
|
||||||
|
# --- Performance ---
|
||||||
|
random_page_cost = 1.1
|
||||||
|
effective_io_concurrency = 200
|
||||||
|
synchronous_commit = local
|
||||||
@@ -1,28 +1,120 @@
|
|||||||
- name: Create replicator user (on primary)
|
---
|
||||||
|
# Konfiguracja replikacji PostgreSQL
|
||||||
|
# Ta rola uruchamia się na replica (pg2)
|
||||||
|
# Tworzy użytkownika replicator i base backup z primary
|
||||||
|
|
||||||
|
# --- Auto-detect PostgreSQL version na primary ---
|
||||||
|
- name: Detect PostgreSQL version on primary
|
||||||
|
shell: "ls -d /etc/postgresql/*/ | head -1 | xargs basename"
|
||||||
|
register: pg_version_detect
|
||||||
|
changed_when: false
|
||||||
delegate_to: pg1
|
delegate_to: pg1
|
||||||
become_user: postgres
|
run_once: true
|
||||||
|
|
||||||
|
- name: Set PostgreSQL variables from detection
|
||||||
|
set_fact:
|
||||||
|
pg_version: "{{ pg_version_detect.stdout | trim }}"
|
||||||
|
pg_cluster: "main"
|
||||||
|
pg_data: "/var/lib/postgresql/{{ pg_version_detect.stdout | trim }}/main"
|
||||||
|
pg_bin_path: "/usr/lib/postgresql/{{ pg_version_detect.stdout | trim }}/bin"
|
||||||
|
|
||||||
|
- name: Wait for PostgreSQL on primary to be ready
|
||||||
|
wait_for:
|
||||||
|
host: pg1
|
||||||
|
port: 5432
|
||||||
|
timeout: 300
|
||||||
|
delegate_to: pg1
|
||||||
|
|
||||||
|
# --- Utworzenie użytkownika replicator na primary ---
|
||||||
|
- name: Create replicator user on primary
|
||||||
postgresql_user:
|
postgresql_user:
|
||||||
name: replicator
|
name: replicator
|
||||||
password: "{{ replicator_password }}"
|
password: "{{ replicator_password }}"
|
||||||
role_attr_flags: REPLICATION,LOGIN
|
role_attr_flags: REPLICATION,LOGIN
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
db: postgres
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
delegate_to: pg1
|
||||||
|
|
||||||
- name: Stop postgres
|
# --- Przygotowanie replica ---
|
||||||
service:
|
- name: Stop PostgreSQL on replica
|
||||||
|
systemd:
|
||||||
name: postgresql
|
name: postgresql
|
||||||
state: stopped
|
state: stopped
|
||||||
|
|
||||||
- name: Remove old data
|
- name: Remove existing cluster data on replica
|
||||||
file:
|
file:
|
||||||
path: "{{ pg_data }}"
|
path: "{{ pg_data }}"
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
- name: Base backup
|
# --- Base backup z primary ---
|
||||||
|
- name: Create replication slot on primary
|
||||||
|
postgresql_query:
|
||||||
|
db: postgres
|
||||||
|
query: "SELECT pg_create_physical_replication_slot('pg2_slot')"
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
become_user: postgres
|
become_user: postgres
|
||||||
command: >
|
delegate_to: pg1
|
||||||
pg_basebackup -h pg1 -D {{ pg_data }}
|
ignore_errors: true
|
||||||
-U replicator -Fp -Xs -P -R
|
|
||||||
|
|
||||||
- name: Start postgres
|
- name: Perform base backup from primary to replica
|
||||||
service:
|
shell: |
|
||||||
|
pg_basebackup \
|
||||||
|
-h pg1 \
|
||||||
|
-D {{ pg_data }} \
|
||||||
|
-U replicator \
|
||||||
|
-Fp \
|
||||||
|
-Xs \
|
||||||
|
-P \
|
||||||
|
-R \
|
||||||
|
-S pg2_slot
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
register: basebackup_result
|
||||||
|
|
||||||
|
- name: Fix permissions on data directory
|
||||||
|
file:
|
||||||
|
path: "{{ pg_data }}"
|
||||||
|
owner: postgres
|
||||||
|
group: postgres
|
||||||
|
mode: "0700"
|
||||||
|
recurse: yes
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Configure replication settings
|
||||||
|
lineinfile:
|
||||||
|
path: "{{ pg_data }}/standby.signal"
|
||||||
|
line: ""
|
||||||
|
create: yes
|
||||||
|
owner: postgres
|
||||||
|
group: postgres
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
# --- Uruchomienie replica ---
|
||||||
|
- name: Start PostgreSQL on replica
|
||||||
|
systemd:
|
||||||
name: postgresql
|
name: postgresql
|
||||||
state: started
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Wait for PostgreSQL replica to be ready
|
||||||
|
wait_for:
|
||||||
|
path: "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
|
timeout: 60
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Verify replication on primary
|
||||||
|
postgresql_query:
|
||||||
|
db: postgres
|
||||||
|
query: "SELECT application_name, client_addr, state FROM pg_stat_replication"
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
delegate_to: pg1
|
||||||
|
register: replication_status
|
||||||
|
|
||||||
|
- name: Display replication status
|
||||||
|
debug:
|
||||||
|
msg: "{{ replication_status.query_result }}"
|
||||||
|
|||||||
@@ -1,19 +1,122 @@
|
|||||||
- name: Stop postgres on primary
|
---
|
||||||
service:
|
# Przywrócenie primary z pg2 (replica)
|
||||||
|
# Używany w przypadku awarii pg1
|
||||||
|
|
||||||
|
# --- Auto-detect PostgreSQL version na replica ---
|
||||||
|
- name: Detect PostgreSQL version on replica
|
||||||
|
shell: "ls -d /etc/postgresql/*/ | head -1 | xargs basename"
|
||||||
|
register: pg_version_detect
|
||||||
|
changed_when: false
|
||||||
|
delegate_to: pg2
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
- name: Set PostgreSQL variables from detection
|
||||||
|
set_fact:
|
||||||
|
pg_version: "{{ pg_version_detect.stdout | trim }}"
|
||||||
|
pg_cluster: "main"
|
||||||
|
pg_data: "/var/lib/postgresql/{{ pg_version_detect.stdout | trim }}/main"
|
||||||
|
pg_bin_path: "/usr/lib/postgresql/{{ pg_version_detect.stdout | trim }}/bin"
|
||||||
|
|
||||||
|
- name: Wait for replica to be accessible
|
||||||
|
wait_for:
|
||||||
|
host: pg2
|
||||||
|
port: 5432
|
||||||
|
timeout: 300
|
||||||
|
|
||||||
|
# --- Promowanie replica ---
|
||||||
|
- name: Promote replica to primary
|
||||||
|
shell: "{{ pg_bin_path }}/pg_ctl promote -D {{ pg_data }}"
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
delegate_to: pg2
|
||||||
|
register: promote_result
|
||||||
|
|
||||||
|
- name: Wait for promoted replica to be ready
|
||||||
|
wait_for:
|
||||||
|
host: pg2
|
||||||
|
port: 5432
|
||||||
|
timeout: 60
|
||||||
|
|
||||||
|
# --- Przywrócenie na pg1 ---
|
||||||
|
- name: Stop PostgreSQL on primary (pg1)
|
||||||
|
systemd:
|
||||||
name: postgresql
|
name: postgresql
|
||||||
state: stopped
|
state: stopped
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
- name: Remove old data on primary
|
- name: Remove old cluster data on primary
|
||||||
file:
|
file:
|
||||||
path: "{{ pg_data }}"
|
path: "{{ pg_data }}"
|
||||||
state: absent
|
state: absent
|
||||||
|
become: true
|
||||||
|
|
||||||
- name: Restore base backup from replica
|
# --- Base backup z nowego primary (pg2) ---
|
||||||
|
- name: Perform base backup from new primary (pg2)
|
||||||
|
shell: |
|
||||||
|
pg_basebackup \
|
||||||
|
-h pg2 \
|
||||||
|
-D {{ pg_data }} \
|
||||||
|
-U replicator \
|
||||||
|
-Fp \
|
||||||
|
-Xs \
|
||||||
|
-P \
|
||||||
|
-R
|
||||||
|
become: true
|
||||||
become_user: postgres
|
become_user: postgres
|
||||||
command: >
|
register: restore_basebackup
|
||||||
pg_basebackup -h pg2 -D {{ pg_data }} -U replicator -Fp -Xs -P -R
|
|
||||||
|
|
||||||
- name: Start postgres on primary
|
- name: Fix permissions on restored data directory
|
||||||
service:
|
file:
|
||||||
|
path: "{{ pg_data }}"
|
||||||
|
owner: postgres
|
||||||
|
group: postgres
|
||||||
|
mode: "0700"
|
||||||
|
recurse: yes
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Configure recovery settings
|
||||||
|
lineinfile:
|
||||||
|
path: "{{ pg_data }}/standby.signal"
|
||||||
|
line: ""
|
||||||
|
create: yes
|
||||||
|
owner: postgres
|
||||||
|
group: postgres
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
# --- Uruchomienie pg1 ---
|
||||||
|
- name: Start PostgreSQL on primary
|
||||||
|
systemd:
|
||||||
name: postgresql
|
name: postgresql
|
||||||
state: started
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Wait for PostgreSQL to start
|
||||||
|
wait_for:
|
||||||
|
path: "/var/run/postgresql/.s.PGSQL.5432"
|
||||||
|
timeout: 60
|
||||||
|
|
||||||
|
# --- Weryfikacja ---
|
||||||
|
- name: Verify primary is accessible
|
||||||
|
postgresql_query:
|
||||||
|
db: postgres
|
||||||
|
query: "SELECT version()"
|
||||||
|
login_unix_socket_directory: /var/run/postgresql
|
||||||
|
become: true
|
||||||
|
become_user: postgres
|
||||||
|
register: version_check
|
||||||
|
|
||||||
|
- name: Display restoration result
|
||||||
|
debug:
|
||||||
|
msg: "Primary restored successfully. PostgreSQL: {{ version_check.query_result[0].version }}"
|
||||||
|
|
||||||
|
- name: Display manual failover instructions
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Restoration complete!
|
||||||
|
|
||||||
|
Next steps:
|
||||||
|
1. Verify pg1 and pg2 connectivity
|
||||||
|
2. Update application connection strings if needed
|
||||||
|
3. Monitor replication status:
|
||||||
|
SELECT * FROM pg_stat_replication;
|
||||||
|
4. Schedule regular test restores
|
||||||
|
|||||||
Reference in New Issue
Block a user