Skip to content

Commit 1b5516e

Browse files
committed
Allow conversion master-standby to patroni cluster
Support the deployment of cluster over already existing and running PostgreSQL, including Replica (standby) servers. You can convert the basic replication configuration to the Patroni cluster. Specify the variable postgresql_exists='true' in inventory file, and postgresql_version, postgresql_data_dir variables (how in current servers) in vars/Debian.yml (or RedHat.yml).
1 parent 7b301b9 commit 1b5516e

File tree

2 files changed

+151
-137
lines changed

2 files changed

+151
-137
lines changed

inventory

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Please specify the ip addresses and connection settings for your environment
33
# The specified ip addresses will be used to listen by the cluster components.
44

5-
# "postgresql_exists='true'" if PostgreSQL is already exists and running on master (for initial deployment only)
5+
# "postgresql_exists='true'" if PostgreSQL is already exists and running
66
# "hostname=" variable is optional (used to change the server name)
77

88
# if dcs_exists: false and dcs_type: "etcd" (in vars/main.yml)
@@ -24,8 +24,8 @@
2424
10.128.64.140 hostname=pgnode01 postgresql_exists='false'
2525

2626
[replica]
27-
10.128.64.142 hostname=pgnode02
28-
10.128.64.143 hostname=pgnode03
27+
10.128.64.142 hostname=pgnode02 postgresql_exists='false'
28+
10.128.64.143 hostname=pgnode03 postgresql_exists='false'
2929

3030
[postgres_cluster:children]
3131
master

roles/patroni/tasks/main.yml

+148-134
Original file line numberDiff line numberDiff line change
@@ -362,139 +362,6 @@
362362
when: postgresql_wal_dir is defined and postgresql_wal_dir | length > 0
363363
tags: patroni, custom_wal_dir
364364

365-
- block: # when postgresql exists (master)
366-
- name: Prepare PostgreSQL | check that data directory "{{ postgresql_data_dir }}" is initialized on Master
367-
stat:
368-
path: "{{ postgresql_data_dir }}/PG_VERSION"
369-
register: pgdata_initialized
370-
371-
- name: Prepare PostgreSQL | data directory check result
372-
fail:
373-
msg: "Whoops! data directory {{ postgresql_data_dir }} is not initialized"
374-
when: not pgdata_initialized.stat.exists
375-
tags: patroni, patroni_check_init
376-
377-
- name: Prepare PostgreSQL | check PostgreSQL is started
378-
become: true
379-
become_user: postgres
380-
command: "{{ postgresql_bin_dir }}/pg_ctl status -D {{ postgresql_data_dir }}"
381-
register: pg_ctl_status_result
382-
changed_when: false
383-
failed_when:
384-
- pg_ctl_status_result.rc != 0
385-
- pg_ctl_status_result.rc != 3
386-
387-
# "Debian"
388-
- name: Prepare PostgreSQL | start PostgreSQL
389-
become: true
390-
become_user: postgres
391-
command: "/usr/bin/pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} start"
392-
when: pg_ctl_status_result.rc == 3 and
393-
ansible_os_family == "Debian"
394-
395-
# "RedHat" or PostgresPro
396-
- name: Prepare PostgreSQL | start PostgreSQL
397-
become: true
398-
become_user: postgres
399-
command: "{{ postgresql_bin_dir }}/pg_ctl start -D {{ postgresql_data_dir }}"
400-
when: pg_ctl_status_result.rc == 3 and
401-
(ansible_os_family == "RedHat" or
402-
postgresql_packages|join(" ") is search("postgrespro"))
403-
404-
- name: Prepare PostgreSQL | check PostgreSQL is accepting connections
405-
become: true
406-
become_user: postgres
407-
command: "{{ postgresql_bin_dir }}/pg_isready -p {{ postgresql_port }}"
408-
register: pg_isready_result
409-
until: pg_isready_result.rc == 0
410-
retries: 30
411-
delay: 10
412-
changed_when: false
413-
414-
- name: Prepare PostgreSQL | generate pg_hba.conf on Master
415-
template:
416-
src: templates/pg_hba.conf.j2
417-
dest: "{{ postgresql_conf_dir }}/pg_hba.conf"
418-
owner: postgres
419-
group: postgres
420-
mode: 0640
421-
422-
- name: Prepare PostgreSQL | reload for apply the pg_hba.conf
423-
become: true
424-
become_user: postgres
425-
command: "{{ postgresql_bin_dir }}/psql -p {{ postgresql_port }} -c 'SELECT pg_reload_conf()'"
426-
register: psql_reload_result
427-
failed_when: psql_reload_result.rc != 0
428-
429-
- name: Prepare PostgreSQL | make sure the user "{{ patroni_superuser_username }}" are present, and password does not differ from the specified
430-
postgresql_user:
431-
db: postgres
432-
name: "{{ patroni_superuser_username }}"
433-
password: "{{ patroni_superuser_password }}"
434-
encrypted: true
435-
role_attr_flags: "SUPERUSER"
436-
login_unix_socket: "{{ postgresql_unix_socket_dir }}"
437-
port: "{{ postgresql_port }}"
438-
state: present
439-
become: true
440-
become_user: postgres
441-
442-
- name: Prepare PostgreSQL | make sure the user "{{ patroni_replication_username }}" are present, and password does not differ from the specified
443-
postgresql_user:
444-
db: postgres
445-
name: "{{ patroni_replication_username }}"
446-
password: "{{ patroni_replication_password }}"
447-
encrypted: true
448-
role_attr_flags: "LOGIN,REPLICATION"
449-
login_unix_socket: "{{ postgresql_unix_socket_dir }}"
450-
port: "{{ postgresql_port }}"
451-
state: present
452-
become: true
453-
become_user: postgres
454-
455-
- name: Prepare PostgreSQL | waiting for CHECKPOINT to complete before stopping postgresql
456-
become: true
457-
become_user: postgres
458-
command: "{{ postgresql_bin_dir }}/psql -p {{ postgresql_port }} -c 'CHECKPOINT'"
459-
register: checkpoint_result
460-
until: checkpoint_result.rc == 0
461-
retries: 180
462-
delay: 15
463-
464-
# "Debian"
465-
- name: Prepare PostgreSQL | stop PostgreSQL (will be managed by patroni)
466-
become: true
467-
become_user: postgres
468-
command: "/usr/bin/pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} stop -m fast"
469-
register: stop_result
470-
until: stop_result.rc == 0
471-
retries: 10
472-
delay: 30
473-
when: ansible_os_family == "Debian" and
474-
postgresql_packages|join(" ") is not search("postgrespro")
475-
476-
# "RedHat" or PostgresPro
477-
- name: Prepare PostgreSQL | stop PostgreSQL (will be managed by patroni)
478-
become: true
479-
become_user: postgres
480-
command: "{{ postgresql_bin_dir }}/pg_ctl stop -D {{ postgresql_data_dir }} -m fast"
481-
register: stop_result
482-
until: stop_result.rc == 0
483-
retries: 30
484-
delay: 10
485-
when: ansible_os_family == "RedHat" or
486-
postgresql_packages|join(" ") is search("postgrespro")
487-
488-
- name: Prepare PostgreSQL | check PostgreSQL is stopped
489-
become: true
490-
become_user: postgres
491-
command: "{{ postgresql_bin_dir }}/pg_ctl status -D {{ postgresql_data_dir }}"
492-
register: pg_ctl_stop_result
493-
failed_when: pg_ctl_stop_result.rc != 3
494-
changed_when: false
495-
when: is_master == "true" and postgresql_exists == "true"
496-
tags: patroni, patroni_start_master
497-
498365
- block: # wheh postgresql NOT exists or PITR
499366
- name: Prepare PostgreSQL | make sure PostgreSQL data directory "{{ postgresql_data_dir }}" exists
500367
file:
@@ -565,9 +432,156 @@
565432
- directory
566433
when: (postgresql_wal_dir is defined and postgresql_wal_dir | length > 0) and
567434
patroni_cluster_bootstrap_method != "pgbackrest" # --delta restore
568-
when: postgresql_exists != "true"
435+
when: postgresql_exists != "true" or patroni_cluster_bootstrap_method != "initdb"
569436
tags: patroni, point_in_time_recovery
570437

438+
- block: # when postgresql exists
439+
- name: Prepare PostgreSQL | check that data directory "{{ postgresql_data_dir }}" is initialized
440+
stat:
441+
path: "{{ postgresql_data_dir }}/PG_VERSION"
442+
register: pgdata_initialized
443+
444+
- name: Prepare PostgreSQL | data directory check result
445+
fail:
446+
msg: "Whoops! data directory {{ postgresql_data_dir }} is not initialized"
447+
when: not pgdata_initialized.stat.exists
448+
tags: patroni, patroni_check_init
449+
450+
- block: # for master only
451+
- name: Prepare PostgreSQL | check PostgreSQL is started on Master
452+
become: true
453+
become_user: postgres
454+
command: "{{ postgresql_bin_dir }}/pg_ctl status -D {{ postgresql_data_dir }}"
455+
register: pg_ctl_status_result
456+
changed_when: false
457+
failed_when:
458+
- pg_ctl_status_result.rc != 0
459+
- pg_ctl_status_result.rc != 3
460+
461+
# "Debian"
462+
- name: Prepare PostgreSQL | start PostgreSQL on Master
463+
become: true
464+
become_user: postgres
465+
command: "/usr/bin/pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} start"
466+
register: pg_start_on_master
467+
when: pg_ctl_status_result.rc == 3 and
468+
(ansible_os_family == "Debian" and postgresql_packages|join(" ") is not search("postgrespro"))
469+
470+
# "RedHat" or PostgresPro
471+
- name: Prepare PostgreSQL | start PostgreSQL on Master
472+
become: true
473+
become_user: postgres
474+
command: "{{ postgresql_bin_dir }}/pg_ctl start -D {{ postgresql_data_dir }}"
475+
register: pg_start_on_master
476+
when: pg_ctl_status_result.rc == 3 and
477+
(ansible_os_family == "RedHat" or postgresql_packages|join(" ") is search("postgrespro"))
478+
479+
- name: Prepare PostgreSQL | check PostgreSQL is accepting connections
480+
become: true
481+
become_user: postgres
482+
command: "{{ postgresql_bin_dir }}/pg_isready -p {{ postgresql_port }}"
483+
register: pg_isready_result
484+
until: pg_isready_result.rc == 0
485+
retries: 30
486+
delay: 10
487+
changed_when: false
488+
489+
- name: Prepare PostgreSQL | generate pg_hba.conf on Master
490+
template:
491+
src: templates/pg_hba.conf.j2
492+
dest: "{{ postgresql_conf_dir }}/pg_hba.conf"
493+
owner: postgres
494+
group: postgres
495+
mode: 0640
496+
497+
- name: Prepare PostgreSQL | reload for apply the pg_hba.conf
498+
become: true
499+
become_user: postgres
500+
command: "{{ postgresql_bin_dir }}/psql -p {{ postgresql_port }} -c 'SELECT pg_reload_conf()'"
501+
register: psql_reload_result
502+
failed_when: psql_reload_result.rc != 0
503+
504+
- name: Prepare PostgreSQL | make sure the user "{{ patroni_superuser_username }}" are present, and password does not differ from the specified
505+
postgresql_user:
506+
db: postgres
507+
name: "{{ patroni_superuser_username }}"
508+
password: "{{ patroni_superuser_password }}"
509+
encrypted: true
510+
role_attr_flags: "SUPERUSER"
511+
login_unix_socket: "{{ postgresql_unix_socket_dir }}"
512+
port: "{{ postgresql_port }}"
513+
state: present
514+
become: true
515+
become_user: postgres
516+
517+
- name: Prepare PostgreSQL | make sure the user "{{ patroni_replication_username }}" are present, and password does not differ from the specified
518+
postgresql_user:
519+
db: postgres
520+
name: "{{ patroni_replication_username }}"
521+
password: "{{ patroni_replication_password }}"
522+
encrypted: true
523+
role_attr_flags: "LOGIN,REPLICATION"
524+
login_unix_socket: "{{ postgresql_unix_socket_dir }}"
525+
port: "{{ postgresql_port }}"
526+
state: present
527+
become: true
528+
become_user: postgres
529+
when: is_master == "true"
530+
531+
- name: Prepare PostgreSQL | check PostgreSQL is started
532+
become: true
533+
become_user: postgres
534+
command: "{{ postgresql_bin_dir }}/pg_ctl status -D {{ postgresql_data_dir }}"
535+
register: pg_ctl_status_result
536+
changed_when: false
537+
failed_when:
538+
- pg_ctl_status_result.rc != 0
539+
- pg_ctl_status_result.rc != 3
540+
541+
- name: Prepare PostgreSQL | waiting for CHECKPOINT to complete before stopping postgresql
542+
become: true
543+
become_user: postgres
544+
command: "{{ postgresql_bin_dir }}/psql -p {{ postgresql_port }} -c 'CHECKPOINT'"
545+
register: checkpoint_result
546+
until: checkpoint_result.rc == 0
547+
retries: 300
548+
delay: 10
549+
when: pg_ctl_status_result.rc == 0
550+
551+
# "Debian"
552+
- name: Prepare PostgreSQL | stop PostgreSQL (will be managed by patroni)
553+
become: true
554+
become_user: postgres
555+
command: "/usr/bin/pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} stop -m fast"
556+
register: stop_result
557+
until: stop_result.rc == 0
558+
retries: 300
559+
delay: 10
560+
when: (checkpoint_result.rc is defined and checkpoint_result.rc == 0) and
561+
(ansible_os_family == "Debian" and postgresql_packages|join(" ") is not search("postgrespro"))
562+
563+
# "RedHat" or PostgresPro
564+
- name: Prepare PostgreSQL | stop PostgreSQL (will be managed by patroni)
565+
become: true
566+
become_user: postgres
567+
command: "{{ postgresql_bin_dir }}/pg_ctl stop -D {{ postgresql_data_dir }} -m fast"
568+
register: stop_result
569+
until: stop_result.rc == 0
570+
retries: 300
571+
delay: 10
572+
when: (checkpoint_result.rc is defined and checkpoint_result.rc == 0) and
573+
(ansible_os_family == "RedHat" or postgresql_packages|join(" ") is search("postgrespro"))
574+
575+
- name: Prepare PostgreSQL | check PostgreSQL is stopped
576+
become: true
577+
become_user: postgres
578+
command: "{{ postgresql_bin_dir }}/pg_ctl status -D {{ postgresql_data_dir }}"
579+
register: pg_ctl_stop_result
580+
failed_when: pg_ctl_stop_result.rc != 3
581+
changed_when: false
582+
when: postgresql_exists == "true" and patroni_cluster_bootstrap_method == "initdb"
583+
tags: patroni, patroni_start_master
584+
571585
- block: # PITR (custom bootstrap)
572586
# Prepare (install pexpect, ruamel.yaml)
573587
- name: Prepare | Make sure the ansible required python library is exist

0 commit comments

Comments
 (0)