infra: fait tourner PostgreSQL 17 et TimescaleDB sur Docker #81
No reviewers
Labels
No labels
Compat/Breaking
EC01
EC02
EC03
EC04
EC05
EC06
Kind/BDD
Kind/Back
Kind/Bug
Kind/CICD
Kind/Cloud
Kind/Contenu
Kind/Data
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Front
Kind/IA
Kind/Infra
Kind/Monitoring
Kind/Security
Kind/Testing
Portée/Post-jury
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
ops/alerte
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
g2/enervision!81
Loading…
Reference in a new issue
No description provided.
Delete branch "olivier/80-postgresql-docker"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ce que ça change
PostgreSQL 17 et TimescaleDB sortent des paquets Debian et tournent dans le conteneur
ev-postgres, en réseau hôte, sur le même port 5433. La pile entière est versionnée dansinfra/compose/postgres/: image épinglée, compose, configuration, scripts de sauvegarde. Les rôles et les bases sont mis en conformité avec la cible — quatre rôles, trois bases, chaque rôle sur sa seule base — et l'accès distant est fermé au profit d'un tunnel SSH, conformément à la décision du #65.Closes #80
Preuve
Accès, depuis la boucle locale du serveur — 16 essais, aucun échec :
Fermeture de l'accès distant, éprouvée depuis un poste hors de la machine (
172.26.44.15), en interrogeant le décideurpg_hbapar le protocole PostgreSQL :Reprise du schéma
opsd'enervision_preprod— le seul contenu applicatif migré. Empreinte md5 du contenu sérialisé, avant et après :Sauvegarde et lisibilité :
Restauration à côté des trois bases depuis les vidages d'avant migration : aucune erreur. Inventaires d'objets identiques avant et après. Épreuve de redémarrage passée, conteneur
Up (healthy), données intactes.Relecture
Ce qui suit le code
docs/runbooks/mis à jour — tous les gestes ont changé de forme : plus desystemctl, plus desudo -u postgres, plus de fichier dans/var/log/postgresql.env.example(cinq, en fait : les quatre rôles et le superutilisateur)docs/adr/— à discuter en relecture : le passage à Docker et la fermeture de l'accès distant méritent-ils une fiche ADR, ou le #65 et ce ticket suffisent-ils ?Où regarder en priorité
Trois points où j'ai hésité, ou qui demandent un avis qui n'est pas le mien.
1. Le rôle et la base
keycloakne sont pas repris. C'était demandé, et la base était vide (zéro table, aucun conteneur Keycloak déployé). Maisdocs/EXIGENCES-collectives.mdarbitre au 01/09 « base de Keycloak : schéma dédié dans l'instance PostgreSQL existante », porte les exigences ENF-01 et ENF-02 sur Keycloak, et attribue 3 j.h à Justine et Lénaïc. Je n'ai pas touché au fichier collectif : il n'est pas à moi de le modifier seul. C'est l'écart n°13 dedocs/POSTGRESQL.md. Si Keycloak est confirmé, le rôle et la base se recréent au déploiement — le vidage est conservé dans/var/backups/postgresql/avant-docker-2026-09-02-0808/keycloak.dump.2. Un port publié par Docker échappe entièrement à UFW, et ça vaut pour toute la pile Compose à venir, pas seulement pour la base. Dans la chaîne
FORWARD,DOCKER-USERest consultée en position 1 et les chaînes d'UFW en position 3 ;DOCKER-USERest vide. Une règleufwsur un service en réseau bridge n'a donc aucun effet, tout en affichant le bon masque dansufw status. C'est l'écart n°14, et c'est la raison principale du réseau hôte ici. À trancher avant MinIO, MLflow et la supervision, pas après.3.
max_worker_processesettimescaledb.max_background_workersont été corrigés. Le natif journalisaitTimescaleDB background worker limit of 4 exceededseize fois au 1er septembre. Le lanceur démarre un ordonnanceur par base du cluster, y compris celles sans l'extension : les quatre places étaient prises par les ordonnanceurs et aucun travail de fond ne pouvait s'exécuter. Sans correction, les agrégats continus auraient cessé de se rafraîchir — le tableau de bord aurait continué d'afficher des courbes qui ne bougent plus. Passés à 8 et 16, l'avertissement a disparu et les deux ordonnanceurs attendus tournent. Les valeurs méritent un second avis : elles s'écartent du dimensionnement documenté au 1er septembre.Deux pièges mesurés, notés parce qu'ils reviendront. Un montage de fichier ne suit pas un remplacement par renommage — donc
rsync,mv,sed -iet la plupart des éditeurs laissent le conteneur sur l'ancien inode pendant quepg_reload_conf()annonce un succès. La pile monte le répertoireconf/en entier pour cette raison. Etpg_restore -l /dev/stdinne fonctionne pas à traversdocker exec, le flux d'entrée n'étant pas repositionnable : d'où le scriptverifier-sauvegardes.shplutôt qu'une ligne dans le manuel.Le cluster natif est conservé, arrêté derrière trois verrous (
start.confàdisabled, unité masquée, parapluie désactivé). C'est le retour arrière, et c'est délibéré : on ne supprime pas le filet le jour de la bascule. Sa purge est l'écart n°8, à faire après la démonstration.Ajout :
5af3c30— purge du cluster natif consignée, et audit de la docDeux choses dans ce commit, toutes deux documentaires.
1. La purge du cluster natif est autorisée, et volontairement différée. Le document porte maintenant sa séquence, ses trois conditions de déclenchement et ce qu'elle coûte. Deux points valent une relecture attentive, parce que le réflexe naturel est faux dans les deux cas :
Address already in use— et ce serait inutile : il est gelé depuis la bascule (sonpg_hba.confrefuse tout accès réseau) et les vidages d'avant-docker-2026-09-02-0808/couvrent déjà ses cinq bases, ses rôles et leurs empreintes. Vérifiés lisibles :pg_dropcluster, pas parrm -rf. L'outil Debian emporte/etc/postgresql/17/mainet/var/lib/postgresql/17/maind'un seul geste et refuse d'agir sur un cluster qui tourne. Il faut démasquer l'unité d'abord, sinon il ne peut pas en vérifier l'état — c'est écrit dans la séquence.La purge fermera aussi l'écart n°7 (le
conf.d/conf.d/imbriqué part avec/etc/postgresql/17) et la moitié de l'écart n°2 (l'historiquepsqlpart avec/var/lib/postgresql). Ce qu'elle coûte est écrit aussi, parce que ce n'est pas gratuit : plus aucunpsqlnipg_dumpsur l'hôte, donc en panne de Docker la base sera injoignable et inexaminable ;pg_lsclustersdisparaîtra et le piège correspondant devra être retiré du manuel ; et il n'y aura plus de retour arrière au sens strict. D'où la condition n°3 : une restauration déjà éprouvée depuis un vidage produit par la pile Docker, avant d'y toucher.2. J'ai confronté chaque affirmation chiffrée de
docs/POSTGRESQL.mdà l'état réel du serveur plutôt que de la supposer à jour. Tout concordait — versions, bornes du conteneur, chemins de configuration, dimensionnement, locales, bases, rôles, droits degrafana, contenu du schémaops, droits de la sauvegarde, verrous du natif, absence de règle UFW, échéance du certificat — sauf trois points, corrigés :/etc/enervision, le certificat sous/etc/postgresql/tls. C'est délibéré et c'est maintenant expliqué : deux régimes de droits distincts,conf/lisible par tous et la clé privée en0600pour l'uid 999 seul. Les imbriquer ferait dépendre les droits de la clé de ceux du répertoire de configurationpostgresql-17,postgresql-16et clients »postgresql-commonetpostgresql-client-commonsont aussi installés, et le répertoire de données pèse 99 Mo. Les deux figurent désormais dans l'écart et dans la séquenceLe document ajoute la commande qui donne les six chemins réellement appliqués, pour que la question « où vit la configuration » se lise au lieu de se déduire.
Ce qui n'a pas changé dans cette demande de fusion
Le service tourne exactement comme décrit plus haut :
ev-postgresen réseau hôte, écoute sur127.0.0.1:5433seule, 4 rôles, 3 bases, accès distant par tunnel SSH. Aucune modification sur le serveur dans ce commit — il ne touche quedocs/.Vérifié depuis mon poste : le port 5433 refuse la connexion.
listen_addressesest sur la boucle locale,pg_hban'autorise plus que 127.0.0.1 paire par paire, ethost all postgres all rejecten tête ferme le superutilisateur au réseau. Le #65 est réglé par cette demande.Un point de coordination, et il n'est pas de ton fait. Ton README place la pile dans
/opt/enervision/postgres/, et c'est bien là qu'elle tourne. Or le rôleappd'Ansible, dans la #61 de Gabriel, clone le dépôt dans/opt/enervisionet lance les composes depuis/opt/enervision/infra/compose. Les deux vont se percuter : soit le clone écrase ton dossier, soit la même pile existe à deux endroits.À trancher entre vous avant que le rôle
appsoit implémenté. Le plus simple est que la pile ne vive qu'à un seul endroit, celui du dépôt cloné, et que le README pointe dessus.Sur l'écart n°13, tu as raison et la correction est à moi. Le document collectif annonce toujours Keycloak comme arbitré le 31 août, alors que la décision réelle est un jeton émis par notre API, Keycloak seulement si le temps le permet. Ce n'est pas ta demande qui contredit la référence, c'est la référence qui n'a pas été mise à jour. Je m'en occupe.