High Availability PostgreSQL Cluster dengan Pgpool-II (Bagian ke-3)

Komunitas openSUSE Indonesia

TL;DR: Karena cukup panjang tulisan akan dibagi dalam 3 tulisan

  • Bagian 1 : membahas instalasi dan konfigurasi master postgresql
  • Bagian 2 : membahas instalasi dan konfigurasi slave postgresql
  • Bagian 3 : membahas instalasi dan konfigurasi pgpool-II

Tulisan ini adalah Bagian ke-3.

4. Instalasi pgpool

Pgpool-II sudah terdapat di OBS repositori. Versinya sedikit terlambat dari versi rilis di web Pgpool. Saat tulisan ini dibuat versi Pgpool di website Pgpool adalah 4.1. Sementara paket di OBS repositori masih versi 4.0.6.

Tambah repositori, install pgpool dan postgresql. Sebenarnya postgresql di mesin pgpool kita butuhkan hanya clientnya saja, untuk mengakses database (psql) dan backup (pg_dump) misalnya. Tapi untuk memudahkan kita install juga postgresql-server walaupun tidak perlu dijalankan

1
2
zypper ar -e -f https://download.opensuse.org/repositories/server:/database:/postgresql/openSUSE_Leap_15.1/ postgresql
zypper in --no-recommends pgpool-II postgresql12-pgpool-II postgresql12 postgresql12-server postgresql12-contrib

Selanjutnya edit file /etc/hosts, misalnya pgsql1 untuk master, pgsql2 untuk slave1, pgsql3 untuk slave2.

1
2
3
4
5
127.0.0.1       localhost
10.100.1.5      pgpool
10.100.1.6      pgsql1
10.100.1.7      pgsql2
10.100.1.8      pgsql3

Perhatikan bahwa kita menginstal pula paket postgresql12-pgpool-II, paket ini berisi library dan extension pgpool untuk PostgreSQL, ditandai dengan .sql dan .control. File-filenya tersimpan di direktori /usr/lib/postgresql12/lib64/, /usr/lib/postgresql12/lib64/bitcode/ dan /usr/share/postgresql12/extension/.

Langkah berikutnya kita memasang extension pgpool tersebut pada database postgresql. Kita pasang extension pgpool tersebut pada template1. Lakukan 1 kali saja di master karena nanti akan otomatis tereplikasi di slave.

1
2
3
4
sudo -i -u postgres
psql template1
CREATE EXTENSION pgpool_recovery;
CREATE EXTENSION pgpool_adm;

Periksa bahwa extension telah terpasang pada template1

1
\dx

Pada master akan seperti

Pada slave

Pada saatnya nanti kita gunakan template1 sebagai template database yang akan kita buat sehingga otomatis database yang terbentuk akan memiliki extension pgpool. Misalnya gunakan pgadmin, buatlah sebuah database baru dengan dengan menggunakan template1 di master, maka database akan dibuat dengan extension pgpool_adm dan pgpool_recovery. Database dengan kondisi yang sama otomatis akan terbentuk di slave. Kalau berhasil artinya sulapan kita bekerja 🙂

Langkah berikutnya adalah mengkonfigurasi file /etc/pgpool-II/pcp.conf. File ini berisi user dan password pgpool untuk admnistrasi management pgpool. Password dihash md5 dan formatnya adalah

 username:[md5 encrypted password]

Buat password dalam format md5 dengan

$ pg_md5 your_password
    1060b7b46a3bd36b3a0d66e0127d0517

Atau jika anda tidak ingin memperlihatkan password anda dengan cara:

 $ pg_md5 -p
    password: your_password

Isi file pcp.conf dengan menggunakan hasil md5 tersebut misal

admin:97bf34d31a8710e6b1649fd33357f783

Walaupun tidak wajib kita bisa mengisikan username dan password yang sama dengan user PostgreSQL agar mempermudah dalam mengakses dan mengingatnya.

Jangan lupa lengkapi file /etc/pgpool-II/pool_hba.conf dengan ip address dari masing-masing server PostgreSQL (sesuaikan dengan ip mesin master dan slave), misalnya

# "local" is for Unix domain socket connections only
local   all         all                               trust
# IPv4 local connections:
host    all         all         127.0.0.1/32          trust
host    all         all         ::1/128               trust
host    all         all         10.100.1.6/32         md5
host    all         all         10.100.1.7/32         md5
host    all         all         10.100.1.8/32         md5

Selanjutnya kita harus mengkonfigurasi file /etc/pgpool-II/pgpool.conf. Sesuai dengan dokumentasi pgpool maka running mode yang dianjurkan secara default adalah streaming replication mode. Dalam mode ini PostgreSQL bertanggung jawab terhadap sinkronisasi database. Load balancing dimungkinkan untuk dijalankan dalam mode ini. Contoh konfigurasinya diberikan ketika kita menginstall pgpool yaitu pada file /etc/pgpool-II/pgpool.conf.sample-stream. Di  bawah ini adalah contoh dari /etc/pgpool-II/pgpool.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# - pgpool Connection Settings -
listen_addresses = '*'
port = 5432
socket_dir = '/var/run/pgpool'
 
# - pgpool Communication Manager Connection Settings -
pcp_listen_addresses = '*'
pcp_port = 9898
pcp_socket_dir = '/var/run/pgpool'
listen_backlog_multiplier = 2
serialize_accept = off
 
# - Backend Connection Settings -
backend_hostname0 = 'gis_pgsql1' # sesuaikan dengan HOSTNAME master postgresql
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'
 
backend_hostname1 = 'gis_pgsql2' # sesuaikan dengan HOSTNAME slave postgresql
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
 
backend_hostname2 = 'gis_pgsql3' # sesuaikan dengan HOSTNAME slave postgresql
backend_port2 = 5432
backend_weight2 = 1
backend_data_directory2 = '/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'
 
# - Authentication -
enable_pool_hba = on
pool_passwd = 'pool_passwd'
authentication_timeout = 60
allow_clear_text_frontend_auth = off
 
# - SSL Connections -
ssl = off
ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
ssl_prefer_server_ciphers = off
 
#------------------------------------------------------------------------------
# POOLS
#------------------------------------------------------------------------------
 
# - Concurrent session and pool size -
num_init_children = 80
max_pool = 4
 
# - Life time -
child_life_time = 300
child_max_connections = 0
connection_life_time = 0
client_idle_limit = 0
 
#------------------------------------------------------------------------------
# LOGS
#------------------------------------------------------------------------------
 
# - Where to log -
log_destination = 'syslog'
 
# - What to log -
log_line_prefix = '%t: pid %p: '
log_connections = on
log_hostname = off
log_statement = on
log_per_node_statement = on
log_client_messages = on
log_standby_delay = 'if_over_threshold'
 
# - Syslog specific -
syslog_facility = 'LOCAL0'
syslog_ident = 'pgpool'
 
# - Debug -
log_error_verbosity = default
 
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
 
pid_file_name = '/var/run/pgpool/pgpool.pid'
logdir = '/var/run/pgpool'
 
#------------------------------------------------------------------------------
# CONNECTION POOLING
#------------------------------------------------------------------------------
 
connection_cache = on
reset_query_list = 'ABORT; DISCARD ALL'
 
#------------------------------------------------------------------------------
# REPLICATION MODE
#------------------------------------------------------------------------------
 
replication_mode = off
replicate_select = off
insert_lock = off
lobj_lock_table = ''
 
# - Degenerate handling -
replication_stop_on_mismatch = off
failover_if_affected_tuples_mismatch = off
 
#------------------------------------------------------------------------------
# LOAD BALANCING MODE
#------------------------------------------------------------------------------
 
load_balance_mode = on
ignore_leading_white_space = on
white_function_list = ''
black_function_list = 'currval,lastval,nextval,setval'
black_query_pattern_list = ''
 
database_redirect_preference_list = ''
app_name_redirect_preference_list = ''
allow_sql_comments = off
disable_load_balance_on_write = 'transaction'
 
#------------------------------------------------------------------------------
# MASTER/SLAVE MODE
#------------------------------------------------------------------------------
 
master_slave_mode = on
master_slave_sub_mode = 'stream'
 
# - Streaming -
sr_check_period = 10
sr_check_user = 'postgres'
sr_check_password = 'password'
sr_check_database = 'postgres'
delay_threshold = 10000000
 
# - Special commands -
follow_master_command = ''
 
#------------------------------------------------------------------------------
# HEALTH CHECK GLOBAL PARAMETERS
#------------------------------------------------------------------------------
health_check_period = 5
health_check_timeout = 20
health_check_user = 'postgres'
health_check_password = 'password'
health_check_database = ''
health_check_max_retries = 0
health_check_retry_delay = 1
connect_timeout = 10000
 
#------------------------------------------------------------------------------
# FAILOVER AND FAILBACK
#------------------------------------------------------------------------------
failover_command = ''
failback_command = ''
failover_on_backend_error = on
detach_false_primary = off
search_primary_node_timeout = 300
 
#------------------------------------------------------------------------------
# ONLINE RECOVERY
#------------------------------------------------------------------------------
 
recovery_user = 'postgres'
recovery_password = 'password'
recovery_1st_stage_command = ''
recovery_2nd_stage_command = ''
recovery_timeout = 90
client_idle_limit_in_recovery = 0
 
#------------------------------------------------------------------------------
# WATCHDOG
#------------------------------------------------------------------------------
 
# - Enabling -
#use_watchdog = on
use_watchdog = off
 
# -Connection to up stream servers -
trusted_servers = ''
ping_path = '/bin'
 
# - Watchdog communication Settings -
wd_hostname = ''
wd_port = 9000
wd_priority = 1
 
wd_hostname = ''
wd_port = 9000
wd_priority = 2
 
wd_hostname = ''
wd_port = 9000
wd_priority = 3
 
wd_authkey = ''
wd_ipc_socket_dir = '/tmp'
 
# - Virtual IP control Setting -
delegate_IP = ''
if_cmd_path = '/sbin'
if_up_cmd = 'ip addr add $_IP_$/24 dev eth0 label eth0:0'
if_down_cmd = 'ip addr del $_IP_$/24 dev eth0'
arping_path = '/usr/sbin'
arping_cmd = 'arping -U $_IP_$ -w 1'
 
# - Behaivor on escalation Setting -
clear_memqcache_on_escalation = on
wd_escalation_command = ''
wd_de_escalation_command = ''
 
# - Watchdog consensus settings for failover -
failover_when_quorum_exists = on
failover_require_consensus = on
allow_multiple_failover_requests_from_node = off
 
# - Lifecheck Setting -
 
# -- common --
wd_monitoring_interfaces_list = ''
wd_lifecheck_method = 'heartbeat'
wd_interval = 10
 
# -- heartbeat mode --
wd_heartbeat_port = 9694
wd_heartbeat_keepalive = 2
wd_heartbeat_deadtime = 30
heartbeat_destination0 = 'host_ip1'
heartbeat_destination_port0 = 9694
heartbeat_device0 = ''
 
other_pgpool_hostname0 = 'host_ip1'
other_pgpool_port0 = 5432
other_wd_port0 = 9000
 
# -- query mode --
wd_life_point = 3
wd_lifecheck_query = 'SELECT 1'
wd_lifecheck_dbname = 'template1'
wd_lifecheck_user = 'nobody'
wd_lifecheck_password = ''
 
#------------------------------------------------------------------------------
# OTHERS
#------------------------------------------------------------------------------
relcache_expire = 0
relcache_size = 256
check_temp_table = on
check_unlogged_table = on
 
#------------------------------------------------------------------------------
# IN MEMORY QUERY MEMORY CACHE
#------------------------------------------------------------------------------
memory_cache_enabled = off
memqcache_method = 'shmem'
memqcache_memcached_host = 'localhost'
memqcache_memcached_port = 11211
memqcache_total_size = 67108864
memqcache_max_num_cache = 1000000
memqcache_expire = 0
memqcache_auto_cache_invalidation = on
memqcache_maxcache = 409600
memqcache_cache_block_size = 1048576
memqcache_oiddir = '/var/log/pgpool/oiddir'
white_memqcache_table_list = ''
black_memqcache_table_list = ''

Perhatikan pada bagian Backend Connection Setting pada file konfigurasi di atas kita set weight=1. Ini artinya kita berusaha agar perbandingan beban dari masing-masing backend adalah sama.

Selanjutnya ada 1 file lagi yang harus kita lengkapi yaitu /etc/pgpool-II/pool_passwd. Isilah file ini dengan username dan password yang sama dengan user postgresql. Entry dari file ini pool_passwd ini harus dibuat dengan menjalankan

pg_md5 -f /etc/pgpool-II/pgpool.conf -m -u postgres postgrespassword

Terakhir jalankan service pgpool

1
2
sudo systemctl start pgpool-II.service
sudo systemctl enable pgpool-II.service

Kita bisa mencoba bagaimana pgpool bekerja dengan mentest membuat database dan menghapusnya melalui pgadmin. Kita koneksikan pgadmin kita ke server pgpool (masukkan ip address dan port mesin pgpool, username dan password pgpool), buat database maka database akan terbentuk di master dan slave. Hapus database melalui pgpool maka database akan terhapus di master dan slave.

Koneksi ke database dari aplikasi kita tinggal diarahkan ke mesin pgpool (tidak lagi ke mesin postgresql). Dengan cara demikian, proses WRITE akan dilakukan oleh pgpool ke mesin master, sedangkan proses READ akan dibagi ke mesin master dan slave. Untuk membuktikannya anda dapat menjalankan htop di setiap mesin postgresql dan lihat distribusi bebannya. Bisa juga dengan membandingkan log dari pgpool untuk melihat proses INSERT, UPDATE, SELECT dilakukan ke mesin mana saja. Misalnya dengan menjalankan

1
2
3
4
5
6
sudo journalctl -u pgpool-II | grep "node id: 0" | grep INSERT
sudo journalctl -u pgpool-II | grep "node id: 1" | grep INSERT
sudo journalctl -u pgpool-II | grep "node id: 2" | grep INSERT
sudo journalctl -u pgpool-II | grep "node id: 0" | grep SELECT
sudo journalctl -u pgpool-II | grep "node id: 1" | grep SELECT
sudo journalctl -u pgpool-II | grep "node id: 2" | grep SELECT

Masih ada yang belum ditulis dalam artikel ini yaitu bagaimana membuat mesin pgpool menjadi HA juga. Mudah-mudahan kedepannya dapat saya tuliskan.

Selamat mencoba, have fun

medwinz

 

Comments: 1

  1. Kang Asep berkata:

    terima kasih sangat membantu artikelnya…
    ditunggu untuk tutorial PG_POOL HA nya..

Add your comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.