Différences entre versions de « Replication PostgreSQL multi slaves »

De Ikoula Wiki
Jump to navigation Jump to search
 
Ligne 506 : Ligne 506 :
 
[[category:PostgreSQL]]
 
[[category:PostgreSQL]]
 
[[category:Linux]]
 
[[category:Linux]]
 +
[[Catégorie:Serveur VPS]]
 +
[[Catégorie:Serveur dédié]]
 
<br />
 
<br />
 
<comments />
 
<comments />

Version actuelle datée du 1 janvier 2021 à 04:02

fr:Replication PostgreSQL multi slaves he:PostgreSQL שכפול עבדים רב ro:PostgreSQL replicare sclavi multi ru:PostgreSQL репликации рабы multi pl:PostgreSQL replikacji niewolników multi ja:PostgreSQL のレプリケーション スレーブ マルチ ar:كيو النسخ المتماثل العبيد متعددة zh:PostgreSQL 复制奴隶多 de:PostgreSQL Replikation Sklaven multi nl:PostgreSQL replicatie slaven multi it:PostgreSQL replica schiavi multi pt:Multi de escravos de replicação PostgreSQL es:PostgreSQL replicación esclavos multi en:PostgreSQL replication slaves multi


postgresql logo

Introduction

Cette page traite de la mise en place d'une réplication PostgreSQL streaming asynchrone avec un master et deux slaves. Nos slaves seront configurés comme hot standby, c'est à dire qu'il sera possible d'exécuter des requêtes (en lecture uniquement) sur ceux-ci.


Contexte de cette mise en place :


Nous avons 3 serveurs Debian 8 (mis à jour) :

Postgres01 (10.1.1.75) : sera notre Master

Postgres02 (10.1.1.90) : sera un slave

Postgres03 (10.1.1.199) : sera un second slave


Les commandes indiquées seront à effectuer en root quand elles sont précédées de "#" et en tant qu'utilisateur système postgres quand elles sont précédées de "$".

Installation de PostgreSQL et pré-configuration des trois serveurs

Toutes les commandes de cette partie sont à faire sur chacun des serveurs.

Dans un premier temps, il est recommandé d'avoir un fichier /etc/hosts peuplé avec les correspondances de chaque serveur, comme ceci (en adaptant avec les hostnames et adresses ip de vos propres serveurs) :

# cat /etc/hosts
127.0.0.1       localhost

10.1.1.75       postgres01
10.1.1.90       postgres02
10.1.1.199      postgres03


On ajoute le dépôt APT PostgreSQL :

# echo "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" > /etc/apt/sources.list.d/postgres.list


On importe la clé public de ce dépôt :

# gpg --keyserver pgpkeys.mit.edu --recv-key 7FCC7D46ACCC4CF8 && gpg -a --export 7FCC7D46ACCC4CF8 | apt-key add -
gpg: directory `/root/.gnupg' created
gpg: new configuration file `/root/.gnupg/gpg.conf' created
gpg: WARNING: options in `/root/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/root/.gnupg/secring.gpg' created
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: requesting key ACCC4CF8 from hkp server pgpkeys.mit.edu
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key ACCC4CF8: public key "PostgreSQL Debian Repository" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK


On met à jour le cache APT pour prendre en compte le dépôt :

# apt-get update


On installe le paquet postgresql (installera la dernière version stable soit la 9.5 au moment où sont écrites ces lignes) :

# apt-get install postgresql


On définit un mot de passe (de son choix mais sécurisé) et génère une paire de clé ssh (sans passphrase) pour l’utilisateur système postgres :

# passwd postgres
# su - postgres
$ ssh-keygen


On copie la clé ssh public de l’utilisateur postgres depuis et entre chaque serveur :


Depuis le premier serveur (postgres01 dans notre cas) vers le second (postgres02 pour nous) et troisisème (postgres03) :

root@postgres01:~# su - postgres
postgres@postgres01:~$ ssh-copy-id postgres02
postgres@postgres01:~$ ssh-copy-id postgres03


Depuis le second serveur vers le premier et troisième :

root@postgres02:~# su - postgres
postgres@postgres02:~$ ssh-copy-id postgres01
postgres@postgres02:~$ ssh-copy-id postgres03


Depuis le troisième serveur vers le premier et second :

root@postgres03:~# su - postgres
postgres@postgres03:~$ ssh-copy-id postgres01
postgres@postgres03:~$ ssh-copy-id postgres02

Configuration du Master

A faire uniquement sur le master (postgres01 dans notre cas) :


On crée le rôle/utilisateur de réplication :

# su - postgres
$ psql -c "CREATE USER repuser REPLICATION LOGIN CONNECTION LIMIT 2 ENCRYPTED PASSWORD '<mot de passe repuser>';"

Note : on définit une limite de connexion de 2 car nous avons 2 slaves


On édite le fichier de configuration principal de postgresql /etc/postgresql/9.5/main/postgresql.conf pour configurer les directives suivantes :

listen_addresses = '*'
wal_level = hot_standby
archive_mode = on
archive_command = 'rsync -av %p postgres@<ip du premier slave>:/var/lib/postgresql/wal_archive/%f'
max_wal_senders = 2
wal_keep_segments = 256
hot_standby = on

Note: nous activons l’archivage vers notre second serveur (adaptez l’adresse ip par celle de votre serveur) pour encore plus de précautions mais cela n'est pas une obligation. Nous définissons également les paramètres hot_standby, bien que ignorés sur un master, dans le cas où celui-ci devait être rétrogradé en slave dans l’avenir.


On édite maintenant le fichier d’authentification de postgresql /etc/postgresql/9.5/main/pg_hba.conf pour ajouter l’autorisation de notre utilisateur de réplication à se connecter depuis nos slaves soit la ligne suivante à la fin du fichier :

hostssl replication     repuser <ip du réseau de vos serveurs>/24     md5

Veuillez adapter cette ligne en fonction du nom de votre utilisateur de réplication et du réseau (ou adresses ip respectives) de vos slaves


On redémarre le service postgresql pour prendre en compte notre configuration (en root) :

# systemctl restart postgresql


On s’assure que le service a démarré correctement :

root@postgres01:~# systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
   Loaded: loaded (/lib/systemd/system/postgresql.service; enabled)
   Active: active (exited) since Thu 2016-06-02 12:06:28 CEST; 22s ago
  Process: 77056 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 77056 (code=exited, status=0/SUCCESS)


root@postgres01:~# ps -u postgres u
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
postgres  77038  0.0  4.4 227300 21836 ?        S    12:06   0:00 /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/9.
postgres  77040  0.0  0.8 227300  4160 ?        Ss   12:06   0:00 postgres: checkpointer process
postgres  77041  0.0  1.0 227300  4968 ?        Ss   12:06   0:00 postgres: writer process
postgres  77042  0.0  1.7 227300  8776 ?        Ss   12:06   0:00 postgres: wal writer process
postgres  77043  0.0  1.3 227728  6708 ?        Ss   12:06   0:00 postgres: autovacuum launcher process
postgres  77044  0.0  0.6  82244  3392 ?        Ss   12:06   0:00 postgres: archiver process
postgres  77045  0.0  0.8  82244  4244 ?        Ss   12:06   0:00 postgres: stats collector process

Configuration des slaves

Sur le premier slave

On commence par stopper le service postgresql :

# systemctl stop postgresql


On édite le fichier de configuration principal de postgresql /etc/postgresql/9.5/main/postgresql.conf pour configurer les même directives que sur le master, en adaptant juste l’ip du premier slave par celle du second slave dans la commande rsync d’archivage si vous souhaitez l'activer soit :

listen_addresses = '*'
wal_level = hot_standby
archive_mode = on
archive_command = 'rsync -av %p postgres@<ip du second slave>:/var/lib/postgresql/wal_archive/%f'
max_wal_senders = 2
wal_keep_segments = 256
hot_standby = on


On édite maintenant le fichier d’authentification de postgresql /etc/postgresql/9.5/main/pg_hba.conf pour ajouter l’autorisation de notre utilisateur de réplication à se connecter depuis nos autres serveurs (cela ne servira que dans le cas où ce slave devrait promu master) :

hostssl replication     repuser <ip du réseau de vos serveurs>/24     md5

Note : Avec cette configuration similaire à celle de notre master cela permettra de promouvoir facilement ce slave en tant que master en cas de besoin.


Pour les opérations ci-dessous, connectez-vous en tant qu’utilisateur système postgres :

# su – postgres


On crée le répertoire de destination des archives wal du master :

$ mkdir /var/lib/postgresql/wal_archive


On supprime le répertoire de données postgresql :

$ rm -rf /var/lib/postgresql/9.5/main


On fait le base backup (adaptez l’ip par celle de votre master et le nom de votre utilisateur de réplication), le mot de passe de votre utilisateur de réplication vous sera demandé :

$ pg_basebackup -h <ip de votre master> -D /var/lib/postgresql/9.5/main -U repuser -v -P --xlog


On configure la réplication en créant le fichier /var/lib/postgresql/9.5/main/recovery.conf avec les paramètres suivants :

standby_mode = on
primary_conninfo = 'host=<ip de votre master> port=5432 user=repuser password=<mot de passe de repuser> sslmode=require application_name=<hostname de votre slave>'
trigger_file = '/var/lib/postgresql/9.5/postgres.trigger'

Note : Le fichier trigger est le fichier qu’on ne crée que lorsque l’on veut que son slave arrête la réplication et commence à accepter les écritures c’est-à-dire quand on veut le promouvoir comme master. Avant de promouvoir un slave en cas de crash de son master, il faut s’assurer que le master initial ne remontera pas pour éviter toute corruption.


On repasse root et on démarre le service :

# systemctl start postgresql


On s’assure que le service a correctement démarré :

# systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
   Loaded: loaded (/lib/systemd/system/postgresql.service; enabled)
   Active: active (exited) since Thu 2016-06-02 12:53:42 CEST; 1min 6s ago
  Process: 8894 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 8894 (code=exited, status=0/SUCCESS)


# ps -u postgres u
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
postgres   8878  0.0  4.4 227308 21892 ?        S    12:53   0:00 /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/9.
postgres   8879  0.0  1.1 227376  5700 ?        Ss   12:53   0:00 postgres: startup process   recovering 00000001000000000000000
postgres   8880  0.0  0.8 227308  4140 ?        Ss   12:53   0:00 postgres: checkpointer process
postgres   8881  0.0  1.0 227308  5236 ?        Ss   12:53   0:00 postgres: writer process
postgres   8882  0.0  0.6  82252  3316 ?        Ss   12:53   0:00 postgres: stats collector process
postgres   8883  0.0  1.7 238064  8520 ?        Ss   12:53   0:00 postgres: wal receiver process   streaming 0/30003E0


Si on se connecte à notre master, on peut déjà vérifier que notre réplication entre le master et le premier slave est fonctionnelle :

On se connecte sur notre master et on se connecte en utilisateur système postgres :

# su - postgres


Puis on se connecte à postgresql :

$ psql


On active l’affichage étendu et on vérifie notre réplication :

postgres=# \x
Expanded display is on.
postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 78879
usesysid         | 16384
usename          | repuser
application_name | postgres02
client_addr      | 10.1.1.90
client_hostname  |
client_port      | 49009
backend_start    | 2016-06-02 12:53:36.641823+02
backend_xmin     |
state            | streaming
sent_CRElocation    | 0/30004C0
write_location   | 0/30004C0
flush_location   | 0/30004C0
replay_location  | 0/30004C0
sync_priority    | 0
sync_state       | async

Notre réplication streaming asynchrone avec notre premier slave s’est bien faite. A ce stade on a une réplication Master/slave classique (un seul slave en streaming asynchrone)

Sur le second slave

On refait à l’identique ce qui a été fait sur le premier slave en adaptant évidemment son hostname dans le fichier recovery.conf et l’adresse ip dans la commande d’archivage dans le fichier de configuration principal si vous souhaitez également activer l'archivage sur ce second slave.

Vérification et test de notre réplication master multi slaves

On se connecte sur le master et on se loggue en utilisateur postgres :

# su – postgres

Puis on se connecte à postgresql :

$ psql


On active l’affichage étendu et on vérifie notre réplication :

postgres=# \x
Expanded display is on.
postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 78879
usesysid         | 16384
usename          | repuser
application_name | postgres02
client_addr      | 10.1.1.90
client_hostname  |
client_port      | 49009
backend_start    | 2016-06-02 12:53:36.641823+02
backend_xmin     |
state            | streaming
sent_location    | 0/5000140
write_location   | 0/5000140
flush_location   | 0/5000140
replay_location  | 0/5000140
sync_priority    | 0
sync_state       | async
-[ RECORD 2 ]----+------------------------------
pid              | 82725
usesysid         | 16384
usename          | repuser
application_name | postgres03
client_addr      | 10.1.1.199
client_hostname  |
client_port      | 51754
backend_start    | 2016-06-02 14:31:43.759683+02
backend_xmin     |
state            | streaming
sent_location    | 0/5000140
write_location   | 0/5000140
flush_location   | 0/5000140
replay_location  | 0/5000140
sync_priority    | 0
sync_state       | async

On a donc bien nos 2 réplications avec nos deux serveurs slaves (postgres02 et postgres03).


Toujours connecté à postgresql sur le master, on crée une base de données de test (ex : checkrep) pour confirmer que la réplication est fonctionnelle :

postgres=# CREATE DATABASE checkrep;


On vérifie que cette base de données s’est bien répliquée sur nos 2 slaves :

root@postgres02:~# su - postgres
postgres@postgres02:~$ psql
psql (9.5.3)
Type "help" for help.

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 checkrep  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)


root@postgres03:~# su - postgres
postgres@postgres03:~$ psql
psql (9.5.3)
Type "help" for help.

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 checkrep  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)

La base de données que nous avons crée sur notre master s’est donc bien automatiquement répliquée sur nos deux slaves.


Pour la supprimer, depuis le master :

postgres=# DROP DATABASE checkrep;



Vous n'êtes pas autorisé à publier de commentaire.