Skip to content

Commit e7c0f91

Browse files
committed
Implement the ability to deploy of cluster components on different servers.
By default, all cluster components will be deployed to PostgreSQL servers. But, you may need to distribute the cluster components (ex. etcd cluster nodes) to different servers. Now you can deploy the etcd cluster and the haproxy balancers to other dedicated servers.
1 parent 91b2257 commit e7c0f91

14 files changed

+236
-71
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ See the vars/[main.yml](./vars/main.yml), [system.yml](./vars/system.yml) and ([
176176
After you successfully deployed your PostgreSQL HA cluster, you may need to scale it further. \
177177
Use the `add_pgnode.yml` playbook for this.
178178

179-
> :grey_exclamation: This playbook does not scaling the etcd cluster.
179+
> :grey_exclamation: This playbook does not scaling the etcd cluster and haproxy balancers.
180180
181181
During the run this playbook, the new nodes will be prepared in the same way as when first deployment the cluster. But unlike the initial deployment, all the necessary **configuration files will be copied from the master server**.
182182

add_pgnode.yml

+41-14
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,71 @@
1313
vars:
1414
existing_pgcluster: true
1515

16-
1716
pre_tasks:
1817
- import_tasks: tasks/check_system.yml
1918

20-
- import_tasks: tasks/add-repository.yml
21-
tags: [ add_repo ]
19+
- import_tasks: tasks/hostname.yml
20+
when: hostname is defined and hostname | length > 0
21+
tags: hostname
2222

23-
- import_tasks: tasks/packages.yml
24-
tags: [ install_packages ]
23+
- name: Make sure the gnupg package is present
24+
apt:
25+
name: gnupg
26+
state: present
27+
update_cache: yes
28+
environment: '{{ proxy_env | default({}) }}'
29+
when: ansible_os_family == "Debian" and installation_method == "repo"
30+
tags: [ add_repo, install_packages, install_postgres ]
2531

26-
- import_tasks: tasks/sudo.yml
27-
tags: [ sudo, postgres_sudo ]
32+
- name: Firewall | build a firewall_ports_dynamic_var
33+
set_fact:
34+
firewall_ports_dynamic_var: "{{ firewall_ports_dynamic_var |default([]) }} + {{ firewall_allowed_tcp_ports_for[item] }}"
35+
loop: '{{ hostvars[inventory_hostname].group_names }}'
36+
when: firewall_enabled_at_boot|bool
37+
tags: firewall
38+
39+
- name: Firewall | build a firewall_rules_dynamic_var
40+
set_fact:
41+
firewall_rules_dynamic_var: "{{ firewall_rules_dynamic_var |default([]) }} + {{ firewall_additional_rules_for[item] }}"
42+
loop: '{{ hostvars[inventory_hostname].group_names }}'
43+
when: firewall_enabled_at_boot|bool
44+
tags: firewall
2845

2946
roles:
3047
- role: ansible-role-firewall
48+
environment: '{{ proxy_env | default({}) }}'
49+
vars:
50+
firewall_allowed_tcp_ports: '{{ firewall_ports_dynamic_var | unique }}'
51+
firewall_additional_rules: '{{ firewall_rules_dynamic_var | unique }}'
52+
when: firewall_enabled_at_boot|bool
3153
tags: firewall
3254

3355
tasks:
3456
- meta: flush_handlers
3557

58+
- import_tasks: tasks/add-repository.yml
59+
tags: [ add_repo ]
60+
61+
- import_tasks: tasks/packages.yml
62+
tags: [ install_packages ]
63+
64+
- import_tasks: tasks/sudo.yml
65+
tags: [ sudo, postgres_sudo ]
66+
3667
- import_tasks: tasks/configure.yml
3768
tags: configure
3869

39-
- import_tasks: tasks/patroni.yml
40-
tags: patroni
41-
4270
- import_tasks: tasks/pgbouncer.yml
4371
when: install_pgbouncer == "true"
4472
tags: pgbouncer
4573

46-
- import_tasks: tasks/haproxy.yml
47-
when: with_haproxy_load_balancing == "true"
48-
tags: load_balancing
49-
5074
- import_tasks: tasks/vip-manager.yml
5175
when: with_haproxy_load_balancing != "true"
5276
tags: [ vip, vip_manager ]
5377

78+
- import_tasks: tasks/patroni.yml
79+
tags: patroni
80+
5481
# finish (info)
5582
- import_tasks: tasks/deploy_finish.yml
5683
tags: [ cluster_info, cluster_status ]

deploy_pgcluster.yml

+98-18
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,138 @@
11
---
22

3-
- name: Deploy PostgreSQL High-Availability Cluster (based on "Patroni" and "DCS(etcd)")
4-
hosts: postgres_cluster
3+
- name: Deploy PostgreSQL High-Availability Cluster (based on "Patroni" and "DCS({{ dcs_type }})")
4+
hosts: postgres_cluster:etcd_cluster:balancers
55
become: true
66
become_method: sudo
7-
any_errors_fatal: true
87
gather_facts: true
8+
any_errors_fatal: true
99
vars_files:
1010
- vars/main.yml
1111
- vars/system.yml
1212
- "vars/{{ ansible_os_family }}.yml"
1313

14-
1514
pre_tasks:
1615
- import_tasks: tasks/check_system.yml
1716

18-
- import_tasks: tasks/add-repository.yml
19-
tags: [ add_repo ]
20-
21-
- import_tasks: tasks/packages.yml
22-
tags: [ install_packages ]
17+
- import_tasks: tasks/hostname.yml
18+
when: hostname is defined and hostname | length > 0
19+
tags: hostname
20+
21+
- name: Make sure the gnupg package is present
22+
apt:
23+
name: gnupg
24+
state: present
25+
update_cache: yes
26+
environment: '{{ proxy_env | default({}) }}'
27+
when: ansible_os_family == "Debian" and installation_method == "repo"
28+
tags: [ add_repo, install_packages, install_postgres ]
29+
30+
- name: Firewall | build a firewall_ports_dynamic_var
31+
set_fact:
32+
firewall_ports_dynamic_var: "{{ firewall_ports_dynamic_var |default([]) }} + {{ firewall_allowed_tcp_ports_for[item] }}"
33+
loop: '{{ hostvars[inventory_hostname].group_names }}'
34+
when: firewall_enabled_at_boot|bool
35+
tags: firewall
2336

24-
- import_tasks: tasks/sudo.yml
25-
tags: [ sudo, postgres_sudo ]
37+
- name: Firewall | build a firewall_rules_dynamic_var
38+
set_fact:
39+
firewall_rules_dynamic_var: "{{ firewall_rules_dynamic_var |default([]) }} + {{ firewall_additional_rules_for[item] }}"
40+
loop: '{{ hostvars[inventory_hostname].group_names }}'
41+
when: firewall_enabled_at_boot|bool
42+
tags: firewall
2643

2744
roles:
2845
- role: ansible-role-firewall
46+
environment: '{{ proxy_env | default({}) }}'
47+
vars:
48+
firewall_allowed_tcp_ports: '{{ firewall_ports_dynamic_var | unique }}'
49+
firewall_additional_rules: '{{ firewall_rules_dynamic_var | unique }}'
50+
when: firewall_enabled_at_boot|bool
2951
tags: firewall
3052

53+
54+
- hosts: etcd_cluster
55+
become: true
56+
become_method: sudo
57+
any_errors_fatal: true
58+
gather_facts: true
59+
vars_files:
60+
- vars/main.yml
61+
- vars/system.yml
62+
- "vars/{{ ansible_os_family }}.yml"
63+
3164
tasks:
3265
- meta: flush_handlers
3366

34-
- import_tasks: tasks/configure.yml
35-
tags: configure
67+
- import_tasks: tasks/timezone.yml
68+
when: timezone is defined and timezone | length > 0
69+
ignore_errors: yes
70+
tags: [ timezone, configure ]
71+
72+
- import_tasks: tasks/ntp.yml
73+
when: ntp_enabled is defined and ntp_enabled == "true"
74+
ignore_errors: yes
75+
tags: [ ntp, configure ]
3676

3777
- import_tasks: tasks/etcd.yml
3878
when: dcs_exists == "false" and dcs_type == "etcd"
3979
tags: [ etcd, etcd_cluster ]
4080

41-
- import_tasks: tasks/patroni.yml
42-
tags: patroni
4381

44-
- import_tasks: tasks/pgbouncer.yml
45-
when: install_pgbouncer == "true"
46-
tags: pgbouncer
82+
- hosts: balancers
83+
become: true
84+
become_method: sudo
85+
any_errors_fatal: true
86+
gather_facts: true
87+
vars_files:
88+
- vars/main.yml
89+
- "vars/{{ ansible_os_family }}.yml"
90+
91+
tasks:
92+
- meta: flush_handlers
4793

4894
- import_tasks: tasks/haproxy.yml
4995
when: with_haproxy_load_balancing == "true" and cluster_vip | length > 0
5096
tags: load_balancing
5197

98+
99+
- hosts: postgres_cluster
100+
become: true
101+
become_method: sudo
102+
any_errors_fatal: true
103+
gather_facts: true
104+
vars_files:
105+
- vars/main.yml
106+
- vars/system.yml
107+
- "vars/{{ ansible_os_family }}.yml"
108+
109+
pre_tasks:
110+
- meta: flush_handlers
111+
112+
- import_tasks: tasks/add-repository.yml
113+
tags: [ add_repo ]
114+
115+
- import_tasks: tasks/packages.yml
116+
tags: [ install_packages ]
117+
118+
- import_tasks: tasks/sudo.yml
119+
tags: [ sudo, postgres_sudo ]
120+
121+
- import_tasks: tasks/configure.yml
122+
tags: configure
123+
124+
tasks:
125+
- import_tasks: tasks/pgbouncer.yml
126+
when: install_pgbouncer == "true"
127+
tags: pgbouncer
128+
52129
- import_tasks: tasks/vip-manager.yml
53130
when: with_haproxy_load_balancing != "true" and cluster_vip | length > 0
54131
tags: [ vip, vip_manager ]
55132

133+
- import_tasks: tasks/patroni.yml
134+
tags: patroni
135+
56136
# optional
57137
- import_tasks: tasks/postgresql-users.yml
58138
when: is_master == "true" and postgresql_users | length > 0
File renamed without changes.

inventory

+20-2
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,37 @@
55
# "postgresql_exists='true'" if PostgreSQL is already exists and runing
66
# "hostname=" variable is optional (used to change the server name)
77

8+
# (if dcs_exists: 'false' and dcs_type: 'etcd')
9+
[etcd_cluster] # recommendation: 3 or 5-7 nodes
10+
10.128.64.140
11+
10.128.64.142
12+
10.128.64.143
13+
14+
15+
# (if with_haproxy_load_balancing: 'true')
16+
[balancers]
17+
10.128.64.140
18+
10.128.64.142
19+
10.128.64.143
20+
21+
22+
# PostgreSQL nodes
823
[master]
9-
10.128.64.140 postgresql_exists='false' hostname=pgnode01
24+
10.128.64.140 hostname=pgnode01 postgresql_exists='false'
1025

1126
[replica]
1227
10.128.64.142 hostname=pgnode02
1328
10.128.64.143 hostname=pgnode03
1429

15-
1630
[postgres_cluster:children]
1731
master
1832
replica
1933

2034

35+
# In this example, all components will be installed on PostgreSQL nodes
36+
# You can deploy the etcd cluster and the haproxy balancers on other dedicated servers.
37+
38+
2139
# Connection settings
2240
[all:vars]
2341
ansible_connection='ssh'

tasks/add-repository.yml

+1-8
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@
22

33
# Debian Ubuntu
44
- block:
5-
- name: Make sure the gnupg package is present
6-
apt:
7-
force_apt_get: yes
8-
name: gnupg
9-
state: present
10-
when: apt_repository_keys | length > 0 and apt_repository | length > 0
11-
125
- name: Add repository apt-key
136
apt_key:
147
url: "{{ item.key }}"
@@ -40,7 +33,7 @@
4033
when: yum_repository | length > 0
4134

4235
# Install Epel Repository
43-
- name: "install | get epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm"
36+
- name: "install | get epel-release-latest rpm package"
4437
get_url:
4538
url: "http://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm"
4639
dest: /tmp/

tasks/configure.yml

-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
---
22

3-
# Hostname
4-
- import_tasks: ../tasks/hostname.yml
5-
when: hostname is defined and hostname | length > 0
6-
ignore_errors: yes
7-
tags: [ hostname, configure ]
8-
93
# Kernel
104
- import_tasks: ../tasks/sysctl.yml
115
when: sysctl_conf is defined and sysctl_conf | length > 0

tasks/haproxy.yml

+43-1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,15 @@
274274
tags: haproxy
275275

276276
# Configure
277+
- name: haproxy | make sure the kernel parameter "net.ipv4.ip_nonlocal_bind" are enabled
278+
sysctl:
279+
name: "net.ipv4.ip_nonlocal_bind"
280+
value: "1"
281+
sysctl_set: "yes"
282+
state: "present"
283+
reload: "yes"
284+
tags: haproxy
285+
277286
- name: haproxy | add haproxy group
278287
group:
279288
name: haproxy
@@ -350,6 +359,40 @@
350359
when: existing_pgcluster is defined and existing_pgcluster|bool
351360
tags: [ haproxy, haproxy_conf ]
352361

362+
- name: haproxy | selinux | make sure the libsemanage-python, policycoreutils-python packages is present
363+
package:
364+
name: "{{ packages }}"
365+
state: present
366+
update_cache: yes
367+
vars:
368+
packages:
369+
- libsemanage-python
370+
- policycoreutils-python
371+
environment: '{{ proxy_env | default({}) }}'
372+
when:
373+
- ansible_os_family == "RedHat"
374+
- ansible_distribution_major_version == '7'
375+
- installation_method == "repo"
376+
- haproxy_installation_method == "rpm"
377+
tags: haproxy
378+
379+
- name: haproxy | selinux | make sure the python3-libsemanage, python3-policycoreutils packages is present
380+
package:
381+
name: "{{ packages }}"
382+
state: present
383+
update_cache: yes
384+
vars:
385+
packages:
386+
- python3-libsemanage
387+
- python3-policycoreutils
388+
environment: '{{ proxy_env | default({}) }}'
389+
when:
390+
- ansible_os_family == "RedHat"
391+
- ansible_distribution_major_version is version('8', '>=')
392+
- installation_method == "repo"
393+
- haproxy_installation_method == "rpm"
394+
tags: haproxy
395+
353396
- name: haproxy | selinux | set haproxy_connect_any flag to enable tcp connections
354397
seboolean:
355398
name: haproxy_connect_any
@@ -374,7 +417,6 @@
374417
enabled: yes
375418
state: restarted
376419
register: haproxy_restart_result
377-
when: haproxy_conf_result.changed or haproxy_conf_prepare_result.changed
378420
tags: [ haproxy, haproxy_conf ]
379421

380422
- name: haproxy | check HAProxy is started and accepting connections

tasks/keepalived.yml

-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@
9090
name: keepalived
9191
enabled: yes
9292
state: restarted
93-
when: haproxy_check_result.changed or keepalived_conf_result.changed or keepalived_conf_prepare_result.changed
9493
tags: [ keepalived_restart, keepalived ]
9594

9695
- name: wait for the cluster ip address (VIP) "{{ cluster_vip }}" is running

0 commit comments

Comments
 (0)