Toulouse, le 17 octobre 2023

Aujourd’hui, nous annonçons la version 1.0 de pglift, un nouvel outil pour déployer et exploiter PostgreSQL à grande échelle. Le projet fournit à la fois une interface en ligne de commande pour gérer le cycle de vie de vos bases de données et une collection de modules Ansible pour piloter votre infrastructure as code dans un contexte de production.

À partir de ce jalon 1.0, l’interface utilisateur est stable et le produit considéré comme apte à une utilisation générale.

Qu’est-ce que pglift ?

Le projet vient du besoin des clients de Dalibo de déployer et d’exploiter un grand nombre d’instances PostgreSQL dans leur contexte de production, et ce d’une manière uniforme au sein de leur infrastructure :

  • L’aspect production signifie que PostgreSQL, le moteur de base de données, a souvent besoin d’être complété par d’autres services de sauvegarde, supervision ou haute disponibilité.
  • L’aspect uniforme fait typiquement référence à l’automatisation, ce qui signifie que les DBAs veulent rationaliser le déploiement de leur service de base de données afin de l’exploiter d’une manière plus sûre.

pglift essaie de répondre à ces enjeux en fournissant :

  1. une ligne de commande unifiée et accessible pour exploiter les instances de bases de données d’un site, et,
  2. une collection de modules Ansible pour automatiser le déploiement et l’exploitation au sein d’une infrastructure.

Dans les deux cas, le comportement de pglift est très configurable, depuis la façon dont l’instance PostgreSQL est déployée (authentification, stockage, journalisation, sauvegarde) jusqu’aux composants qui sont configurés à coté de l’instance pour permettre son exploitation dans un contexte de production (sauvegarde physique, supervision, haute disponibilité).

Quiconque souhaitant déployer et exploiter PostgreSQL à un niveau plus élevé que les commandes initdb ou pg_ctl ou avec un besoin plus important d’automatisation pourra trouver un intérêt dans pglift. Ceci va des services informatiques de l’entreprise aux devops qui gèrent leurs infrastructures en suivant les principes du GitOps.

D’un autre coté, pglift n’a pas vocation à être l’unique solution à tous les cas d’usage mais plutôt à être une brique logicielle composable avec d’autres. De ce fait, alors que pglift est un outil local et indépendant d’un framework de gestion d’infrastructure particulier, il s’intègre d’ores et déjà avec Ansible et pourrait être interfacé avec Terraform (ou Kubernetes) de manière similaire.

Même s’il reste aussi configurable que possible, son comportement résulte parfois de choix métiers particuliers, en général guidés par l’expertise de Dalibo.

Fini la théorie, voyons maintenant ce que pglift peut faire !

La ligne de commande

L’élément fondamental de pglift est l’instance, qui est constituée a minima d’une instance PostgreSQL mais inclut généralement des composants satellites. La création d’une instance en ligne de commande se fait comme suit :

$ pglift instance create main --pgbackrest-stanza=main
INFO     initializing PostgreSQL
INFO     configuring PostgreSQL authentication
INFO     configuring PostgreSQL
INFO     starting PostgreSQL 16-main
INFO     creating role 'powa'
INFO     creating role 'prometheus'
INFO     creating role 'backup'
INFO     altering role 'backup'
INFO     creating 'powa' database in 16/main
INFO     creating extension 'btree_gist' in database powa
INFO     creating extension 'pg_qualstats' in database powa
INFO     creating extension 'pg_stat_statements' in database powa
INFO     creating extension 'pg_stat_kcache' in database powa
INFO     creating extension 'powa' in database powa
INFO     configuring Prometheus postgres_exporter 16-main
INFO     configuring pgBackRest stanza 'main' for
         pg1-path=/srv/pgsql/16/main/data
INFO     creating pgBackRest stanza main
INFO     starting Prometheus postgres_exporter 16-main

Nous voyons que, à coté de PostgreSQL, l’instance inclut un ensemblre d’extensions nécessaires à l’utilisation de PoWA, un service de supervision Prometheus postgres_exporter et un service pgBackRest pour la sauvegarde physique. Ces intégrations ne sont pas déclarées au moment de l’exploitation, mais plutôt configurées en avance de phase, localement, via ce que l’on appelle la configuration du site, sous la forme d’un fichier YAML tel que :

# file: /etc/pglift/settings.yaml
prefix: /srv
postgresql:
  auth:
    host: scram-sha-256
prometheus:
  execpath: /usr/bin/prometheus-postgres-exporter
pgbackrest:
  repository:
    mode: path
    path: /srv/pgsql-backups
powa: {}
systemd: {}
rsyslog: {}

En plus des services qui tournent à coté de PostgreSQL (supervision, sauvegarde), pglift gère aussi des intégrations “système” telles que systemd ou rsyslog comme dans notre exemple. Tout ceci fonctionne sans privilège root pour une meilleure séparation des responsabilités et une meilleure sécurité.

Une caractéristique fondamentale de pglift est d’être sans état tout en restant conscient de l’état des objets qu’il gère à l’exécution ; typiquement, cela permet de récupérer l’état d’une instance (à un moment donné) :

$ pglift instance get main -o json
{
  "name": "main",
  "version": "16",
  "port": 5432,
  "settings": {
    "unix_socket_directories": "/run/user/1000/pglift/postgresql",
    "shared_buffers": "1 GB",
    "wal_level": "replica",
    "archive_mode": true,
    "archive_command": "/usr/bin/pgbackrest --config-path=/etc/pgbackrest --stanza=main --pg1-path=/srv/pgsql/16/main/data archive-push %p",
    "effective_cache_size": "4 GB",
    "log_destination": "syslog",
    "logging_collector": true,
    "log_directory": "/var/log/postgresql",
    "log_filename": "16-main-%Y-%m-%d_%H%M%S.log",
    "syslog_ident": "postgresql-16-main",
    "cluster_name": "main",
    "lc_messages": "C",
    "lc_monetary": "C",
    "lc_numeric": "C",
    "lc_time": "C",
    "shared_preload_libraries": "pg_qualstats, pg_stat_statements, pg_stat_kcache"
  },
  "data_checksums": false,
  "locale": "C",
  "encoding": "UTF8",
  "standby": null,
  "state": "started",
  "pending_restart": false,
  "wal_directory": "/srv/pgsql/16/main/wal",
  "prometheus": {
    "port": 9187
  },
  "data_directory": "/srv/pgsql/16/main/data",
  "powa": {},
  "pgbackrest": {
    "stanza": "main"
  }
}

ou de modifier l’instance :

$ pglift pgconf -i main set log_connections=on
INFO     configuring PostgreSQL
INFO     instance 16/main needs reload due to parameter changes: log_connections
INFO     reloading PostgreSQL configuration for 16-main
log_connections: None -> True
$ pglift instance alter main --prometheus-port 8188
INFO     configuring PostgreSQL
INFO     reconfiguring Prometheus postgres_exporter 16-main
INFO     instance 16/main needs reload due to parameter changes: log_connections
INFO     reloading PostgreSQL configuration for 16-main
INFO     starting Prometheus postgres_exporter 16-main
$ pglift instance get main
 name  version  port  data_checksums  locale  encoding  pending_restart  prometheus  pgbackrest
 main  16       5432  False           C       UTF8      False            port: 9187  stanza: main

pglift peut aussi exploiter des objets PostgreSQL : bases de données, rôles, schémas, privilèges, etc.

De plus, les instances et les autres objets PostgreSQL peuvent être manipulés à l’aide des outils natifs de PostgreSQL depuis la ligne de commande pglift qui est composable en cela qu’elle transmet l’environnement de l’instance à la commande invoquée :

$ pglift instance exec main -- pgbench -i bench
creating tables...
generating data (client-side)...
100000 of 100000 tuples (100%) done (elapsed 0.06 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done in 0.18 s (drop tables 0.00 s, create tables 0.01 s, client-side generate 0.08 s, vacuum 0.04 s, primary keys 0.05 s).
$ pglift instance exec main -- pgbench bench
pgbench (16.0 (Debian 16.0-1.pgdg120+1))
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 1
number of threads: 1
maximum number of tries: 1
number of transactions per client: 10
number of transactions actually processed: 10/10
number of failed transactions: 0 (0.000%)
latency average = 1.669 ms
initial connection time = 4.544 ms
tps = 599.125277 (without initial connection time)

Ceci s’applique aussi à des outils tiers, par exemple :

$ pglift instance exec main -- pgbackrest info
stanza: main
    status: ok
    cipher: none

    db (current)
        wal archive min/max (16): 000000010000000000000001/000000010000000000000007

        full backup: 20231016-092726F
            timestamp start/stop: 2023-10-16 09:27:26+02 / 2023-10-16 09:27:31+02
            wal start/stop: 000000010000000000000004 / 000000010000000000000004
            database size: 32.0MB, database backup size: 32.0MB
            repo1: backup set size: 4.2MB, backup size: 4.2MB

        diff backup: 20231016-092726F_20231016-092821D
            timestamp start/stop: 2023-10-16 09:28:21+02 / 2023-10-16 09:28:24+02
            wal start/stop: 000000010000000000000007 / 000000010000000000000007
            database size: 54.5MB, database backup size: 22.6MB
            repo1: backup set size: 6MB, backup size: 1.8MB
            backup reference list: 20231016-092726F

Pour plus de détails, voir le tutoriel de la ligne de commande.

Les modules Ansible

pglift fournit une collection de modules Ansible, sous l’espace de noms dalibo.pglift. Voici un exemple de playbook illustrant ses capacités :

- name: Set up database instances
  hosts: dbserver
  tasks:
    - name: main instance
      dalibo.pglift.instance:
        name: main
        state: started
        port: 5444
        settings:
          max_connections: 100
          shared_buffers: 1GB
          shared_preload_libraries: 'pg_stat_statements, passwordcheck'
        surole_password: '{{ postgresql_surole_password }}'
        pgbackrest:
          stanza: main
          password: '{{ backup_role_password }}'
        prometheus:
          password: '{{ prometheus_role_password }}'
          port: 9186
        roles:
          - name: admin
            login: true
            password: '{{ admin_password }}'
            connection_limit: 10
            validity: '2025-01-01T00:00'
            in_roles:
              - pg_read_all_stats
              - pg_signal_backend
        databases:
          - name: main
            owner: admin
            settings:
              work_mem: 3MB
            extensions:
              - name: unaccent
                schema: public

Nous voyons que le module dalibo.pglift.instance permet de gérer non seulement l’instance, mais aussi les objets reliés comme des rôles ou des bases de données. Les données sensibles (comme les mots de passe) peuvent être pris en charge par une solution de gestion de secrets, telle que Ansible vault. Les modules Ansible permettent un contrôle plus important que la ligne de commandes, au sens où les champs imbriquées ou complexes, tels que les la configuration de l’instance ou des bases de données, les extensions, etc.

Cette interface est complètement déclarative et idempotente, mais reste sans état (comme le sont les modules Ansible en général). Comme pour la ligne de commande, référez-vous au tutoriel Ansible de la documentation pour plus de détails. Notons aussi que ces modules fonctionnent avec d’autres modules Ansible, tels que community.postgresql.

À propos du projet

Sous le capôt, toute la logique métier est implémentée sous la forme d’une API Python. L’idée phare de pglift est de rendre la gestion d’infrastructure PostgreSQL déclarative et sans état afin de l’exploiter selon les principes de l’infrastructure-as-code. Cette conception a permis de développer à la fois une interface impérative en ligne de commandes et une interface déclarative, sous la forme de modules Ansible.

Le projet est nativement open source, mis à disposition sous licence GPLv3. Il est le fruit du travail d’une équipe de développeurs et d’administrateurs poursuivant l’objectif de pérenniser l’expertise de Dalibo dans un outil puissant, souple et accessible pour l’administration quotidienne de PostgreSQL. Son développement se passe en public :

Enfin, une grande attention a été portée à l’écriture d’une documentation exhaustive et accessible, incluant des tutoriels, des guides d’utilisations ou des recettes.


DALIBO

DALIBO est le spécialiste français de PostgreSQL®. Nous proposons du support, de la formation et du conseil depuis 2005.