PostgreSQL Master-Slave repmgr triple Replication
In this tutorial we're going to setup a triple master-slave postgreSQL replication using repmgr:
The idea of using the aforementionned full mesh topology is in case the master node fails, the slave nodes would elect a new master node amongst themselves. We will first setup our first debian CT on proxmox, setup the latest postgresql version on it and then configure it accordingly to act as the master node.:::
s
Initial setup
Once the CT is created, get in it's console to setup SSH properly:
Debian GNU/Linux 10 debian-psql-1 tty1
debian-psql-1 login: root
Password:
Linux debian-psql-1 5.4.106-1-pve #1 SMP PVE 5.4.106-1 (Fri, 19 Mar 2021 11:08:47 +0100) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@debian-psql-1:~# apt update -y ; apt upgrade -y ; apt install vim -y ; vim /etc/ssh/sshd_config
PermitRootLogin yes
:wq
root@debian-psql-1:~# systemctl restart sshd ; exit
Once that's done login via ssh:
[ 10.0.0.10/16 ] [ /dev/pts/58 ] [~]
→ ssh root@10.0.0.161
The authenticity of host '10.0.0.161 (10.0.0.161)' can't be established.
ED25519 key fingerprint is SHA256:s6HbZSbkMR4DSr8AnFn/owHl82+gQvuomQ++Oe8S6cw.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.0.161' (ED25519) to the list of known hosts.
root@10.0.0.161's password:
Linux debian-psql-1 5.4.106-1-pve #1 SMP PVE 5.4.106-1 (Fri, 19 Mar 2021 11:08:47 +0100) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Apr 5 10:28:43 2021
root@debian-psql-1:~#
Now from here we're going to install the latest postgresql:
root@debian-psql-1:~# apt install lsb-release gnupg2 -y
root@debian-psql-1:~# sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
root@debian-psql-1:~# wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
OK
root@debian-psql-1:~# apt update -y
Hit:1 http://security.debian.org buster/updates InRelease
Hit:2 http://ftp.debian.org/debian buster InRelease
Hit:3 http://ftp.debian.org/debian buster-updates InRelease
Get:4 http://apt.postgresql.org/pub/repos/apt buster-pgdg InRelease [104 kB]
Get:5 http://apt.postgresql.org/pub/repos/apt buster-pgdg/main amd64 Packages [219 kB]
Fetched 322 kB in 2s (181 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.
root@debian-psql-1:~# apt install postgresql-13 postgresql-13-repmgr -y
root@debian-psql-1:~# systemctl stop postgresql
Once that's done we're going to clone this CT 4 times to end up with the following topology:
Basically, each of the database server nodes are going to send queries to the pgpooler node and the pgpooler node is going to send them to the master node. So let's first clone our debian machine after we shut it down:
root@debian-psql-1:~# shutdown now
root@debian-psql-1:~# Connection to 10.0.0.161 closed by remote host.
Connection to 10.0.0.161 closed.
[ 10.0.0.10/16 ] [ /dev/pts/58 ] [~]
→
and clone it 4 times:
Once cloned, make sure you set their local IP correctly:
Once that's done, start them all and connect to them via SSH:
Now we want to create a .ssh directory owned by the postgres user, and we will do so FROM THE PGBOUNCER node, the other nodes won't communicate to each other by themselves, it will anyway happen through the pgbouncer node. Before we do that, we're going to install pgbouncer:
root@debian-pgbouncer:~# apt search pgbouncer
Sorting... Done
Full Text Search... Done
hobbit-plugins/stable 20190129 all
plugins for the Xymon network monitor
pgbouncer/buster-pgdg 1.15.0-1.pgdg100+1 amd64
lightweight connection pooler for PostgreSQL
pgbouncer-dbgsym/buster-pgdg 1.15.0-1.pgdg100+1 amd64
debug symbols for pgbouncer
pgstat/buster-pgdg 1.0.1-1.pgdg100+1 amd64
Collects PostgreSQL statistics the same way as a vmstat tool
prometheus-pgbouncer-exporter/stable 1.7-1 all
Export metrics from pgbouncer to Prometheus
root@debian-pgbouncer:~# apt install pgbouncer -y
Once that's done, create pgbouncer's ~/.ssh directory
root@debian-pgbouncer:~# su - postgres
postgres@debian-pgbouncer:~$ ls -lash
total 16K
4.0K drwxr-xr-x 3 postgres postgres 4.0K Apr 5 11:43 .
4.0K drwxr-xr-x 21 root root 4.0K Apr 5 10:50 ..
4.0K -rw------- 1 postgres postgres 32 Apr 5 11:43 .bash_history
4.0K drwxr-xr-x 3 postgres postgres 4.0K Apr 5 10:38 13
postgres@debian-pgbouncer:~$ mkdir ~/.ssh
postgres@debian-pgbouncer:~$ cd ~/.ssh
postgres@debian-pgbouncer:~/.ssh$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/var/lib/postgresql/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/lib/postgresql/.ssh/id_rsa.
Your public key has been saved in /var/lib/postgresql/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:jkRXPz3sIgIfhefwluU4HKLzRPBwI0jnxCq0nWQkwhY postgres@debian-pgbouncer
The key's randomart image is:
+---[RSA 2048]----+
|oEoooo*.o.o |
| +..++.==+o..o |
|.. = o+o+B *o + |
| o +.o+..O .o . |
| . .+S.... . |
| . o.. . . |
| . . |
| |
| |
+----[SHA256]-----+
postgres@debian-pgbouncer:~/.ssh$
and we will do the same for the other nodes but from our pgbouncer node:
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo ${i}; done
1
2
3
4
5
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo 10.0.0.16${i}; done
10.0.0.161
10.0.0.162
10.0.0.163
10.0.0.164
10.0.0.165
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo 10.0.0.16${i} ; ssh root@10.0.0.16${i} ; done
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo 10.0.0.16${i} ; ssh root@10.0.0.16${i} "mkdir /var/lib/postgresql/.ssh && chown postgres:postgres /var/lib/postgresql/.ssh" ; done
10.0.0.161
root@10.0.0.161's password:
10.0.0.162
root@10.0.0.162's password:
10.0.0.163
root@10.0.0.163's password:
10.0.0.164
root@10.0.0.164's password:
10.0.0.165
root@10.0.0.165's password:
mkdir: cannot create directory '/var/lib/postgresql/.ssh': File exists
postgres@debian-pgbouncer:~/.ssh$
Now that's done, we're going to make sure each of the 4 servers can be accessed by the pgbouncer node:
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo 10.0.0.16${i} ; scp id_rsa* root@10.0.0.16${i}:/var/lib/postgresql/.ssh/ ; done
10.0.0.161
root@10.0.0.161's password:
id_rsa 100% 1831 1.3MB/s 00:00
id_rsa.pub 100% 407 590.4KB/s 00:00
10.0.0.162
root@10.0.0.162's password:
id_rsa 100% 1831 1.7MB/s 00:00
id_rsa.pub 100% 407 593.3KB/s 00:00
10.0.0.163
root@10.0.0.163's password:
id_rsa 100% 1831 758.0KB/s 00:00
id_rsa.pub 100% 407 375.6KB/s 00:00
10.0.0.164
root@10.0.0.164's password:
id_rsa 100% 1831 1.2MB/s 00:00
id_rsa.pub 100% 407 541.9KB/s 00:00
10.0.0.165
root@10.0.0.165's password:
id_rsa 100% 1831 1.8MB/s 00:00
id_rsa.pub 100% 407 579.9KB/s 00:00
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo 10.0.0.16${i} ; scp id_rsa.pub root@10.0.0.16${i}:/var/lib/postgresql/.ssh/authorized_keys ; done
10.0.0.161
root@10.0.0.161's password:
id_rsa.pub 100% 407 512.1KB/s 00:00
10.0.0.162
root@10.0.0.162's password:
id_rsa.pub 100% 407 306.8KB/s 00:00
10.0.0.163
root@10.0.0.163's password:
id_rsa.pub 100% 407 455.7KB/s 00:00
10.0.0.164
root@10.0.0.164's password:
id_rsa.pub 100% 407 357.0KB/s 00:00
10.0.0.165
root@10.0.0.165's password:
id_rsa.pub 100% 407 221.5KB/s 00:00
postgres@debian-pgbouncer:~/.ssh$
Now that's done we can see that the postgres user from the pgbouncer node can log in via ssh to all the other 4 nodes as the postgres user without needing a password:
postgres@debian-pgbouncer:~/.ssh$ for i in {1..5} ; do echo 10.0.0.16${i} ; ssh postgres@10.0.0.16${i} "id" ; done
10.0.0.161
uid=107(postgres) gid=115(postgres) groups=115(postgres),102(ssl-cert)
10.0.0.162
uid=107(postgres) gid=115(postgres) groups=115(postgres),102(ssl-cert)
10.0.0.163
uid=107(postgres) gid=115(postgres) groups=115(postgres),102(ssl-cert)
10.0.0.164
uid=107(postgres) gid=115(postgres) groups=115(postgres),102(ssl-cert)
10.0.0.165
uid=107(postgres) gid=115(postgres) groups=115(postgres),102(ssl-cert)
Now this means that we have passwordless connectivity between all of the machines for the postgres user. Now for our next steps, we will need to apply the following changes primary host (node1 at 10.0.0.161)
root@debian-psql-1:~# apt install sudo -y ; usermod -aG sudo postgres ; echo "postgres ALL = NOPASSWD: /usr/bin/pg_ctlcluster" > /etc/sudoers.d/postgres
root@debian-psql-2:~# apt install sudo -y ; usermod -aG sudo postgres ; echo "postgres ALL = NOPASSWD: /usr/bin/pg_ctlcluster" > /etc/sudoers.d/postgres
root@debian-psql-3:~# apt install sudo -y ; usermod -aG sudo postgres ; echo "postgres ALL = NOPASSWD: /usr/bin/pg_ctlcluster" > /etc/sudoers.d/postgres
root@debian-psql-4:~# apt install sudo -y ; usermod -aG sudo postgres ; echo "postgres ALL = NOPASSWD: /usr/bin/pg_ctlcluster" > /etc/sudoers.d/postgres
once that's done, we're going to edit the postgresql.conf config file for our 4 hosts:
root@debian-psql-1:~# su - postgres
postgres@debian-psql-1:~$ vim /etc/postgresql/13/main/postgresql.conf
[...]
listen_addresses = '*'
[...]
shared_preload_libraries = 'repmgr'
[...]
include 'postgresql.replication.conf'
:wq to save and quit, then create the file /etc/postgresql/13/main/postgresql.replication.conf with this:
postgres@debian-psql-1:~$ vim /etc/postgresql/13/main/postgresql.replication.conf
max_wal_senders = 15
max_replication_slots = 15
wal_level = 'replica'
hot_standby = on
archive_mode = on
archive_command = '/bin/true'
wal_keep_segments = 500
:wq to save and quit out of vim, then edit pg_hba.conf:
postgres@debian-psql-1:~$ vim /etc/postgresql/13/main/pg_hba.conf
local replication repmgr trust
host replication repmgr 127.0.0.1/32 trust
host replication repmgr 10.0.0.0/16 trust
local repmgr repmgr trust
host repmgr repmgr 127.0.0.1/32 trust
host repmgr repmgr 10.0.0.0/16 trust
once that's done for all of the 4 hosts, restart postgresql:
postgres@debian-psql-2:~$ vim /etc/postgresql/13/main/pg_hba.conf
postgres@debian-psql-2:~$ exit
logout
root@debian-psql-2:~# systemctl restart postgresql ; systemctl status postgresql
* postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; v
Active: active (exited) since Mon 2021-04-05 15:20:27 UTC; 38ms ag
Process: 1001 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
Main PID: 1001 (code=exited, status=0/SUCCESS)
Apr 05 15:20:27 debian-psql-2 systemd[1]: Starting PostgreSQL RDBMS..
Apr 05 15:20:27 debian-psql-2 systemd[1]: Started PostgreSQL RDBMS.
Nihilist
8AUYjhQeG3D5aodJDtqG499N5jXXM71gYKD8LgSsFB9BUV1o
7muLv3DXHoydRTK4SZaaUBq4EAUqpZHLrX2VZLH71Jrd9k8 Donate XMR to Nihilist: