Skip to content

Commit 61af3e6

Browse files
committed
add support pgbackrest
For bootstrap a patroni cluster and create replicas from backups.
1 parent 2277c0b commit 61af3e6

File tree

11 files changed

+322
-10
lines changed

11 files changed

+322
-10
lines changed

add_pgnode.yml

+25-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
- vars/main.yml
1212
- vars/system.yml
1313
- "vars/{{ ansible_os_family }}.yml"
14-
vars:
15-
existing_pgcluster: true
1614

1715
pre_tasks:
1816
- name: Checking Linux distribution
@@ -76,6 +74,31 @@
7674
- role: ntp
7775
- role: ssh-keys
7876

77+
- hosts: pgbackrest:postgres_cluster
78+
become: true
79+
become_method: sudo
80+
gather_facts: true
81+
any_errors_fatal: true
82+
vars_files:
83+
- vars/main.yml
84+
- "vars/{{ ansible_os_family }}.yml"
85+
roles:
86+
- role: pgbackrest
87+
when: pgbackrest_install|bool
88+
89+
- hosts: replica
90+
become: true
91+
become_method: sudo
92+
gather_facts: true
93+
any_errors_fatal: true
94+
vars_files:
95+
- vars/main.yml
96+
- vars/system.yml
97+
- "vars/{{ ansible_os_family }}.yml"
98+
vars:
99+
existing_pgcluster: true
100+
101+
roles:
79102
- role: wal-g
80103
when: wal_g_install|bool
81104

deploy_pgcluster.yml

+23
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,29 @@
8989
- role: ntp
9090
- role: ssh-keys
9191

92+
- hosts: pgbackrest:postgres_cluster
93+
become: true
94+
become_method: sudo
95+
gather_facts: true
96+
any_errors_fatal: true
97+
vars_files:
98+
- vars/main.yml
99+
- "vars/{{ ansible_os_family }}.yml"
100+
roles:
101+
- role: pgbackrest
102+
when: pgbackrest_install|bool
103+
104+
- hosts: postgres_cluster
105+
become: true
106+
become_method: sudo
107+
gather_facts: true
108+
any_errors_fatal: true
109+
vars_files:
110+
- vars/main.yml
111+
- vars/system.yml
112+
- "vars/{{ ansible_os_family }}.yml"
113+
114+
roles:
92115
- role: wal-g
93116
when: wal_g_install|bool
94117

inventory

+10-2
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,20 @@ replica
3636
# You can deploy the etcd cluster and the haproxy balancers on other dedicated servers.
3737

3838

39+
# if pgbackrest_install: true and "repo_host" is set (in vars/main.yml)
40+
[pgbackrest] # optional (Dedicated Repository Host)
41+
42+
3943
# Connection settings
4044
[all:vars]
4145
ansible_connection='ssh'
4246
ansible_ssh_port='22'
4347
ansible_user='root'
44-
ansible_ssh_pass='testpas' # "sshpass" package is required for use "ansible_ssh_pass"
45-
#ansible_ssh_private_key_file=
48+
ansible_ssh_pass='secretpassword' # "sshpass" package is required for use "ansible_ssh_pass"
49+
# ansible_ssh_private_key_file=
4650
# ansible_python_interpreter='/usr/bin/python3' # is required for use python3
4751

52+
[pgbackrest:vars]
53+
ansible_user='postgres'
54+
ansible_ssh_pass='secretpassword'
55+

roles/patroni/tasks/main.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -544,8 +544,8 @@
544544
command: "{{ postgresql_bin_dir }}/pg_isready -p {{ postgresql_port }}"
545545
register: pg_isready_result
546546
until: pg_isready_result.rc == 0
547-
retries: 30
548-
delay: 10
547+
retries: 1000
548+
delay: 30
549549
changed_when: false
550550
when: is_master == "true"
551551
tags: patroni, patroni_start_master
@@ -563,6 +563,8 @@
563563
become: true
564564
become_user: postgres
565565
command: "{{ postgresql_bin_dir }}/psql -p {{ postgresql_port }} -c 'SELECT pg_reload_conf()'"
566+
register: psql_reload_result
567+
changed_when: psql_reload_result.rc == 0
566568
failed_when: false # exec pg_reload_conf on all running postgres (to re-run with --tag pg_hba).
567569
when: existing_pgcluster is not defined or not existing_pgcluster|bool
568570
tags: patroni, pg_hba, pg_hba_generate

roles/patroni/templates/patroni.yml.j2

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ bootstrap:
3333
recovery_target_action: promote
3434
recovery_target_timeline: latest
3535
restore_command: wal-g wal-fetch %f %p
36+
{% endif %}
37+
{% if patroni_cluster_bootstrap_method == 'pgbackrest' %}
38+
pgbackrest:
39+
command: /etc/patroni/pgbackrest_bootstrap.sh
40+
keep_existing_recovery_conf: True
3641
{% endif %}
3742
dcs:
3843
ttl: {{ patroni_ttl |d(30, true) |int }}

roles/pgbackrest/tasks/main.yml

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
# yamllint disable rule:line-length
3+
4+
- block: # Debian pgdg repo
5+
- name: Make sure pgdg apt key is installed
6+
apt_key:
7+
id: ACCC4CF8
8+
url: http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc
9+
10+
- name: Make sure pgdg repository is installed
11+
apt_repository:
12+
repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ ansible_distribution_release }}-pgdg main"
13+
14+
- name: Update apt cache
15+
apt:
16+
update_cache: true
17+
environment: "{{ proxy_env | default({}) }}"
18+
when:
19+
- installation_method == "repo"
20+
- ansible_os_family == "Debian"
21+
- pgbackrest_install_from_pgdg_repo|bool
22+
tags: pgbackrest, pgbackrest_repo, pgbackrest_install
23+
24+
- block: # RedHat pgdg repo
25+
- name: Get pgdg-redhat-repo-latest.noarch.rpm
26+
get_url:
27+
url: "https://download.postgresql.org/pub/repos/yum/reporpms/EL-{{ ansible_distribution_major_version }}-x86_64/pgdg-redhat-repo-latest.noarch.rpm" # noqa 204
28+
dest: /tmp/
29+
timeout: 30
30+
validate_certs: false
31+
32+
- name: Make sure pgdg repository is installed
33+
package:
34+
name: /tmp/pgdg-redhat-repo-latest.noarch.rpm
35+
state: present
36+
37+
- name: Clean yum cache
38+
command: yum clean all
39+
args:
40+
warn: false
41+
when: ansible_distribution_major_version == '7'
42+
43+
- name: Clean dnf cache
44+
command: dnf clean all
45+
args:
46+
warn: false
47+
when: ansible_distribution_major_version is version('8', '>=')
48+
environment: "{{ proxy_env | default({}) }}"
49+
when:
50+
- installation_method == "repo"
51+
- ansible_os_family == "RedHat"
52+
- pgbackrest_install_from_pgdg_repo|bool
53+
tags: pgbackrest, pgbackrest_repo, pgbackrest_install
54+
55+
- name: Install pgbackrest
56+
package:
57+
name: pgbackrest
58+
state: latest
59+
tags: pgbackrest, pgbackrest_install
60+
61+
- block:
62+
- name: Ensure config directory exist
63+
file:
64+
path: "{{ pgbackrest_conf_file | dirname }}"
65+
state: directory
66+
67+
- name: "Generate conf file {{ pgbackrest_conf_file }}"
68+
template:
69+
src: pgbackrest.conf.j2
70+
dest: "{{ pgbackrest_conf_file }}"
71+
owner: root
72+
group: root
73+
mode: 0644
74+
when: "'postgres_cluster' in group_names"
75+
tags: pgbackrest, pgbackrest_conf
76+
77+
# if pgbackrest_repo_type: "posix" and pgbackrest_repo_host is set
78+
- import_tasks: ssh_keys.yml
79+
when:
80+
- pgbackrest_repo_type|lower != "s3"
81+
- pgbackrest_repo_host is defined
82+
- pgbackrest_repo_host | length > 0
83+
tags: pgbackrest, pgbackrest_ssh_keys
84+
85+
- block: # if patroni_cluster_bootstrap_method: "pgbackrest"
86+
- name: Make sure the pgbackrest bootstrap script directory exist
87+
file:
88+
dest: /etc/patroni
89+
state: directory
90+
owner: postgres
91+
group: postgres
92+
93+
- name: Create /etc/patroni/pgbackrest_bootstrap.sh script
94+
template:
95+
src: templates/pgbackrest_bootstrap.sh.j2
96+
dest: /etc/patroni/pgbackrest_bootstrap.sh
97+
owner: postgres
98+
group: postgres
99+
mode: 0775
100+
when:
101+
- patroni_cluster_bootstrap_method is defined
102+
- patroni_cluster_bootstrap_method == "pgbackrest"
103+
- "'postgres_cluster' in group_names"
104+
tags: pgbackrest, pgbackrest_bootstrap_script
105+
106+
...

roles/pgbackrest/tasks/ssh_keys.yml

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
# yamllint disable rule:line-length
3+
4+
- name: ssh_keys | Ensure ssh key are created for "{{ pgbackrest_repo_user }}" user on pgbackrest server
5+
user:
6+
name: "{{ pgbackrest_repo_user }}"
7+
generate_ssh_key: true
8+
ssh_key_bits: 2048
9+
ssh_key_file: .ssh/id_rsa
10+
when: "'pgbackrest' in group_names"
11+
12+
- name: ssh_keys | Ensure ssh key are created for "postgres" user on database servers
13+
user:
14+
name: "postgres"
15+
generate_ssh_key: true
16+
ssh_key_bits: 2048
17+
ssh_key_file: .ssh/id_rsa
18+
when: "'postgres_cluster' in group_names"
19+
20+
- name: ssh_keys | Get public ssh key from pgbackrest server
21+
slurp:
22+
src: "~{{ pgbackrest_repo_user }}/.ssh/id_rsa.pub"
23+
register: pgbackrest_sshkey
24+
changed_when: false
25+
when: "'pgbackrest' in group_names"
26+
27+
- name: ssh_keys | Get public ssh key from database servers
28+
slurp:
29+
src: "~postgres/.ssh/id_rsa.pub"
30+
register: postgres_cluster_sshkey
31+
changed_when: false
32+
when: "'postgres_cluster' in group_names"
33+
34+
- name: ssh_keys | Add pgbackrest ssh key in "~postgres/.ssh/authorized_keys" on database servers
35+
authorized_key:
36+
user: postgres
37+
state: present
38+
key: "{{ hostvars[item].pgbackrest_sshkey['content'] | b64decode }}"
39+
loop: "{{ groups['pgbackrest'] }}"
40+
when: "'postgres_cluster' in group_names"
41+
42+
- name: ssh_keys | Add database ssh keys in "~{{ pgbackrest_repo_user }}/.ssh/authorized_keys" on pgbackrest server
43+
authorized_key:
44+
user: "{{ pgbackrest_repo_user }}"
45+
state: present
46+
key: "{{ hostvars[item].postgres_cluster_sshkey['content'] | b64decode }}"
47+
loop: "{{ groups['postgres_cluster'] }}"
48+
when: "'pgbackrest' in group_names"
49+
50+
- name: known_hosts | Get public ssh keys of hosts (ssh-keyscan)
51+
command: "ssh-keyscan -trsa -p {{ ansible_ssh_port | default(22) }} {{ item }}"
52+
loop: "{{ groups['all'] }}"
53+
register: ssh_known_host_keyscan
54+
changed_when: false
55+
56+
- name: known_hosts | add ssh public keys in "~postgres/.ssh/known_hosts" on database servers
57+
become: true
58+
become_user: postgres
59+
known_hosts:
60+
host: "{{ item.item }}"
61+
key: "{{ item.stdout }}"
62+
path: "~postgres/.ssh/known_hosts"
63+
no_log: true
64+
loop: "{{ ssh_known_host_keyscan.results }}"
65+
when: "'postgres_cluster' in group_names"
66+
67+
- name: known_hosts | add ssh public keys in "~{{ pgbackrest_repo_user }}/.ssh/known_hosts" on pgbackrest server
68+
become: true
69+
become_user: "{{ pgbackrest_repo_user }}"
70+
known_hosts:
71+
host: "{{ item.item }}"
72+
key: "{{ item.stdout }}"
73+
path: "~{{ pgbackrest_repo_user }}/.ssh/known_hosts"
74+
no_log: true
75+
loop: "{{ ssh_known_host_keyscan.results }}"
76+
when: "'pgbackrest' in group_names"
77+
78+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[global]
2+
{% for global in pgbackrest_conf.global %}
3+
{{ global.option }}={{ global.value }}
4+
{% endfor %}
5+
6+
[{{ pgbackrest_stanza }}]
7+
{% for stanza in pgbackrest_conf.stanza %}
8+
{{ stanza.option }}={{ stanza.value }}
9+
{% endfor %}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env bash
2+
{% raw %}
3+
while getopts ":-:" optchar; do
4+
[[ "${optchar}" == "-" ]] || continue
5+
case "${OPTARG}" in
6+
datadir=* )
7+
DATA_DIR=${OPTARG#*=}
8+
;;
9+
scope=* )
10+
SCOPE=${OPTARG#*=}
11+
;;
12+
esac
13+
done
14+
{% endraw %}
15+
16+
{{ pgbackrest_patroni_cluster_bootstrap_command }}
17+

tags.md

+6
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,9 @@
7878
- wal_g
7979
- - wal_g_install
8080
- - wal_g_conf
81+
- pgbackrest
82+
- - pgbackrest_repo
83+
- - pgbackrest_install
84+
- - pgbackrest_conf
85+
- - pgbackrest_ssh_keys
86+
- - pgbackrest_bootstrap_script

0 commit comments

Comments
 (0)