Ver configuración parte 1
Ver configuración parte 2
Ver configuración parte 1 daemon repmgr
Instalamos el pgbouncer en el nodo «testigo» (postgres4):
[root@postgres4 ~]# dnf install pgbouncer
Para hacer las pruebas de conexión de clientes, vamos a crear una nueva base de datos en el cluster (appdb) a la que se conectarán los clientes.
Añadimos la siguiente entrada en el pg_hba.conf del resto de nodos (postgres1, postgres2, postgres3) y recargamos:
host appdb appdb 192.168.0.0/24 trust
sudo systemctl reload postgresql-13
Añadimos las siguientes entradas al fichero /etc/pgbouncer/pgbouncer.ini:
[pgbouncer]
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
listen_addr = *
listen_port = 6432
unix_socket_dir = /tmp
auth_type = trust
auth_file = /etc/pgbouncer/userlist.txt
auth_hba_file = /etc/pgbouncer/pg_hba.conf
admin_users = postgres
stats_users = postgres
pool_mode = transaction
server_reset_query = DISCARD ALL
max_client_conn = 100
default_pool_size = 20
min_pool_size = 5
reserve_pool_size = 5
reserve_pool_timeout = 3
log_connections = 1
log_disconnections = 1
log_pooler_errors = 1
%include /etc/pgbouncer/pgbouncer.database.ini
El fichero /etc/pgbouncer/pgbouncer.database.ini apunta al nodo primario del cluster (postgres2 en este caso):
[root@postgres4 ~]# cat /etc/pgbouncer/pgbouncer.database.ini
[databases]
appdb= host=postgres2 dbname=appdb
Y creamos el fichero /etc/pgbouncer/userlist.txt para el usuario y su password:
[root@postgres4 ~]# cat /etc/pgbouncer/userlist.txt
"appdb" "appdb"
Añadimos un fichero pg_hba.conf para el pgbouncer (para poder parar y arrancar desde el resto de nodos el pool de conexiones en el failover):
[root@postgres4 ~]# chown pgbouncer:pgbouncer /etc/pgbouncer/pg_hba.conf
[root@postgres4 ~]# cat /etc/pgbouncer/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
host pgbouncer pgbouncer 192.168.0.0/24 trust
Añadimos al fichero /etc/sudoers las siguientes entradas, por comodidad:
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
postgres ALL= NOPASSWD: /bin/systemctl stop postgresql-13, \
/bin/systemctl start postgresql-13, \
/bin/systemctl status postgresql-13, \
/bin/systemctl restart postgresql-13, \
/bin/systemctl reload postgresql-13, \
/bin/systemctl start repmgr13, \
/bin/systemctl status repmgr13, \
/bin/systemctl restart repmgr13, \
/bin/systemctl reload repmgr13, \
/bin/systemctl stop repmgr13, \
/bin/systemctl start pgbouncer, \
/bin/systemctl restart pgbouncer, \
/bin/systemctl reload pgbouncer, \
/bin/systemctl stop pgbouncer
Cambiamos permisos a los ficheros:
[root@postgres4 ~]# chown postgres:postgres /etc/pgbouncer /etc/pgbouncer/*.ini
[root@postgres4 pgbouncer]# ls -l
total 24
-rwx------. 1 root root 819 nov 24 11:03 mkauth.py
-rw-r--r--. 1 postgres postgres 34 ene 9 09:31 pgbouncer.database.ini
-rw-r--r--. 1 postgres postgres 9349 ene 9 08:54 pgbouncer.ini
-rw-r--r--. 1 root root 16 ene 9 09:33 userlist.txt
Y reiniciamos pgbouncer:
[root@postgres4 ~]# systemctl restart pgbouncer
Creamos la base de datos «appdb» en el cluster (en el nodo primario postgres2) a la que se conectarán los clientes:
[local]:5432; postgres@postgres # create role appdb login;
CREATE ROLE
[local]:5432; postgres@postgres # \password appdb
Enter new password:
Enter it again:
********* QUERY **********
ALTER USER appdb PASSWORD 'SCRAM-SHA-256$4096:Hu2zNyVgzoEcZXrh1X4sKA==$XVOkHMvfcwPTf74abgWgS4tKtoC1lSz8rsBrbFwEHbs=:UMmvFFvb6FO8qta6y9cBMTZ9AzJ/FGoV0DXpA7mJlDo='
**************************
[local]:5432; postgres@postgres # create database appdb owner appdb;
CREATE DATABASE
Añadimos en el firewall del nodo del pgbouncer:
[root@postgres4 ~]# firewall-cmd --permanent --zone=public --add-rich-rule='rule family=ipv4 source address=192.168.0.0/24 port port=6432 protocol=tcp accept'
[root@postgres4 ~]# firewall-cmd --reload
Y hacemos pruebas de conexión desde el nodo cliente (postgres4) a la base de datos «appdb», del nodo postgres2 en modo r/w, a través del pgbouncer, y creamos una tabla de prueba:
[postgres@postgres4 ~]$ psql 'host=192.168.0.104 user=appdb port=6432'
192.168.0.104:6432; appdb@appdb # create table prueba(columna char(20));
CREATE TABLE
[postgres@postgres4 ~]$ psql 'host=192.168.0.104 user=appdb port=6432'
192.168.0.104:6432; appdb@appdb # \d prueba
Table "public.prueba"
+---------+---------------+-----------+----------+---------+
| Column | Type | Collation | Nullable | Default |
+---------+---------------+-----------+----------+---------+
| columna | character(20) | | | |
+---------+---------------+-----------+----------+---------+
[postgres@postgres4 ~]$ psql --host=192.168.0.104 --username=appdb --port=6432
192.168.0.104:6432; appdb@appdb # select inet_server_addr(), inet_server_port();
+------------------+------------------+
| inet_server_addr | inet_server_port |
+------------------+------------------+
| 192.168.0.102 | 5432 |
+------------------+------------------+
(1 row)
Creamos un script para integrarlo con el repmgr y que provoque el failover entre los nodos, teniendo el control del pgbouncer y su pool de conexiones:
[root@postgres1 ~]# mkdir -p /var/lib/postgres/repmgr/
[root@postgres1 ~]# chmod 700 /var/lib/postgres/repmgr/promote.sh
[root@postgres1 ~]# chown postgres:postgres /var/lib/postgres/repmgr/promote.sh
[postgres@postgres1 ~]$ cat /var/lib/postgres/repmgr/promote.sh
#!/bin/bash
set -u
set -e
# Configurable items
PGBOUNCER_HOSTS="postgres4"
PGBOUNCER_DATABASE_INI="/etc/pgbouncer/pgbouncer.database.ini"
PGBOUNCER_DATABASES="appdb"
PGBOUNCER_PORT=6432
REPMGR_DB="repmgr"
REPMGR_USER="repmgr"
# 0.- Pause pgbouncer
for HOST in ${PGBOUNCER_HOSTS}
do
for DB in ${PGBOUNCER_DATABASES}
do
/usr/pgsql-13/bin/psql -U postgres -h ${HOST} -p ${PGBOUNCER_PORT} pgbouncer -tc "pause ${DB}"
done
done
# 1. Promote server
/usr/pgsql-13/bin/repmgr standby promote -f /etc/repmgr/13/repmgr.conf --log-to-file
# 2. Reconfigure pgbouncer instances
PGBOUNCER_DATABASE_INI_NEW="/tmp/pgbouncer.database.ini"
for HOST in ${PGBOUNCER_HOSTS}
do
for DB in ${PGBOUNCER_DATABASES}
do
# Recreate the pgbouncer config file
echo -e "[databases]" > ${PGBOUNCER_DATABASE_INI_NEW}
echo -e "${DB}= host=$(hostname -f) dbname=${DB}" >> ${PGBOUNCER_DATABASE_INI_NEW}
# Copy new config file
scp ${PGBOUNCER_DATABASE_INI_NEW} ${HOST}:${PGBOUNCER_DATABASE_INI}
# Reload
/usr/pgsql-13/bin/psql -U postgres -h ${HOST} -p ${PGBOUNCER_PORT} pgbouncer -tc "reload"
# Resume
/usr/pgsql-13/bin/psql -U postgres -h ${HOST} -p ${PGBOUNCER_PORT} pgbouncer -tc "resume ${DB}"
done
done
# 3. Clean up generated file
rm ${PGBOUNCER_DATABASE_INI_NEW}
Ahora, en el fichero /etc/repmgr/13/repmgr.conf, de los nodos del cluster, cambiamos la línea del promote_command para indicarle nuestro script:
promote_command='/var/lib/postgres/repmgr/promote.sh'
Y reiniciamos el demonio en todos los nodos:
sudo systemctl restart repmgr13
Ver parte 2