Mise à jour d’une instance PostgreSQL

Magazine
Marque
Linux Pratique
Numéro
143
Mois de parution
mai 2024
Spécialité(s)


Résumé

Cela fait maintenant plusieurs mois que la version 16 est sortie. Il est vraiment temps de mettre à jour notre serveur en version 15 avec la version 16. Pour cela, il existe trois méthodes, et nous allons décrire chacune de ces méthodes dans cet article.


Body

Commençons déjà par dire qu'il n'est pas nécessaire de passer par chaque version intermédiaire. Vous pouvez très bien mettre à jour une version 12 en version 16, sans avoir à faire les passages intermédiaires (versions 13, 14 et 15).

Le point important à savoir lors d'une mise à jour majeure est que les catalogues système changent d'une version majeure à une autre. De nouveaux catalogues peuvent apparaître, les anciens peuvent être modifiés. Par exemple, des colonnes peuvent leur être ajoutées ou supprimées, voire, dans certains cas, renommées ou changées de type. Ces changements dans les catalogues système nécessitent donc un travail préalable pour passer d'une version majeure à une autre, ce qui va occasionner une coupure de service pour les utilisateurs.

La méthode historique (généralement appelée dump/restore) est une méthode sûre, mais potentiellement lente. En fait, plus la volumétrie de l'instance est importante, plus la mise à jour sera longue. Deux autres méthodes (réplication logique et pg_upgrade) sont apparues au fil des années pour éviter justement une coupure importante du service, mais elles sont généralement plus complexes à mettre en place.

1. Installation de PostgreSQL 16

Quelle que soit la méthode sélectionnée, la première étape concerne l'installation de la nouvelle version de PostgreSQL. Seule la méthode pg_upgrade nécessite que la nouvelle version soit installée sur le même serveur. Cette nouvelle version peut être installée sur un nouveau serveur pour les deux autres méthodes. Dans ce cas, c'est généralement l'occasion de passer à un matériel plus performant ou tout du moins de mettre à jour le système d'exploitation.

Sur tous les exemples de cet article, je travaillerai sur le même serveur.

Voici rapidement les commandes exécutées pour l'installation de la version 16 (l'article « Installation de PostgreSQL » de cette série se trouve dans le numéro 139 de Linux Pratique et est aussi disponible sur https://connect.ed-diamond.com/linux-pratique/lp-139/installation-de-postgresql) :

dnf install -y postgresql16-server postgresql16-contrib
mkdir -p /etc/systemd/system/postgresql-16.service.d
cat > /etc/systemd/system/postgresql-16.service.d/override.conf <<_EOF_
[Service]
Environment=PGDATA=/srv/data16
_EOF_
install -d -o postgres -g postgres -m 700 /srv/data16
PGSETUP_INITDB_OPTIONS="--data-checksums" /usr/pgsql-16/bin/postgresql-16-setup initdb

Si vous suivez bien notre série sur PostgreSQL, vous avez peut-être remarqué que je n'ai pas utilisé l'option --wal-dir avec l'outil initdb. Comme je n'ai pas de partition pour les journaux de transactions de la nouvelle version, je ne déplace pas immédiatement le répertoire des journaux de transactions. Je ne le ferai qu'à la fin.

Pour la configuration du serveur, il est possible de copier les fichiers pg_hba.conf et pg_ident.conf de l'ancienne version :

cp /srv/data/pg_{hba,ident}.conf /srv/data16

Par contre, il ne faut jamais copier le fichier postgresql.conf de l'ancienne version vers la nouvelle version, car il manquerait les nouveaux paramètres et surtout les paramètres qui ont changé de nom se retrouveraient avec l'ancien nom, ce qui empêcherait le démarrage du service. Dans notre cas, notre configuration se trouve dans le fichier linuxpratique.conf et nous n'avons pas configuré de paramètres qui ont changé de nom, donc nous pouvons le copier sans souci :

install -o postgres -g postgres -m 600 /srv/data/linuxpratique.conf /srv/data16

Comme nous allons avoir deux services PostgreSQL démarrés sur le même serveur, leur numéro de port respectif doit être différent. Il est donc nécessaire d'éditer le fichier /srv/data16/linuxpratique.conf pour remplacer la ligne du paramètre port par la ligne suivante :

port = 5433

Il nous faut maintenant modifier le fichier /srv/data16/postgresql.conf pour ajouter l'inclusion de notre fichier de configuration. Cela se fait avec cette ligne :

include 'linuxpratique.conf'

Enfin, nous pouvons activer et démarrer le service :

systemctl enable postgresql-16
systemctl start postgresql-16

2. Migration des données

2.1 Méthode dump/restore

Comme dit juste avant, cette méthode est la méthode historique. Elle peut être utilisée dans tous les cas, et elle est sûre. De plus, elle est simple à comprendre.

Elle a cependant un inconvénient de taille : un arrêt de production d'autant plus long que la volumétrie est importante (notamment lors de l'étape de restauration).

L'opération de mise à jour se passe en trois étapes :

  •   couper l'application ;
  •   sauvegarder les objets globaux et chaque base de l'ancienne version ;
  •   restaurer les objets globaux puis chaque base sur la nouvelle version.

Couper l'application revient à l'arrêter. En fait, il ne faut pas qu'il y ait d'écritures sur le serveur pendant les deux étapes suivantes, sinon ces nouvelles écritures ne seront pas migrées. Une solution assez simple et très sûre revient à couper les accès à la base. Cela peut se faire en configurant le fichier pg_hba.conf ou en modifiant les rôles applicatifs. Bref, il y a plusieurs solutions. Il faut juste s'assurer que les écritures ne sont pas possibles sur les bases de l'instance.

Ceci fait, nous pouvons procéder à une sauvegarde complète du serveur avec les outils pg_dump et pg_dumpall. Encore mieux, il est possible d'utiliser pg_back. C'est ce que nous allons faire maintenant :

$ pg_back
2023/12/28 17:36:43 INFO: dumping globals
2023/12/28 17:36:43 INFO: dumping instance configuration
2023/12/28 17:36:43 INFO: dumping database postgres
2023/12/28 17:36:43 INFO: dump of postgres to /srv/backups/pg_back/postgres_2023-12-28T17:36:43+01:00.dump done
2023/12/28 17:36:43 INFO: dumping database b1
2023/12/28 17:36:43 INFO: dump of b1 to /srv/backups/pg_back/b1_2023-12-28T17:36:43+01:00.dump done
2023/12/28 17:36:43 INFO: dumping database b2
2023/12/28 17:36:49 INFO: dump of b2 to /srv/backups/pg_back/b2_2023-12-28T17:36:43+01:00.dump done
2023/12/28 17:36:49 INFO: dumping database temboard
2023/12/28 17:36:49 INFO: dump of temboard to /srv/backups/pg_back/temboard_2023-12-28T17:36:49+01:00.dump done
2023/12/28 17:36:49 INFO: waiting for postprocessing to complete
2023/12/28 17:36:49 INFO: purging old dumps

Ceci fait, il nous faut restaurer cette sauvegarde sur la nouvelle version. Nous commençons par restaurer les objets globaux :

psql -p 5433 -f /srv/backups/pg_back/pg_globals_2023-12-28T17:36:43+01:00.sql

Cette commande va se plaindre que le rôle postgres existe déjà. C'est normal, il est créé automatiquement par l'outil initdb. Puis nous pouvons restaurer chaque base :

pg_restore -p 5433 -C -d postgres /srv/backups/pg_back/b1_2023-12-28T17:36:43+01:00.dump
pg_restore -p 5433 -C -d postgres /srv/backups/pg_back/b2_2023-12-28T17:36:43+01:00.dump
pg_restore -p 5433 -C -d postgres /srv/backups/pg_back/temboard_2023-12-28T17:36:49+01:00.dump

Comme nous pouvons le voir, cette méthode est vraiment très simple. Elle utilise des outils de sauvegarde standards normalement connus. Dans mon cas, cela a été très rapide vu que les bases ont une volumétrie minuscule. Cependant, pour des bases conséquentes, l’opération complète peut prendre de nombreuses heures pendant lesquelles les applications ne peuvent pas travailler.

2.2 Méthode réplication logique

Contrairement à la réplication physique qui ne peut pas se faire entre deux serveurs ayant une version majeure différente, la réplication logique peut se faire. Il est possible d'utiliser la solution native ou une solution externe (comme Slony par exemple), mais cet article n'abordera que la solution native.

Cette méthode nécessite de mettre en place la réplication logique sur chaque base à récupérer sur le nouveau serveur en version 16. Mais pour cela, il faut déjà configurer le serveur actuel pour que les journaux de transaction soient à un niveau compatible avec la réplication logique (valeur logical pour le paramètre wal_level). De plus, nous allons mettre en place une réplication par base. Il faut donc un bon nombre de workers et de slots de réplication. Tout cela passe par la configuration des paramètres wal_level, max_logical_replication_workers (et de ce fait max_worker_processes), et max_replication_slots dans le fichier /srv/data/linuxpratique.conf :

wal_level = logical
max_worker_processes = 30
max_logical_replication_workers = 20
max_replication_slots = 20

Pour que cette modification soit prise en compte, il faut redémarrer le serveur :

systemctl restart postgresql-15

Pour rappel, le serveur en version 15 utilise le port 5432, et le serveur en version 16 utilise le port 5433.

Commençons par sauvegarder la définition des objets globaux sur le serveur en version 15 et à la restaurer sur le serveur en version 16 :

pg_dumpall -p 5432 --globals-only | psql -qp 5433

Le script suivant va récupérer la liste des bases où il est possible de se connecter et, pour chacune de ses bases, va :

  • créer la base sur le serveur en version 16 ;
  • sauvegarder le schéma de la base sur le serveur en version 15 ;
  • restaurer ce schéma sur cette base du serveur en version 16 ;
  • créer la publication de toutes les tables de la base du serveur en version 15 ;
  • abonner le serveur en version 16 à la publication tout juste créée.
psql -p 5432 -XAtc "SELECT datname FROM pg_database WHERE datallowconn" | while read base
do
  createdb -p 5433 ${base}
  pg_dump -p 5432 -s ${base} | psql -qp 5433 ${base}
  psql -p 5432 -c "CREATE PUBLICATION pub_${base} FOR ALL TABLES" ${base}
  psql -p 5433 -c "CREATE SUBSCRIPTION sub_${base} CONNECTION 'dbname=${base}' PUBLICATION pub_${base}" ${base}
done

Ce script donnera deux erreurs sur la création des bases postgres et template1. Elles ne peuvent pas être créées étant donné qu’elles existent déjà.

À chaque création de souscription (ou abonnement), PostgreSQL va commencer par une phase de synchronisation des données entre le serveur en version 15 et le serveur en version 16. Dans mon cas, j’ai quatre bases, et donc quatre synchronisations en cours. Je dois attendre la fin de ces synchronisations, et pour cela, je dois surveiller le catalogue système pg_stat_replication :

psql -p 5432 -c "SELECT application_name, pg_current_wal_lsn(), sent_lsn FROMpg_stat_replication"
application_name | pg_current_wal_lsn | sent_lsn
-----------------+--------------------+------------
sub_postgres     | 0/52008E98         | 0/52008E98
sub_b1           | 0/52008E98         | 0/52008E98
sub_b2           | 0/52008E98         | 0/52008E98
sub_temboard     | 0/52008E98         | 0/52008E98
(4 rows)

Avec ce résultat, la deuxième colonne a la même valeur que la troisième colonne pour chaque ligne. Les quatre synchronisations sont donc terminées.

Il est néanmoins un type de données à synchroniser. Les séquences ne font pas partie des données répliquées. Il convient donc de les réinitialiser manuellement :

psql -p 5432 -Atc        \
  "SELECT format('ALTER SEQUENCE %I.%I RESTART WITH %s', schemaname, sequencename, last_value+1)
   FROM pg_sequences" b1 \
  | psql -p 5433 b1

Maintenant, nous pouvons arrêter le serveur en version 15 :

systemctl stop postgresql-15

et supprimer les souscriptions du serveur en version 16 :

psql -p 5433 -XAtc "SELECT datname FROM pg_database WHERE datallowconn" | while read base
do
  psql -p 5433 -c "ALTER SUBSCRIPTION sub_${base} DISABLE"                \
               -c "ALTER SUBSCRIPTION sub_${base} SET (slot_name = NONE)" \
               -c "DROP SUBSCRIPTION sub_${base}"                        \
               ${base}
done

Simplement supprimer la souscription ne suffit pas. En effet, à l’exécution d’un DROP SUBSCRIPTION, PostgreSQL va se connecter au serveur de publication pour supprimer le slot de réplication. Or nous avons arrêté le serveur en version 15 pour éviter de nouvelles écritures sur ce serveur. Donc nous devons supprimer l’information du slot de réplication sur la souscription (c’est le but de l’ordre ALTER SUBSCRIPTION ... SET (slot_nane=NONE), mais pour cela, nous devons tout d’abord désactiver la souscription, d’où le ALTER SUBSCRIPTION ... DISABLE.

2.3 Méthode pg_upgrade

pg_upgrade est certainement l'outil le plus récent, mais il a quand même maintenant une dizaine d'années. Autant dire que les bugs assez catastrophiques des premières années sont du passé.

Il fonctionne en deux modes : copie de fichiers et liens physiques. Le mode copie est plus long que le mode lien physique, mais il a l'avantage de permettre un retour en arrière si nécessaire, ce qui ne sera pas le cas avec le mode lien physique. Dans le cas de l'utilisation de ce deuxième mode, il convient donc de s'assurer d'avoir à sa disposition une sauvegarde complète de l'instance au cas malheureux où un retour en arrière serait nécessaire.

Les étapes de la mise à jour sont très restreintes : arrêt du serveur, lancement de pg_upgrade, démarrage du serveur. Voici un exemple concernant ma VM :

systemctl stop postgresql-15
systemctl stop postgresql-16
/usr/pgsql-16/bin/pg_upgrade \
  -b /usr/pgsql-15/bin       \
  -B /usr/pgsql-16/bin       \
  -d /srv/data               \
  -D /srv/data16
systemctl start postgresql-16

L'outil pg_upgrade indique qu’il faut exécuter une étape supplémentaire, mais cette étape est nécessaire, quelle que soit la méthode. Nous la verrons donc dans le prochain chapitre.

3. Nettoyage et remise en place des services

Il reste maintenant du nettoyage à faire pour revenir dans la situation nominale : déplacer les fichiers de données dans /srv/data et les journaux de transactions dans /srv/wal, et utiliser le port 5432 pour le service PostgreSQL en version 16.

Commençons déjà par arrêter les deux serveurs :

systemctl stop postgresql-15
systemctl stop postgresql-16

Nous allons maintenant déplacer les fichiers de données et les journaux de transactions de la version 15 dans un emplacement autre en attendant de les supprimer après quelques jours :

mv /srv/data /srv/data15
rm /srv/data15/pg_wal
install -d -o postgres -g postgres -m 700 /srv/data15/pg_wal
mv /srv/wal/* /srv/data15/pg_wal

Nous pouvons maintenant déplacer les fichiers de données et les journaux de transaction de la version 16 à leur emplacement nominal :

mv /srv/data16 /srv/data
mv /srv/data/pg_wal/* /srv/wal
rm -r /srv/data/pg_wal/
ln -s /srv/wal /srv/data/pg_wal

Enfin, avant de démarrer PostgreSQL, nous devons configurer le port de connexion à 5432 :

sed -i.old -e 's/port = 5433/port = 5432/' /srv/data/linuxpratique.conf

Notez que si vous voulez toujours pouvoir démarrer la version 15 en même temps que la version 16, vous devez changer son numéro de port (par le 5433 par exemple).

Il ne reste plus qu’à modifier le répertoire de données dans le script de démarrage de la version 16 :

cat > /etc/systemd/system/postgresql-16.service.d/override.conf <<_EOF_
[Service]
Environment=PGDATA=/srv/data
_EOF_

Il est enfin possible de démarrer PostgreSQL version 16 :

systemctl daemon-reload
systemctl start postgresql-16

La version 15 reste éteinte, mais disponible dans le cas où des vérifications seraient à entreprendre (mais n’oubliez pas de modifier son numéro de port et son script de démarrage).

Une fois la nouvelle version en place, il est essentiel d’exécuter un VACUUM ANALYZE sur toutes les bases. C’était justement l’étape supplémentaire préconisée par pg_upgrade, mais, encore une fois, elle est valable pour toutes les méthodes. Cela peut se faire en une seule commande Unix :

/usr/pgsql-16/bin/vacuumdb --all --analyze-in-stages

Nous avons mis en place deux services de sauvegarde. Il faut s’assurer qu’ils fonctionnent avec la nouvelle version.

Ce ne sera pas le cas immédiatement pour pg_back. En effet, nous lui avons indiqué dans son fichier de configuration où se trouvaient les binaires de PostgreSQL. Il faut donc modifier sa configuration. Cela se fait ainsi :

sed -i.old -e 's#/usr/pgsql-15/bin#/usr/pgsql-16/bin#' /etc/pg_back/pg_back.conf

Quant à pgbackrest, les sauvegardes précédemment effectuées sont incompatibles sur une autre version majeure. Il est donc préférable de supprimer les anciennes sauvegardes et de refaire une sauvegarde complète dès que possible :

rm -rf /srv/backups/pgbackrest/*
pgbackrest stanza-create --stanza linuxpratique
pgbackrest backup --stanza linuxpratique

Quant aux outils de supervision/monitoring, pgBadger n’a pas d’attachement fort à la version majeure. Profitez-en néanmoins pour le mettre à jour. PgCluu et temboard lisant les catalogues statistiques, ces derniers ont pu changer entre deux versions majeures. Il est donc essentiel d’avoir une version de ces deux outils compatible avec cette nouvelle version de PostgreSQL. Dans le doute, mettez-les à jour.

Pensez à faire de même pour tous les autres outils se connectant à PostgreSQL : outils d’administration, outils de modélisation, pilotes JDBC ou autre, etc.

4. Suppression de l’ancienne instance

Il est conseillé d’attendre au moins quelques jours, pour s’assurer que la nouvelle version fonctionne bien, que les données n’ont pas été altérées, qu’il n’y a pas eu d’erreurs commises, bref, qu’il n’y a pas de mauvaise surprise suite au passage à la nouvelle version de PostgreSQL. Évidemment, cela nécessite d’avoir suffisamment de place sur le serveur pour héberger deux versions de l’instance, mais il est toujours rassurant d’avoir l’ancienne version en place.

Si tous les voyants sont au vert, il est important de supprimer l’ancienne instance. Pour cela, il faut supprimer les données et les programmes installés. Voici comment faire en trois commandes :

systemctl stop postgresql-15 # au cas ou il serait démarré
rm -rf /srv/data15
dnf remove postgresql-15

5. Quelle méthode choisir ?

Maintenant que nous avons vu les trois méthodes possibles, discutons de laquelle choisir.

pg_dump/pg_restore :

+ fonctionne dans tous les cas

+ mise en place simple

+ supprime la fragmentation

- coupure de service importante

- retour en arrière possible, mais sans conservation des nouvelles données

réplication logique :

+ coupure de service très faible

+ supprime la fragmentation

+ retour en arrière possible avec conservation des nouvelles données (simple avec Slony, compliqué avec réplication native)

- peut ne pas fonctionner (voir plus bas)

- mise en place complexe

- mise en place encore plus complexe si plus d'une base utilisateur

- pas de changement de structure de la base pendant la synchronisation

- clé primaire ou contrainte d'unicité obligatoire pour toutes les tables

- pas de support des Large Objects

pg_upgrade :

+ mise en place simple

+ coupure de service faible

- peut ne pas fonctionner

- conserve la fragmentation

- retour en arrière possible si mode copie, mais sans conservation des nouvelles données

Conclusion : et les versions mineures ?

Il n'y a strictement aucune raison valable d'ignorer les versions mineures. Elles ne contiennent que des corrections de bugs, il faut donc les installer. C'est heureusement bien plus simple et bien plus rapide que les mises à jour majeures. Généralement, il suffit d'arrêter le service PostgreSQL, de mettre à jour les paquets, puis de redémarrer le service. Donc :

systemctl stop postgresql-16
dnf update
systemctl start postgresql-16

Il est néanmoins préférable de lire les Release Notes de la version pour savoir si des opérations supplémentaires sont à réaliser. C'est rare, mais cela peut arriver, autant le savoir.



Article rédigé par

Par le(s) même(s) auteur(s)

Supervision d’une instance PostgreSQL

Magazine
Marque
Linux Pratique
Numéro
142
Mois de parution
mars 2024
Spécialité(s)
Résumé

Maintenant que nous sommes rassurés suite à l’installation de solutions de sauvegarde [1], il est temps de s’occuper de la supervision de notre instance. Il existe différents types d’outils, certains en ligne de commandes, certains graphiques (généralement une application web), certains font de la rétro-analyse alors que d’autres font de la supervision en direct. Encore une fois avec PostgreSQL, les outils sont nombreux et la difficulté vient principalement du choix offert.

Les derniers articles Premiums

Les derniers articles Premium

PostgreSQL au centre de votre SI avec PostgREST

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Dans un système d’information, il devient de plus en plus important d’avoir la possibilité d’échanger des données entre applications. Ce passage au stade de l’interopérabilité est généralement confié à des services web autorisant la mise en œuvre d’un couplage faible entre composants. C’est justement ce que permet de faire PostgREST pour les bases de données PostgreSQL.

La place de l’Intelligence Artificielle dans les entreprises

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

L’intelligence artificielle est en train de redéfinir le paysage professionnel. De l’automatisation des tâches répétitives à la cybersécurité, en passant par l’analyse des données, l’IA s’immisce dans tous les aspects de l’entreprise moderne. Toutefois, cette révolution technologique soulève des questions éthiques et sociétales, notamment sur l’avenir des emplois. Cet article se penche sur l’évolution de l’IA, ses applications variées, et les enjeux qu’elle engendre dans le monde du travail.

Petit guide d’outils open source pour le télétravail

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Ah le Covid ! Si en cette période de nombreux cas resurgissent, ce n’est rien comparé aux vagues que nous avons connues en 2020 et 2021. Ce fléau a contraint une large partie de la population à faire ce que tout le monde connaît sous le nom de télétravail. Nous avons dû changer nos habitudes et avons dû apprendre à utiliser de nombreux outils collaboratifs, de visioconférence, etc., dont tout le monde n’était pas habitué. Dans cet article, nous passons en revue quelques outils open source utiles pour le travail à la maison. En effet, pour les adeptes du costume en haut et du pyjama en bas, la communauté open source s’est démenée pour proposer des alternatives aux outils propriétaires et payants.

Sécurisez vos applications web : comment Symfony vous protège des menaces courantes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les frameworks tels que Symfony ont bouleversé le développement web en apportant une structure solide et des outils performants. Malgré ces qualités, nous pouvons découvrir d’innombrables vulnérabilités. Cet article met le doigt sur les failles de sécurité les plus fréquentes qui affectent même les environnements les plus robustes. De l’injection de requêtes à distance à l’exécution de scripts malveillants, découvrez comment ces failles peuvent mettre en péril vos applications et, surtout, comment vous en prémunir.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 126 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous