Exploitation (jour 2)

Vaks PM · Exploitation jour 2 · juin 2026

Objet de ce guide. Ce document décrit comment faire fonctionner une instance Vaks PM après son installation et sa remise en service : les tâches récurrentes de son exploitation en production. Cela couvre la sauvegarde et la restauration, le déploiement de nouvelles versions sans interruption, la vérification de son bon état, l'ajout d'une organisation et la collecte des bonnes données lorsqu'un support est nécessaire. Le document s'adresse à une personne administratrice système qui découvre le produit et ne suppose aucun contexte préalable. L'installation initiale, ponctuelle, est traitée à part, dans Déploiement Docker Swarm et Déploiement Kubernetes.

Vue d'ensemble

Vaks PM est une application web de gestion de projet, multi-utilisateurs et auto-hébergée. Une fois en service, la responsabilité quotidienne de son exploitation se ramène à un petit nombre d'activités récurrentes, chacune traitée par une section de ce guide :

L'architecture compte pour chacune de ces activités. Les services applicatifs, api, web et worker, sont sans état : ils ne détiennent aucune donnée durable et peuvent être démarrés, arrêtés et répliqués librement. Tout l'état durable réside dans trois magasins sous-jacents : PostgreSQL (la base de données relationnelle), Redis (cache et file de jobs) et un stockage objet compatible S3 (Simple Storage Service, les fichiers téléversés). L'exploitation se divise donc nettement entre préoccupations sans état, comme les mises à jour, la mise à l'échelle et la santé, et préoccupations avec état, comme la sauvegarde et la restauration. Voir Architecture pour le tableau complet.

Glossaire

Sigles utilisés dans ce guide, définis une fois ici pour référence.

TermeSignification
RPORecovery Point Objective (objectif de point de reprise) : la quantité maximale de perte de données qu'une organisation est prête à tolérer après un incident, exprimée comme une durée (par exemple « au plus 15 minutes de travail »). Un RPO plus petit signifie des sauvegardes plus fréquentes.
RTORecovery Time Objective (objectif de temps de reprise) : la durée cible d'une restauration, c'est-à-dire le temps qu'il peut falloir pour remettre le service en route après un incident. Le RPO porte sur combien on perd ; le RTO porte sur combien de temps dure la reprise.
PITRPoint-In-Time Recovery (restauration à un instant précis) : restaurer la base de données à un moment choisi (par exemple la seconde précédant une commande malheureuse), plutôt qu'au moment de la dernière sauvegarde complète.
WALWrite-Ahead Log (journal des écritures anticipées) : le journal de PostgreSQL, dans lequel chaque changement est consigné avant que les tables ne soient touchées. L'archivage continu du WAL est ce qui rend la PITR possible.
S3Simple Storage Service : une interface de stockage objet, d'origine Amazon, devenue un standard de fait de l'industrie. Vaks PM stocke les fichiers téléversés dans un magasin compatible S3 qu'il héberge lui-même.
SPASingle-Page Application (application monopage) : le front-end navigateur (le service web), un ensemble de ressources statiques qui fait tourner l'interface utilisateur dans le navigateur et dialogue avec l'API.
JWTJSON Web Token : un jeton de session signé émis après la connexion ; il porte l'identité de l'utilisateur et du tenant pour que l'API puisse autoriser chaque requête.
Autres abréviations rencontrées au passage : SSH (Secure Shell, un protocole d'administration distante chiffré), HA (High Availability, haute disponibilité, une topologie qui survit à la perte d'un seul hôte), DB (base de données), DR (disaster recovery, reprise après sinistre), et KEK/DEK (les clés de chiffrement de clé / de chiffrement de données décrites sous Sauvegardes chiffrées).

Paliers de sauvegarde

Vaks PM n'impose pas une politique de sauvegarde unique. Il propose un ensemble de paliers, chacun acceptant une quantité différente de perte de données (un RPO différent) à un coût de stockage différent. Une organisation choisit le palier qui correspond à la perte de données qu'elle peut tolérer. Chaque palier repose uniquement sur des outils livrés avec PostgreSQL, donc aucun logiciel de sauvegarde tiers n'est requis.

Le palier base de données est, en production, répliqué sur plusieurs hôtes pour la disponibilité. La réplication n'est pas une sauvegarde : un DELETE erroné, un changement corrupteur ou un rançongiciel se propage à toutes les répliques en quelques millisecondes, donc trois copies saines deviennent trois copies du dommage. Ce sont les vraies sauvegardes, conservées dans le temps avec au moins une copie hors du cluster, qui protègent contre les erreurs logiques. Les paliers ci-dessous fournissent exactement cela.

Les trois paliers sont cumulatifs, chacun s'appuyant sur le précédent. La plupart des organisations démarrent au palier 1 et ne montent que si perdre une journée de travail est inacceptable.

PalierMécanismeRPO (perte de données max.)Coût / complexité
Palier 1 Vidage logique Un instantané SQL compressé (pg_dump) pris chaque nuit et expédié hors cluster. ~24 heures (depuis le dernier vidage nocturne). Faible. Un seul fichier autonome par jour ; rétention triviale ; le point de départ recommandé.
Palier 2 PITR via archivage WAL Une sauvegarde de base complète quotidienne (pg_basebackup) plus l'archivage continu du flux WAL. ~15 minutes, ajustable (fixé par archive_timeout ; une valeur plus petite abaisse le RPO). Moyen. Restaure à un instant précis. ~25 Go pour une base de 10 Go sur 7 jours.
Palier 2b Incrémentiel (PostgreSQL 17) Une sauvegarde de base complète hebdomadaire plus des sauvegardes de base incrémentielles quotidiennes (une fonctionnalité native de PostgreSQL 17), toujours avec WAL continu. ~15 minutes (comme le palier 2). Moyen+. Même précision de reprise que le palier 2 pour environ un tiers du stockage : à peu près 10 à 12 Go pour la même fenêtre de 7 jours.
Plus le RPO est bas, plus on capture et plus on consomme de stockage. Le palier 1 est le plus simple et suffit à la plupart des sites. Le palier 2 ajoute la précision à un instant donné. Le palier 2b offre la précision du palier 2 tout en maîtrisant la facture de stockage à grande échelle, ce qui en fait le choix séduisant pour une instance de 200 utilisateurs, où le coût est dominé par les copies complètes de la base plutôt que par le WAL. Changer de palier est une modification de configuration, pas une modification de code.
L'archivage WAL doit être surveillé. Sous palier 2 / 2b, si la destination d'archivage se remplit ou devient injoignable, PostgreSQL refuse de recycler le WAL et le disque du primaire finit par saturer. Surveiller l'espace libre du répertoire d'archivage et les compteurs d'échec dans la vue pg_stat_archiver de PostgreSQL. Les procédures palier par palier et la planification sont décrites dans les sections ci-dessous.

Dimensionnement

Les chiffres ci-dessous modélisent une instance pour environ 200 utilisateurs (la cible de référence du produit), en supposant à peu près 72 000 écritures en base par jour et une base d'environ 10 Go. Les fichiers téléversés résident dans le stockage objet et ne gonflent ni la base ni le WAL ; ils sont dimensionnés à part (voir Stockage objet).

ÉlémentBrutCompresséNote
Une sauvegarde de base complète~10 Go~3 GoSuit la taille de la base.
7 bases complètes (palier 2)~70 Go~21 GoLe coût dominant à cette échelle.
WAL par jour~2 Go~0,5 à 0,7 GoLes segments forcés, presque vides, se compressent fortement.
WAL sur 7 jours~14 Go~3,5 à 5 GoPeu coûteux par rapport aux bases complètes.
Total palier 2 (7 jours)s.o.~25 GoPour une base de 10 Go.
Total palier 2b (7 jours)s.o.~10 à 12 GoBase complète hebdomadaire + incréments quotidiens.
Règle empirique. Palier 1 : jours × base_compressée. Palier 2 : jours × (base_compressée + ~0,6 Go WAL/jour). Palier 2b : 1 complète + jours × (incrément + ~0,6 Go). Parce que le WAL est peu coûteux et que les bases complètes sont lourdes, le palier 2b est nettement plus économique à l'échelle de 200 utilisateurs. Toujours provisionner la destination hors cluster avec une marge confortable.

Stockage objet

Les fichiers téléversés, y compris les pièces jointes des tâches, le branding de l'organisation, les modèles de documents, les documents de cadrage de projet et les archives d'audit compressées, sont stockés dans le stockage objet compatible S3, hors de PostgreSQL. La base ne contient que des références vers ces fichiers. La conséquence est directe : une restauration limitée à la base perd tous les fichiers téléversés. Le stockage objet doit être sauvegardé comme une préoccupation à part entière.

Deux approches équivalentes conviennent pour sauvegarder le stockage objet :

L'application utilise un petit ensemble fixe de buckets, qui doivent tous être inclus dans la sauvegarde : pièces jointes, branding, modèles de documents, blobs de cadrage de projet et archive d'audit froide. Conserver la sauvegarde du stockage objet sur la même planification et la même rétention que la sauvegarde de la base, afin qu'une restauration rétablisse une paire cohérente : les lignes de la base et les fichiers qu'elles référencent.

Une restauration complète après sinistre a aussi besoin de la configuration de déploiement, des certificats TLS et du matériel de clés de chiffrement, dont aucun ne réside dans la base ni dans le stockage objet. La liste complète « quoi sauvegarder en plus » est donnée dans la section Restauration.

Sauvegardes chiffrées

Par défaut, les artefacts de sauvegarde quittent l'hôte en clair. Pour les environnements réglementés, où le chiffrement est requis à la fois au repos et en transit, chaque artefact (le vidage logique, chaque sauvegarde de base et chaque segment WAL) peut être chiffré à la création, avant même d'être expédié hors de l'hôte. Le mécanisme est age, un outil moderne de chiffrement de fichiers, employé de façon asymétrique : l'hôte ne détient que la clé publique (le « destinataire »), de sorte qu'il n'y a rien à voler sur l'hôte, tandis que la clé privée correspondante nécessaire au déchiffrement est conservée en séquestre hors cluster. Chaque artefact chiffré gagne un suffixe .age, et les procédures de restauration déchiffrent avec la clé privée séquestrée comme première étape.

La garde des clés équivaut à la capacité de restauration. Une sauvegarde chiffrée n'est restaurable que dans la mesure où la clé qui la déverrouille l'est. Deux clés distinctes doivent être préservées, toutes deux hors des sauvegardes qu'elles protègent et avec une rétention au moins aussi longue que les sauvegardes elles-mêmes :
  • La clé privée age, qui déchiffre les artefacts de sauvegarde.
  • La KEK (Key Encryption Key, clé de chiffrement de clé) de l'application. Vaks PM chiffre les champs sensibles au repos avec une DEK (Data Encryption Key, clé de chiffrement de données) par tenant, elle-même enveloppée par la KEK. Un vidage de base ne contient que les clés enveloppées plus du texte chiffré, donc sans la KEK une instance restaurée fonctionne mais ses secrets chiffrés (secrets multifacteurs, mot de passe SMTP, secrets d'authentification unique et de connecteurs) sont définitivement illisibles.
Ne jamais retirer une KEK tant qu'une sauvegarde conservée peut encore la référencer. Le modèle complet des clés et la politique de gestion des clés sont décrits dans Sécurité : sauvegardes et garde des clés.

Restauration

La procédure de restauration dépend du palier auquel la sauvegarde a été prise. Dans tous les cas, si les artefacts étaient chiffrés (un suffixe .age), les déchiffrer d'abord avec la clé privée séquestrée.

PalierComment se déroule une restauration
Palier 1 Vidage logique Vérifier la somme de contrôle du vidage, puis le ré-importer avec pg_restore, dans une base isolée neuve pour un test, ou par-dessus la base en service pour une vraie reprise. Des tables individuelles peuvent être restaurées sélectivement. La base restaurée revient à l'état du dernier vidage nocturne.
Palier 2 PITR Déployer la dernière sauvegarde de base sur la cible, puis configurer PostgreSQL pour rejouer le WAL archivé en avant jusqu'à un instant choisi (par exemple la seconde précédant une commande malheureuse) et s'arrêter là. Une restauration PITR reconstruit le cluster de base de données. Dans une topologie HA, elle s'effectue avec le gestionnaire de cluster arrêté, puis les répliques sont ré-amorcées ensuite.
Palier 2b Incrémentiel Recombiner d'abord la base complète hebdomadaire avec les incréments quotidiens en une seule copie complète (pg_combinebackup), puis suivre le même rejeu WAL à un instant donné que pour le palier 2.
Une sauvegarde non testée n'est pas une sauvegarde. Planifier un exercice de restauration périodique : restaurer la dernière sauvegarde dans une base ou une VM jetable et confirmer un nombre de lignes attendu et qu'un secret chiffré au niveau du champ se déchiffre. Un simple nombre de lignes passe même quand la KEK manque ; seul un déchiffrement réussi prouve que la clé est présente sur le cluster restauré. Noter le temps que prend la restauration, car ce chiffre est le RTO réel. Les commandes exactes de restauration, la liste de contrôle de reprise après sinistre et la procédure d'exercice sont données dans la section Restauration.

Mises à jour progressives

Les nouvelles versions d'image sont déployées sans interruption. Parce que les services api, web et worker sont sans état et tournent en plusieurs répliques, l'orchestrateur les remplace une (ou quelques-unes) à la fois pendant que les répliques restantes continuent de servir le trafic, de sorte que les clients ne voient aucune interruption.

PlateformeComment le déploiement est effectué
Docker SwarmUne mise à jour de service progressive demande à Swarm de remplacer les tâches en cours d'un service par la nouvelle image, en respectant le parallélisme et le délai de mise à jour configurés. Les répliques sont renouvelées graduellement ; si une nouvelle tâche échoue à son contrôle de santé, le déploiement peut être suspendu ou annulé.
KubernetesUn helm upgrade applique la nouvelle image ; la stratégie de mise à jour progressive du Deployment fait monter de nouveaux pods et ne retire les anciens qu'une fois les nouveaux pods déclarés prêts.

Les changements de schéma de la base sont appliqués automatiquement au démarrage de l'API. Quand une nouvelle version nécessite un changement de schéma, l'api réconcilie le schéma de la base au moment de son amorçage, donc il n'y a pas de commande de migration manuelle séparée à lancer pour une mise à niveau de routine. Combiné au déploiement sans état, cela fait d'une mise à niveau de version une action unique sur l'une ou l'autre plateforme.

Vérifier un déploiement de la même façon que l'installation a été vérifiée : confirmer que les endpoints de santé renvoient un succès (voir Contrôles de santé) et que la page de connexion se charge et qu'un compte peut s'authentifier. Dans les déploiements multi-tenants (pooled) où chaque organisation a sa propre base, la réconciliation de schéma est appliquée à chaque base de tenant. Voir Ajouter une organisation et les guides de déploiement pour la procédure par tenant.

Contrôles de santé

Le service api expose deux endpoints HTTP de santé. Les contrôles de santé de l'orchestrateur les appellent, et un système de supervision externe peut aussi les interroger. Tous deux doivent renvoyer une réponse de succès sur une instance saine.

EndpointIndiqueSert à
/health/live livenessLe processus est vivant et capable de servir des requêtes, c'est-à-dire qu'il n'est ni figé ni en interblocage.L'orchestrateur redémarre une réplique dont la sonde de vivacité (liveness) échoue.
/health/ready readinessLa réplique est prête à accepter du trafic : ses dépendances (telles que la base de données) sont joignables.L'orchestrateur retient le trafic d'une réplique dont la sonde de disponibilité (readiness) échoue (par exemple au démarrage), et n'envoie de requêtes qu'aux répliques prêtes pendant une mise à jour progressive.

La distinction compte pendant un déploiement : une réplique fraîchement démarrée peut être vivante mais pas encore prête. Ne router le trafic que vers les répliques prêtes est ce qui empêche la mise à jour progressive de perdre des requêtes. Si une réplique est redémarrée de façon répétée, une sonde de vivacité en échec est le premier signal ; si le trafic ne parvient pas aux nouvelles répliques après une mise à jour, vérifier la sonde de disponibilité et la dépendance sur laquelle elle se prononce.

Ajouter une organisation

Vaks PM peut fonctionner selon deux modes de tenancy. En mode dédié, l'instance sert une seule organisation, le cas on-premise typique. En mode pooled (mutualisé), une instance sert plusieurs organisations, chacune isolée dans sa propre base et atteinte sous son propre nom d'hôte.

Ajouter une organisation en mode pooled est une opération additive et isolée : elle provisionne une nouvelle base pour le tenant et route un nouveau nom d'hôte vers elle, sans perturber les tenants existants. Il n'y a aucune interruption pour les organisations déjà présentes sur l'instance, et leurs données ne sont jamais touchées. En résumé, provisionner un tenant implique de :

Parce que chaque tenant a sa propre base, une mise à niveau qui change le schéma réconcilie toutes les bases de tenants, pas une seule. Garder cela à l'esprit en planifiant une mise à niveau sur une instance pooled chargée. Les commandes de provisionnement faisant autorité, spécifiques à chaque plateforme, se trouvent dans Déploiement Docker Swarm et Déploiement Kubernetes.

Diagnostics et journaux

Quand un point demande investigation, les données de support sont collectées à deux niveaux, reflétant une frontière de sécurité délibérée : l'application tourne comme un conteneur durci et sans état qui écrit ses journaux sur la sortie standard uniquement, n'a aucun accès au démon Docker et est cloisonnée des hôtes. De ce fait, l'application ne peut pas lire les journaux d'infrastructure (ceux du reverse proxy, du cluster de base de données, du cache ou du stockage objet) ; ceux-ci vivent sur les hôtes. Les deux niveaux sont complémentaires.

Niveau 1 : le paquet de diagnostics intégré à l'application

Une personne administratrice d'organisation peut télécharger un paquet de diagnostics en un clic depuis l'espace d'administration (Admin → Sécurité et conformité → Support et diagnostics → Télécharger le paquet). Il est produit par un endpoint réservé aux administrateurs et renvoie un fichier JSON expurgé qui couvre les problèmes au niveau applicatif :

Aucun secret ne quitte l'application. Mots de passe, clés d'API, identifiants SMTP et clés de chiffrement/signature sont masqués ou omis, en réutilisant l'expurgation du journal d'audit. Le fichier porte tout de même des libellés instantanés (noms et e-mails de qui a fait quoi), donc le traiter comme confidentiel, bien qu'il ne contienne aucun identifiant.
Le tampon d'erreurs en mémoire est par réplique d'API, et l'instance en fait tourner plusieurs. Le paquet est un excellent premier signal, mais pour une trace complète, ajouter les journaux d'hôte ci-dessous : la commande de journaux au niveau du service couvre toutes les répliques.

Niveau 2 : journaux d'hôte

Les problèmes d'infrastructure exigent des journaux rassemblés sur les hôtes par SSH par une personne opératrice. Sur Docker Swarm, ils se lisent avec des commandes de journaux au niveau du service sur le nœud manager, cadrées à la fenêtre temporelle de l'incident ; sur Kubernetes, l'équivalent est la lecture des journaux de pods. Faire correspondre la source de journaux au symptôme :

SymptômePaquet niveau 1Journaux d'hôte à ajouter
Fonctionnalité cassée, erreurs serveur, données erronéesSignal principalJournaux des services api (et worker)
Échecs de connexion / authentification unique / MFAOui (audit + config)Journaux du service api
Erreurs de passerelle, erreurs TLS / certificatNon couvertJournaux du reverse proxy (Traefik)
Site indisponible, base injoignable, basculeOui (sonde DB)État et journaux du cluster de base de données (Patroni / etcd / HAProxy)
E-mails / webhooks non envoyésOui (profondeurs de files)Journaux du worker et de Redis
Connecteur de ticketing externe défaillant (ServiceNow, Jira…) : le test échoue, ou la recherche de ticket ne renvoie rien dans la timesheetPartiel (réglages effectifs)Journaux du service api — filtrer sur ticketing / servicenow. Le bouton Tester du connecteur affiche aussi l'erreur en direct (401 identifiants invalides, 403 droits Table API insuffisants, délai dépassé, hôte injoignable).
Échecs de téléversement / téléchargement des pièces jointesOui (sonde S3)Journaux du stockage objet (Garage / MinIO)
Lenteur diffuse / défaillances aléatoiresOui (mémoire, durée de fonctionnement)Ressources des hôtes (disque, mémoire) et état des tâches du cluster

Pour ouvrir une demande de support, télécharger le paquet de niveau 1. Si le problème est lié à l'infrastructure, collecter les journaux d'hôte de niveau 2 correspondants. Noter l'heure approximative de l'incident (avec le fuseau horaire) et ce qui était en cours, puis tout joindre. L'ensemble complet des commandes d'hôte, avec des exemples par service, se trouve dans le guide de support dédié référencé depuis Sécurité.


Voir aussi : Le produit · Architecture · Déploiement Docker Swarm · Déploiement Kubernetes · Sécurité · Démo · Accueil de la documentation