Vallée de Munster, le 25 avril 2025
pglift, le composant central de notre solution d’industrialisation pour PostgreSQL, est à présent disponible en version 2.0.
Cette nouvelle version apporte son lot de correctifs, nouvelles fonctionnalités et améliorations. Nous vous proposons, aujourd’hui, un aperçu de quelques-unes des nouveautés majeures depuis pglift 1.0.
Nettoyage de fonctionnalités obsolètes et amélioration des tests
Avec cette nouvelle version majeure, les développeurs de pglift ont
entrepris un important travail de nettoyage en supprimant les
fonctionnalités déclarées obsolètes, ainsi que le code associé. Cette
démarche a notamment conduit à la suppression de certains paramètres de
configuration (par exemple : prometheus.queriespath
, cli.logpath
…)
et d’options dans les interfaces Ansible ou en ligne de commande (comme
--jobs
pour la commande pglift instance upgrade
). Tous les
changements susceptibles d’impacter les utilisateurices sont répertoriés
dans la note de
version
détaillée du projet.
Parallèlement, un effort continu est mené pour faire évoluer la couverture de tests (unitaires, fonctionnels ou end-to-end). Cette version s’inscrit dans cette démarche, en intégrant notamment la réécriture d’éléments essentiels de la base de code. Ce travail de fond contribue à maintenir un haut niveau de qualité pour le projet pglift.
Enfin, la version de Python et les dépendances utilisées par pglift ont
évolué tout au long du cycle de vie de la version 1. La version 2.0 de
pglift requiert désormais Python 3.10 au minimum. Les développeurs
veillent à maintenir à jour les principales librairies utilisées
(pydantic
, pydantic-settings
, httpx
…), afin de garantir la
stabilité, la maintenabilité et la qualité du projet.
Support pour PostgreSQL 12 et 17
pglift s’aligne sur les versions de PostgreSQL supportées par la communauté. Il est donc maintenant possible de déployer, gérer et utiliser des instances avec PostgreSQL 17. A contrario, la version 12 (hors maintenance depuis le 14 novembre 2024) n’est plus supportée.
Sans configuration spécifique, installer le paquet pour PostgreSQL
server 17 (postgresql-17
sous Debian, postgresql17-server
pour la
famille RedHat) permet d’activer et utiliser cette version avec pglift :
$ pglift site-settings --output-format=json | jq -r '.postgresql.versions[].version'
13
14
15
16
$ sudo apt install postgresql-17
…
$ pglift site-settings --output-format=json | jq -r '.postgresql.versions[].version'
13
14
15
16
17
$ pglift instance create prod --version 17 --port 5445
INFO initializing PostgreSQL
INFO configuring PostgreSQL authentication
INFO configuring PostgreSQL
INFO starting PostgreSQL 17/prod
INFO creating instance dumps directory: /srv/dumps/17-prod
$ pglift instance list
┏━━━━━━━┳━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ name ┃ version ┃ port ┃ datadir ┃ status ┃
┡━━━━━━━╇━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ prod │ 17 │ 5445 │ /srv/pgsql/17/prod/data │ running │
└───────┴─────────┴──────┴──────────────────────────┴─────────┘
Création d’une instance depuis un backup pgBackRest
Depuis la version 1.7, il est possible de créer une instance depuis une sauvegarde disponible dans une stanza pgBackrest précédemment configurée. Cette fonctionnalité permet de récupérer ou recréer une instance depuis une sauvegarde.
Dans l’exemple qui suit, nous allons :
- initier une instance ;
- supprimer les données de l’instance (pour simuler une perte accidentelle) ;
- et pour finir, la récupérer depuis la stanza pgBackRest.
$ pglift instance create prod --version 17 --port 5775 --pgbackrest-stanza prod-stz
INFO initializing PostgreSQL
INFO configuring PostgreSQL authentication
INFO configuring PostgreSQL
INFO starting PostgreSQL 17/prod
INFO creating role 'backup'
INFO configuring pgBackRest stanza 'prod-stz' for
pg1-path=/srv/pgsql/17/prod/data
INFO creating pgBackRest stanza 'prod-stz'
INFO checking pgBackRest configuration for stanza 'prod-stz'
INFO creating instance dumps directory: /srv/dumps/17-prod
$ pglift instance exec prod psql
[17/prod] postgres@~=# CREATE DATABASE myapp;
CREATE DATABASE
$ pglift instance stop prod
$ INFO stopping PostgreSQL 17/prod
$ rm -rf /srv/pgsql/17/prod/{data,wal} # on supprime les données de notre instance
La commande pglift instance list
, retourne maintenant une liste vide.
Nos données sont potentiellement perdues, heureusement il est possible
de les récupérer depuis la stanza pgBackRest (on utilise à nouveau
prod-stz).
On peut reconstruire notre instance en utilisant un backup depuis la
stanza prod-stz
:
$ pglift instance create prod --version 17 --port 5775 --pgbackrest-stanza prod-stz
INFO initializing PostgreSQL
> Confirm creation of instance from pgBackRest backup [y/n] (y): y
INFO restoring from a pgBackRest backup
…
INFO configuring pgBackRest stanza 'prod-stz' for
pg1-path=/srv/pgsql/17/prod/data
INFO creating pgBackRest stanza 'prod-stz'
INFO checking pgBackRest configuration for stanza 'prod-stz'
Nos données sont à nouveau disponibles :
[17/prod] postgres@~=# \l+ myapp
List of databases
-[ RECORD 1 ]-----+-----------
Name | myapp
Owner | postgres
…
Édition du pg_hba
Depuis la sortie de pglift 1.0, un travail de fond a été mené afin de permettre l’édition des entrées HBA des instances. La version 2.0, en plus de bénéficier de ce travail, permet aussi de modifier les entrées HBA pour les instances configurées via Patroni :
$ pglift instance create demopatroni1 --patroni-cluster=demo-patroni \
--patroni-node=demo-patroni-1 --port 5444
$ cat /srv/pglift/etc/patroni/17-demopatroni1.yaml | yq .postgresql.pg_hba
[
"local all postgres trust",
"local all all trust",
"host all all 127.0.0.1/32 trust",
"host all all ::1/128 trust"
]
L’ajout et la suppression des entrées HBA peut donc être réalisée avec
la commande pglift pghba
. Comme le montre l’exemple suivant, cette
commande valide et modifie la configuration Patroni de l’instance :
# Pour ajouter une entrée
$ pglift pghba -i demopatroni1 add --connection-type host \
--connection-address 10.8.0.1 \
--connection-netmask 24 \
--database postgres \
--user isidore \
--method scram-sha-256
$ cat /srv/pglift/etc/patroni/17-demopatroni1.yaml | yq .postgresql.pg_hba
[
"local all postgres trust",
"local all all trust",
"host all all 127.0.0.1/32 trust",
"host all all ::1/128 trust",
"host postgres isidore 10.8.0.1 24 scram-sha-256"
]
# Pour retirer une entrée
$ pglift pghba -i demopatroni1 remove --connection-type host \
--connection-address 10.8.0.1 \
--connection-netmask 24 \
--database postgres \
--user isidore \
--method scram-sha-256
$ cat /srv/pglift/etc/patroni/17-demopatroni1.yaml | yq .postgresql.pg_hba
[
"local all postgres trust",
"local all all trust",
"host all all 127.0.0.1/32 trust",
"host all all ::1/128 trust"
]
Pour une instance « classique » (sans Patroni), depuis la version 1.8,
l’utilisation de ces commandes entraîne la modification du fichier
pg_hba.conf
de l’instance.
Conversion d’une instance standalone en instance gérée par Patroni
Depuis pglift 1.8, il est possible de convertir une instance PostgreSQL standalone en membre d’une grappe gérée par Patroni.
L’instance standalone prod
initiée de la sorte :
$ pglift instance create prod
INFO initializing PostgreSQL
INFO configuring PostgreSQL authentication
INFO configuring PostgreSQL
INFO starting PostgreSQL 17/prod
INFO creating instance dumps directory: /srv/dumps/17-prod
$ pglift instance status prod
PostgreSQL: running
peut être convertie en membre d’une grappe Patroni (adoption). Cette opération est
réalisable en utilisant la commande pglift instance alter
ou en
ajoutant les options pour Patroni lors de l’utilisation du module
Ansible dalibo.pglift.instance
:
$ pglift instance alter prod --patroni-cluster=demo-patroni \
--patroni-node=demo-patroni-1
INFO configuring PostgreSQL
INFO stopping PostgreSQL 17/prod
INFO setting up Patroni service
INFO starting Patroni 17-prod
$ pglift instance status prod
PostgreSQL: running
Patroni API: running
Nouvelles options pour manipuler les schémas et extensions d’une base
Pour la version 1.7 de pglift, un travail de fond a été réalisé pour permettre de manipuler certains champs complexes, comme les extensions, qui peuvent inclure un nom, une version, et un état (présent ou absent)
Ce travail a notamment été réalisé pour introduire de nouvelles options permettant d’ajouter ou de supprimer des schémas et extensions à une base existante :
$ pglift database create mydb
INFO creating 'mydb' database in 17/prod
$ pglift database alter mydb --add-schema myschema
INFO altering 'mydb' database on instance 17/prod
INFO creating schema 'myschema' in database mydb with owner 'postgres'
pglift database alter mydb --remove-schema myschema
INFO altering 'mydb' database on instance 17/prod
INFO dropping schema myschema from database mydb
$ pglift database alter mydb --add-extension pgcrypto
INFO altering 'mydb' database on instance 17/prod
INFO creating extension 'pgcrypto' in database mydb
$ pglift database alter mydb --remove-extension pgcrypto
INFO altering 'mydb' database on instance 17/prod
INFO dropping extension 'pgcrypto'
Au passage, l’interface ligne de commande a été améliorée pour afficher ces champs complexes. Depuis cette version de pglift, les informations concernant les schemas et extensions d’une base sont plus facilement visibles :
$ pglift database get mydb --output-format=json
{
"name": "mydb",
"owner": "postgres",
"settings": null,
"schemas": [
{
"name": "myschema",
"owner": "postgres"
},
{
"name": "public",
"owner": "pg_database_owner"
}
],
"extensions": [
{
"name": "pgcrypto",
"schema": "public",
"version": "1.3"
}
],
…
}
Ces nouveautés ont aussi permis d’améliorer l’utilisation des options
schemas et extensions via Ansible. Il est maintenant possible de
déclarer l’ajout ou la suppression de ces objets via un Playbook Ansible
(clé state
, valeur present
ou absent
, pour les schemas et extensions) :
- name: my postgresql instances
hosts: localhost
vars:
port: 5432
- name: Add mydb database with schema
dalibo.pglift.database:
name: mydb
instance: prod
schemas:
- name: myschema
state: present
- name: my_other_schema
state: present
extensions:
- name: pgcrypto
state: present
version: 1.3
Ces travaux pour les schemas et extensions ont servi de base
pour ajouter le support des slots de réplication d’une instance.
Depuis pglift 1.8, ce mécanisme peut être utilisé pour créer et
supprimer des slots avec les options --create-slot
et
--drop-slot
ou via le module Ansible
dalibo.pglift.instance
.
Nouveautés de pglift 2.0
Numéro de version facultatif dans les chemins
pglift est à présent paramétrable sans numéro de version pour les
chemins dédiés au PGDATA (datadir
), aux WAL (waldir
) et
pour les sauvegardes logiques (dumps_directory
).
Par exemple, la configuration suivante est maintenant valide et permet de gérer des instances sans le numéro de version dans ces chemins :
---
postgresql:
waldir: /srv/pgsql/{name}/waldir
datadir: /srv/pgsql/{name}/data
dumps_directory: /srv/pgsql/{name}/dumps
$ pglift instance create prod
INFO initializing PostgreSQL
INFO configuring PostgreSQL authentication
INFO configuring PostgreSQL
INFO starting PostgreSQL 17/prod
INFO creating instance dumps directory: /srv/pgsql/prod/dumps
$ pglift instance get prod --output-format=json | jq -r '.wal_directory, .data_directory'
/srv/pgsql/prod/wal
/srv/pgsql/prod/data
Ce changement permet, au contraire de la version 1 de pglift, une plus grande souplesse pour configurer les chemins relatifs aux instances.
Modèle de configuration pour Patroni
Avec cette nouvelle version, il est désormais possible de personnaliser la configuration des instances Patroni. Les utilisateurices peuvent utiliser, pour Patroni, le mécanisme de template déjà disponible pour certains autres composants configurables via pglift.
Par exemple, un·e utilisateurice peut garnir le fichier
${XDG_CONFIG_HOME}/pglift/patroni/patroni.yaml
avec le template
suivant :
---
bootstrap:
dcs:
loop_wait: 10
retry_timeout: 3
watchdog:
mode: 'off'
tags:
demo1: mytag
Ce modèle de configuration sera ensuite utilisé lors de la création des instances Patroni :
$ pglift instance create demo1 --patroni-cluster=pgdemo1 --patroni-node=demo1
$ cat /home/pglift/.local/share/pglift/etc/patroni/17-demo1.yaml | yq .tags
{
"demo1": "mytag"
}
$ cat /home/pglift/.local/share/pglift/etc/patroni/17-demo1.yaml | yq .bootstrap.dcs
{
"loop_wait": 10,
"retry_timeout": 3
}
$ patronictl show-config
loop_wait: 10
retry_timeout: 3
Cette fonctionnalité offre plus de liberté pour configurer Patroni.
Création d’instance sans pgBackRest
pglift 2.0 permet la création d’instance sans pgBackRest et ce même si ce dernier est configuré.
Avec les versions précédentes de pglift, lorsque pgBackRest était
configuré, il était obligatoire de spécifier les options dédiées (Ex :
--pgbackrest-stanza
) lors de la création d’une instance. Par exemple,
avec pglift 1.9 et pgBackRest configuré, l’utilisateurice devait à
minima déclarer la stanza :
$ pglift instance create prod_without_backup
Usage: pglift instance create [OPTIONS] NAME
Try 'pglift instance create --help' for help.
Error: Missing option '--pgbackrest-stanza'.
Il n’est plus obligatoire de spécifier ces options, avec la version 2.0 la commande ci-dessus fonctionne et ce même si pgBackRest est configuré. Dans un tel cas, l’instance sera créée et configurée sans le composant pgBackRest et donc sans sauvegarde au fil de l’eau.
Nouvelles options diff
et dry-run
Option diff
Certaines sous commandes de pglift permettent de visualiser les
modifications réalisées en utilisant l’option --diff
. Cette option est
utilisable directement avec la ligne de commande ou via la collection
Ansible dédiée à
pglift.
Par exemple, la modification du port d’écoute avec l’option --diff
(commande : pglift instance alter pg1 --diff --port 9981
), va afficher
la sortie suivante :
--- /srv/pgsql/17/pg1/data/postgresql.conf
+++ /srv/pgsql/17/pg1/data/postgresql.conf
@@ -61,7 +61,7 @@
# comma-separated list of addresses;
# defaults to 'localhost'; use '*' for all
# (change requires restart)
-port = 5432 # (change requires restart)
+port = 9981 # (change requires restart)
#max_connections = 100 # (change requires restart)
#reserved_connections = 0 # (change requires restart)
#superuser_reserved_connections = 3 # (change requires restart)
Pour utiliser cette fonctionnalité avec Ansible, il est possible
d’appeler ansible-playbook
avec l’option --diff
ou positionner la
clé diff
dans les Playbooks. Le Playbook suivant active cette
fonctionnalité par défaut, les différences seront systématiquement
affichées lors de l’exécution de la tâche :
- name: My postgresql instances
hosts: localhost
tasks:
- name: Create production instance
diff: true
dalibo.pglift.instance:
name: prod
state: started
port: 5432
settings:
max_connections: 200
surole_password: changeme
$ ansible-playbook --diff instance-production.yaml
…
TASK [Create production instance] **************************************
--- before: /srv/pgsql/17/prod/data/pg_hba.conf
+++ after: /srv/pgsql/17/prod/data/pg_hba.conf
@@ -112,15 +112,7 @@
# TYPE DATABASE USER ADDRESS METHOD
-
-# "local" is for Unix domain socket connections only
+local all postgres trust
local all all trust
-# IPv4 local connections:
host all all 127.0.0.1/32 trust
-# IPv6 local connections:
host all all ::1/128 trust
-# Allow replication connections from localhost, by a user with the
-# replication privilege.
-local replication all trust
-host replication all 127.0.0.1/32 trust
-host replication all ::1/128 trust
--- before: /srv/pgsql/17/prod/data/postgresql.conf
+++ after: /srv/pgsql/17/prod/data/postgresql.conf
@@ -61,11 +61,11 @@
# comma-separated list of addresses;
# defaults to 'localhost'; use '*' for all
# (change requires restart)
-#port = 5432 # (change requires restart)
-max_connections = 100 # (change requires restart)
+port = 5432 # (change requires restart)
+max_connections = 200 # (change requires restart)
#reserved_connections = 0 # (change requires restart)
#superuser_reserved_connections = 3 # (change requires restart)
-#unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories
+unix_socket_directories = '/tmp' # comma-separated list of directories
…
Option dry-run
L’option --dry-run
est maintenant disponible pour certaines sous
commandes de pglift. Elle permet de simuler les actions sans effectuer
les modifications réellement.
Par exemple, la sous commande pgconf
, avec l’option --dry-run
,
permet de simuler et visualiser les modifications :
$ pglift --non-interactive pgconf -i prod set --dry-run max_connections=32
INFO configuring PostgreSQL
WARNING instance 17/prod needs restart due to parameter changes: max_connections
max_connections: 16 -> 32
DRY RUN: no changes made
Conclusion
pglift est maintenant utilisé par l’intégralité de nos clients https://www.dalibo.com/socle. La sortie de la version 2.0 est un indicateur important concernant la maturité du projet. C’est le résultat de plusieurs mois de travail, d’échanges et de collaboration avec nos clients.
Afin de rester concis, nous n’avons présenté que quelques fonctionnalités majeures parues depuis pglift 1.0. Cet article aurait pu aussi aborder les améliorations suivantes :
- le support des templates de
configuration
dépendant de la version de PostgreSQL. Par exemple, les
utilisateurices peuvent configurer un template
postgresql/17/postgresql.conf
, il sera ensuite utilisé lors de la manipulation d’instances PostgreSQL 17 ; - la possibilité d’obtenir un shell configuré pour une instance ;
- le support des instances PostgreSQL gérées par Patroni, par la fonctionnalité de montée de version ;
- La possibilité de paramétrer pg_upgrade plus librement, lors de la montée de version d’instances via pglift ;
- des options pour consigner les changements depuis l’interface ligne de commande (capacité d’audit) ;
- plusieurs améliorations (ajout du préfix
pglift_
et gestion de la valeurnull
) dans l’utilisation des variables d’environnement pour surcharger la configuration de pglift ; - l’ajout de notion de profil de
permission
(
read-only
etread-write
) ; - une validation plus stricte de la configuration générée par pglift pour Patroni ;
- la possibilité de choisir la locale lors de la création d’une base de donnée.
Pour plus d’information concernant les nouveauté et correctifs de cette nouvelle version ou pglift en général, nous vous invitons à :
- consulter l’entrepôt, la documentation ou les notes de version du projet ;
- nous contacter pour obtenir plus d’information concernant notre solution d’industrialisation.