Restaurer une base de données depuis Barman

Les accidents arrivent même aux meilleurs. Il y a quelques semaines avant l'écriture de ce billet, j'ai par mégarde DROPé une base de données sur le serveur de prod. Certes, une manipulation bien maladroite mais bon, la maladresse fait partie du jeu non ?

Bref. Il fallait que je restaure la base de données d'une manière ou d'une autre. Pour celles et ceux qui suivent mon flux RSS ou me lisent depuis un petit moment se rappelleront certainement que j'utilise pgBarman pour sauvegarder mon serveur de bases de données.

Récupérer la sauvegarde

Heureusement que l'application affectée hurlait au scandale de ne pas pouvoir se connecter à sa base de données et j'ai donc pu avoir l'heure de l'incident.

Pour récupérer une sauvegarde de la base de données, rien de plus simple, ou presque:

barman recover \
    --target-time "date" \
    --remote-ssh-command "user@hote" \
    serveur \
    sauvegarde \
    /chemin/de/restauration

Je pense qu'il va sans dire de s'assurer d'avoir suffisament d'espace pour accueillir tout le dossier de données du serveur PostgreSQL et de mettre les bonnes permissions sur le dossier qui réceptionnera votre sauvegarde.

J'ai préféré travailler sur une copie, au cas où quelque chose se passerait mal.

Configurer le serveur PostgreSQL temporaire

Ce que vous récupérez est le serveur de bases complet, configurations et autres bases de données. Par contre, il y a évidemment quelques éléments à rectifier parce que PostgreSQL, dans la version 12, refusera de démarrer avec un fichier recovery.conf, même vide.

Ce qui faudra faire à la place est créer un fichier recovery.signal puis de transvaser le contenu de recovery.conf à la tête du fichier principal postgresql.conf.

Il faudra aussi changer des variables de chemins tels que:

  • data_directory;
  • hba_file;
  • ident_file.

Commenter ou changer le chemin de external_pid_file et pointer stats_temp_directory vers un dossier existant qui a les bonnes permissions. Un dossier à l'arrache fera l'affaire.

Enfin, parce qu'on a pas de certificat snakeoil à notre disposition, du moins j'en ai pas, on pourra désactiver SSL.

{% warning(title="Attention les vélos") %} Cette installation est temporaire. Désactiver la fonction SSL dans cet environnement ne posera aucun problème puisque personne ne s'y connectera. Par contre, ne le faites pas dans un environnement de production !

Je pense que cet avertissement était implicite, mais je préfère toujours bien signaler les choses comme il faut. {% end %}

Enfin, on pourra démarrer PostgreSQL sur un autre port:

postgres -p port -D /dossier/vers/les/données

Récupérer la base de données désirée

Si tout se passe bien, PostgreSQL ne devrait pas lâcher d'erreurs et rejouer les transactions depuis son journal puis s'arrêter au moment spécifié.

On pourra ensuite se connecter à ce serveur très temporaire histoire de vérifier que la base choisie est présente:

# Se connecter
psql -p port -h hôte -U utilisateur postgres

# Lister les bases
\l

Si tout est là, parfait. Si ce n'est pas là, repartir de la case zéro avec une nouvelle copie. Reculer le recovery_target_time causera une erreur comme quoi le cluster de bases de données est un peu beaucoup neuf.

Enfin, on pourra récupérer la base de données souhaitée avec un coup de pg_dump

pg_dump -p port -h hôte -U utilisateur base_de_donnees > base.sql

et la restaurer sur le serveur de production qui a continué à tourner:

sudo -u postgres psql < base.sql

Et voilà. Normalement tout se passe sans soucis. On peut couper le serveur temporaire et supprimer son dossier de données; on en a plus besoin.

Le mot de la fin

Une procédure qui aurait dû prendre moins de temps qu'elle ne l'a pris de mon côté. Maintenant que je l'ai faite une fois et documentée pour les autres et moi-même, je pense que la prochaine bourde devrait être remise en moins de temps. Devrait, dit-il.

En espérant que la prochaine arrive dans un moment :)