Les sauvegardes sont la partie vitale et importante de tout plan de reprise après sinistre, la sauvegarde de la base de données de production est également une partie fondamentale et importante de l'administration PostgreSQL. Cependant, les DBA ne vérifient pas souvent que ces sauvegardes sont fiables.
Chaque organisation utilise des sauvegardes de base de données PostgreSQL sous différentes formes, certaines peuvent effectuer une sauvegarde du système de fichiers (physique) des répertoires de données PostgreSQL (à l'aide d'outils tels que Barman, PGBackRest) tandis que d'autres peuvent effectuer uniquement des sauvegardes logiques (à l'aide pg_dump), et même d'autres peuvent prendre des instantanés au niveau du bloc à l'aide d'outils comme EBS ou VMWare snapshot.
Dans ce blog, nous allons vous montrer comment valider votre sauvegarde PostgreSQL en restaurant la sauvegarde sur un conteneur Docker à l'aide de l'outil pgBackRest pour prendre et restaurer la sauvegarde. Nous supposons que vous savez déjà comment utiliser PostgreSQL, Docker et pgBackRest.
Pourquoi utiliser Docker ?
Docker simplifie l'automatisation, il facilite également le travail d'intégration de notre tâche de validation de sauvegarde PostgreSQL dans un outil CI/CD comme CircleCI, Travis, GitLab ou Jenkins. L'utilisation de Docker évite le temps et les ressources que nous devons consacrer à la mise en place du nouvel environnement pour tester la sauvegarde.
Configuration de la démo
Hôte | Rôle | Installé Forfaits | Crontab |
nœud-1 192.168.0.111 CentOS-7 | Instance principale Posgresql-11. Créé l'utilisateur et la base de données "pgbench" et initialisé avec les tables pgbench. | postgresql-11, pgbackrest-2.15 | Exécution de pgbench toutes les 5 minutes pour simuler la charge de travail. |
nœud-2 | Test Machine - nous exécuterons notre validation Docker sur cet hôte. | docker-ce-18.06, pgbackrest-2.15 | |
nœud-3 192.168.0.113 CentOS-7 | Hôte du référentiel pgBackRest | pgbackrest-2.15 | Exécuter pgbackrest pour effectuer une sauvegarde Incr toutes les 4 heures Sauvegarde des différences tous les jours Sauvegarde complète hebdomadaire |
Pour que pgbackrest fonctionne, j'ai configuré un accès SSH sans mot de passe entre ces nœuds.
L'utilisateur « postgres » sur les nœuds 1 et 2 peut se connecter sans mot de passe à l'utilisateur « pgbackrest » sur le nœud 3.
[[email protected] ~]$ sudo -u postgres ssh [email protected] uptime
13:31:51 up 7:00, 1 user, load average: 0.00, 0.01, 0.05
[[email protected] ~]$ sudo -u postgres ssh [email protected] uptime
13:31:27 up 7:00, 1 user, load average: 0.00, 0.01, 0.05
L'utilisateur « pgbackrest » sur le nœud 3 peut se connecter sans mot de passe à l'utilisateur « postgres » sur le nœud-1 et le nœud-2.
[[email protected] ~]$ sudo -u pgbackrest ssh [email protected] uptime
13:32:29 up 7:02, 1 user, load average: 1.18, 0.83, 0.58
[[email protected] ~]$ sudo -u pgbackrest ssh [email protected] uptime
13:32:33 up 7:01, 1 user, load average: 0.00, 0.01, 0.05
Présentation de la validation de sauvegarde
Vous trouverez ci-dessous un bref aperçu des étapes que nous suivrons pour notre validation de sauvegarde PostgreSQL.
- À l'aide de la commande pgbackrest restore, nous allons récupérer la dernière sauvegarde de l'hôte de référentiel pgBackRest (nœud-3) vers le répertoire de la machine de test (nœud-2) /var/lib/pgsql/11/data
- Pendant l'exécution du docker, nous montons le répertoire /var/lib/pgsql de la machine hôte (nœud-2) sur le conteneur docker et démarrons le démon postgres/postmaster à partir du répertoire monté. Nous exposerions également le port 5432 du conteneur au port 15432 de la machine hôte.
- Une fois que le conteneur Docker a commencé à s'exécuter, nous nous connectons à la base de données PostgreSQL via le nœud 2:15432 et vérifions que toutes les tables et lignes sont restaurées. Nous vérifions également les journaux PostgreSQL pour nous assurer qu'il n'y a pas de message ERROR pendant la récupération et que l'instance a également atteint l'état cohérent.
La plupart des étapes de validation de la sauvegarde seront effectuées sur le nœud hôte 2.
Construire l'image Docker
Sur le nœud 2, créez Dockerfile et créez l'image docker "postgresql:11". Dans le Dockerfile ci-dessous, nous appliquerons les modifications suivantes sur l'image de base centos:7.
- Installation de postgresql-11, pgbackrest et openssh-clients. Openssh-clients est nécessaire pour pgbackrest.
- Configuration de pgbackrest - Nous avons besoin de la configuration de pgbackrest dans l'image pour tester le PITR, sans la configuration de pgbackrest, restore_command échouerait. Dans le cadre de la configuration de pgbackrest
- Nous ajoutons l'adresse IP de l'hôte du référentiel pgbackrest (192.168.0.113) dans le fichier de configuration /etc/pgbackrest.conf.
- Nous avons également besoin d'un accès SSH sans mot de passe entre le conteneur Docker et l'hôte du référentiel pgbackrest. Pour cela, je copie SSH_PRIVATE_KEY que j'ai déjà généré et j'ai également ajouté sa clé publique à l'hôte du référentiel pgbackrest ( [email protected] ).
- VOLUME ["${PGHOME_DIR}"] - Définit le répertoire du conteneur /var/lib/pgsql comme point de montage. Lors de l'exécution de la commande docker run, nous spécifierons le répertoire hôte du nœud 2 à ce point de montage.
- USER postgres - Toute commande exécutée sur le conteneur sera exécutée en tant qu'utilisateur postgres.
$ cat Dockerfile
FROM centos:7
ARG PGBACKREST_REPO_HOST
ARG PGHOME_DIR=/var/lib/pgsql
## Adding Postgresql Repo for CentOS7
RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
## Installing PostgreSQL
RUN yum -y install postgresql11 postgresql11-server postgresql11-devel postgresql11-contrib postgresql11-libs pgbackrest openssh-clients
## Adding configuration for pgbackrest, needed for WAL recovery and replication.
RUN echo -ne "[global]\nrepo1-host=${PGBACKREST_REPO_HOST}\n\n[pgbench]\npg1-path=/var/lib/pgsql/11/data\n" > /etc/pgbackrest.conf
## Adding Private Key to the Docker. Docker container would use this private key for pgbackrest wal recovery.
RUN mkdir -p ${PGHOME_DIR}/.ssh && chmod 0750 ${PGHOME_DIR}/.ssh
COPY --chown=postgres:postgres ./SSH_PRIVATE_KEY ${PGHOME_DIR}/.ssh/id_rsa
RUN chmod 0600 ${PGHOME_DIR}/.ssh/id_rsa
RUN echo -ne "Host ${PGBACKREST_REPO_HOST}\n\tStrictHostKeyChecking no\n" >> ${PGHOME_DIR}/.ssh/config
## Making "/var/lib/pgsql" as a mountable directory in the container
VOLUME ["${PGHOME_DIR}"]
## Setting postgres as the default user for any remaining commands
USER postgres
Nous avons maintenant deux fichiers, Dockerfile utilisé par docker build et SSH_PRIVATE_KEY que nous allons copier sur l'image docker.
$ ls
Dockerfile SSH_PRIVATE_KEY
Exécutez la commande ci-dessous sur le nœud 2 pour créer notre image Docker. J'ai mentionné l'adresse IP de l'hôte du référentiel pgbackrest dans la commande et cette adresse IP sera utilisée dans le paramètre "repo-host" de pgbackrest.
$ docker build --no-cache -t postgresql:11 --build-arg PGBACKREST_REPO_HOST=192.168.0.113 .
Sending build context to Docker daemon 230.4kB
Step 1/12 : FROM centos:7
---> 9f38484d220f
Step 2/12 : ARG PGBACKREST_REPO_HOST
---> Running in 8b7b36c6f151
Removing intermediate container 8b7b36c6f151
---> 31510e46e286
Step 3/12 : ARG PGHOME_DIR=/var/lib/pgsql
...
Step 4/12 : RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
...
...
Step 12/12 : USER postgres
---> Running in c91abcf46440
Removing intermediate container c91abcf46440
---> bebce78df5ae
Successfully built bebce78df5ae
Successfully tagged postgresql:11
Assurez-vous que l'image est construite avec succès et vérifiez que l'image "postgresql:11" est créée récemment, comme indiqué ci-dessous.
$ docker image ls postgresql:11
REPOSITORY TAG IMAGE ID CREATED SIZE
postgresql 11 2e03ed2a5946 3 minutes ago 482MB
Restauration de la sauvegarde PostgreSQL
Nous allons maintenant restaurer notre sauvegarde PostgreSQL maintenue dans le nœud 3 de l'hôte du référentiel de sauvegarde pgbackrest.
Ci-dessous se trouve le fichier de configuration pgbackrest présent sur l'hôte node-2 et j'ai mentionné le node-3 comme hôte du référentiel pgbackrest. Le répertoire mentionné dans le paramètre pg1-path est l'endroit où le répertoire de données PostgreSQL serait restauré.
[[email protected] ~]$ cat /etc/pgbackrest.conf
[global]
log-level-file=detail
repo1-host=node-3
[pgbench]
pg1-path=/var/lib/pgsql/11/data
En utilisant la commande de restauration pgbackrest ci-dessous, le répertoire de données postgresql sera restauré au nœud-2 :/var/lib/pgsql/11/data.
Pour valider le PITR avec la sauvegarde pgbackrest, j'ai défini --type=time --target='2019-07-30 06:24:50.241352+00', afin que la récupération WAL s'arrête avant la temps mentionné.
[[email protected] ~]$ sudo -u postgres bash -c "/usr/bin/pgbackrest --type=time --target='2019-07-30 06:24:50.241352+00' --target-action=promote --recovery-option='standby_mode=on' --stanza=pgbench restore"
La commande ci-dessus peut prendre du temps en fonction de la taille de la sauvegarde et de la bande passante du réseau. Une fois restauré, vérifiez la taille du répertoire de données et vérifiez également recovery.conf.
[[email protected] ~]$ sudo -u postgres du -sh /var/lib/pgsql/11/data
2.1G /var/lib/pgsql/11/data
[[email protected] ~]$ sudo -u postgres cat /var/lib/pgsql/11/data/recovery.conf
standby_mode = 'on'
restore_command = '/usr/bin/pgbackrest --stanza=pgbench archive-get %f "%p"'
recovery_target_time = '2019-07-30 06:24:50.241352+00'
Désactiver le mode d'archivage pour le conteneur Docker PostgreSQL.
[[email protected] ~]$ sudo -u postgres bash -c "echo 'archive_mode = off' >> /var/lib/pgsql/11/data/postgresql.auto.conf"
Démarrez le conteneur docker avec l'image "postgresql:11". Dans la commande nous sommes
-
Définir le nom du conteneur comme "pgbench"
-
Montage du répertoire hôte docker (nœud-2) /var/lib/psql sur le répertoire du conteneur docker /var/lib/psql
-
Exposer le port de conteneur 5432 au port 15432 sur le nœud 2.
-
Démarrer le démon postgres à l'aide de la commande /usr/pgsql-11/bin/postmaster -D /var/lib/pgsql/11/data
[[email protected] ~]$ docker run --rm --name "pgbench" -v /var/lib/pgsql:/var/lib/pgsql -p 15432:5432 -d postgresql:11 /usr/pgsql-11/bin/postmaster -D /var/lib/pgsql/11/data
e54f2f65afa13b6a09236a476cb1de3d8e499310abcec2b121a6b35611dac276
Vérifiez que le conteneur "pgbench" est créé et en cours d'exécution.
[[email protected] ~]$ docker ps -f name=pgbench
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e54f2f65afa1 postgresql:11 "/usr/pgsql-11/bin/p…" 34 seconds ago Up 33 seconds 0.0.0.0:15432->5432/tcp pgbench
Valider PostgreSQL
Étant donné que le répertoire hôte /var/lib/pgsql est partagé avec le conteneur docker, les journaux générés par le service PostgreSQL sont également visibles depuis le nœud-2. Vérifiez le journal d'aujourd'hui pour vous assurer que PostgreSQL a bien démarré sans ERREUR et assurez-vous que les lignes de journal ci-dessous sont présentes.
[[email protected] ~]$ sudo -u postgres tailf /var/lib/pgsql/11/data/log/postgresql-Tue.csv
..
2019-07-30 06:38:34.633 UTC,,,7,,5d3fe5e9.7,5,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"consistent recovery state reached at E/CE000210",,,,,,,,,""
2019-07-30 06:38:34.633 UTC,,,1,,5d3fe5e9.1,2,,2019-07-30 06:38:33 UTC,,0,LOG,00000,"database system is ready to accept read only connections",,,,,,,,,""
2019-07-30 06:38:35.236 UTC,,,7,,5d3fe5e9.7,6,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"restored log file ""000000010000000E000000CF"" from archive",,,,,,,,,""
2019-07-30 06:38:36.210 UTC,,,7,,5d3fe5e9.7,7,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"restored log file ""000000010000000E000000D0"" from archive",,,,,,,,,""
...
2019-07-30 06:39:57.221 UTC,,,7,,5d3fe5e9.7,37,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"recovery stopping before commit of transaction 52181192, time 2019-07-30 06:25:01.576689+00",,,,,,,,,""
...
2019-07-30 06:40:00.682 UTC,,,7,,5d3fe5e9.7,47,,2019-07-30 06:38:33 UTC,1/0,0,LOG,00000,"archive recovery complete",,,,,,,,,""
Le message "état de récupération cohérent atteint à E/CE000210", indique qu'avec le répertoire de données de sauvegarde pgbackrest, nous avons pu atteindre un état cohérent.
Le message "récupération de l'archive terminée", indique que nous sommes en mesure de rejouer le fichier WAL sauvegardé par pgbackrest et de pouvoir le récupérer sans aucun problème.
Connectez-vous à l'instance postgresql via le port local 15432 et vérifiez les tables et le nombre de lignes.
[[email protected] ~]$ sudo -iu postgres /usr/pgsql-11/bin/psql -p 15432 -h localhost -U pgbench
Password for user pgbench:
psql (11.4)
Type "help" for help.
pgbench=> \dt
List of relations
Schema | Name | Type | Owner
--------+------------------+-------+---------
public | pgbench_accounts | table | pgbench
public | pgbench_branches | table | pgbench
public | pgbench_history | table | pgbench
public | pgbench_tellers | table | pgbench
(4 rows)
pgbench=> select * from pgbench_history limit 1;
tid | bid | aid | delta | mtime | filler
-----+-----+---------+-------+----------------------------+--------
98 | 3 | 2584617 | 507 | 2019-07-30 06:20:01.412226 |
(1 row)
pgbench=> select max(mtime) from pgbench_history ;
max
----------------------------
2019-07-30 06:22:01.402245
(1 row)
pgbench=> select count(1) from pgbench_history ;
count
-------
90677
(1 row)
pgbench=> select count(1) from pgbench_accounts ;
count
----------
10000000
(1 row)
Nous avons maintenant restauré notre sauvegarde PostgreSQL sur un conteneur Docker et également vérifié le PITR. Une fois la sauvegarde validée, nous pouvons arrêter le conteneur et supprimer le répertoire de données.
[[email protected] ~]$ docker stop pgbench
pgbench
[[email protected] ~]$ sudo -u postgres bash -c "rm -rf /var/lib/pgsql/11/data && mkdir -p /var/lib/pgsql/11/data && chmod 0700 /var/lib/pgsql/11/data"
Conclusion
Dans ce blog, j'ai démontré la validation de la sauvegarde à l'aide d'une petite base de données sur une petite machine virtuelle VirtualBox. Pour cette raison, la validation de la sauvegarde a été effectuée en quelques minutes seulement. Il est important de noter qu'en production, vous devrez choisir une machine virtuelle appropriée avec suffisamment de mémoire, de processeur et de disque pour permettre à la validation de la sauvegarde de se terminer avec succès. Vous pouvez également automatiser l'ensemble du processus de validation dans un script bash ou même en l'intégrant à un pipeline CI/CD afin de pouvoir valider régulièrement nos sauvegardes PostgreSQL.