docs : les deux manuels disent quoi faire quand ça échoue (#44) #190
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!190
Loading…
Reference in a new issue
No description provided.
Delete branch "lenaic/44-manuels-echec"
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?
Ferme la première partie du #44. Gabarit repris de
mlflow.md§8-§9, comme demandé.reprise.md: une section d'échec, elle n'en avait aucuneLes trois frictions de l'exercice du 02/09 remontent du tableau de constat vers une procédure :
pg_restoresansshared_preload_libraries=timescaledb,forgejo.dbrejoué par-dessus le vidage, l'app.iniqui écoute sur127.0.0.1.Plus quatre cas rencontrés depuis : coffre qui refuse, vidage illisible, migrations plus récentes que le vidage, pile
apisautée faute de clé de signature.deploiement.md: huit symptômesLes quatre demandés, coffre, UFW qui coupe SSH, crontab qui garde une tâche retirée du dépôt, retour arrière du front. Plus le cas le plus traître,
failed=0mais rien de neuf sur le serveur, qui est arrivé deux fois cette semaine et qu'on a mis vingt minutes à comprendre chaque fois.Le retour arrière du front est écrit pour de vrai :
app.ancienexiste, une génération de profondeur, et Caddy sert le répertoire donc il n'y a rien à recharger.Un défaut trouvé en écrivant, et c'est la raison d'être de l'exercice
restore.ymlprend un « filet » avant d'écraser, en appelantpg-backup.sh. Ce script nomme ses fichiers<base>-<date du jour>.dump, dans le même répertoire.Restaurer la sauvegarde du jour faisait donc écraser la source par le filet, juste avant de la lire. La reprise repartait de l'état cassé, et le dispositif censé protéger détruisait ce qu'il protégeait. Personne ne l'aurait vu avant d'en avoir besoin.
Le correctif tient en deux lignes :
pg-backup.shacceptePG_BACKUP_DEST, etrestore.ymlécrit son filet dansbackup_dir/filet/.Pour demain matin
Marvin rejoue
reprise.md. Je me tais pendant. Chaque question qu'il me pose est un défaut du manuel : je la note, je ne réponds pas, et je corrige après. C'est le critère central du ticket, et y répondre le perdrait.ansible-lint profil production, yamllint propre, trois playbooks valides, shellcheck propre, 199 liens markdown vérifiés.
Relu, et tout vérifié sur
ml-stagiaire-02avant de poster — les commandes des deux manuels ont été rejouées, pas seulement lues.Le correctif du filet est bon et bien trouvé : simulé avec le script de cette branche,
PG_BACKUP_DEST+mkdir -pfont exactement ce qui est annoncé, et le vidage du jour à la racine reste intact.Trois blocages en commentaires de ligne : la commande ➀ de
reprise.md(impossible à exécuter, trois raisons distinctes), le retour arrière du filet (Permission denied), et l'alerte #42 faussée par le filet. Deux points de plus ici.Le même bug reste ouvert sur le chemin « machine neuve »
Hors diff, mais c'est la classe de bug que cette PR ferme, et elle est dans le périmètre de
reprise.md.Le rôle
backupfinit par « Premier vidage, à la main comme le fait cron », gardé parcreates: {{ backup_dir }}/.dernier-etat— un fichier caché (confirmé sur le serveur). En reprise sur machine neuve, la doc dit que{{ backup_dir }}a été « copié à la main » : si on recopie les*.dumpsans le point-fichier,site.ymlvide les bases neuves par-dessus le vidage du jour, à la racine debackup_dir.Et rien ne l'attrape ensuite :
verifier-sauvegardes.shle déclare « lisible », le contrôle d'entrée derestore.ymlvoit le fichier présent, et la restauration ne restaure rien. La phrase « si vous voyez un filet à la racine de/var/backups/postgresql/, c'est une machine qui n'a pas le correctif » ne couvre pas ce cas-là.Hors PR, mais en cours en ce moment : l'alerte sauvegarde est aveugle
Les
.promdatent du vidage de 07:53 et sont en0640 root:root;pg-backup.shn'a reçu lechmod 0644du #172 qu'au déploiement de 09:40. Ça se répare tout seul au vidage de 02:30 — donc pas avant le jury. Pour les rendre visibles tout de suite :sudo chmod 0644 /var/lib/node_exporter/textfile/ev_ops_sauvegarde_pg*.prom.Ce qui tient
Le retour arrière du front est juste, y compris sur le point qui aurait pu piéger :
g2-forge-proxymonte le parent (/opt/g2-forge/www -> /srv/www), donc lemvest bien vu par Caddy et il n'y a effectivement rien à recharger.appetapp.ancienexistent tous les deux. Les commandesgit logetcrontab -l -u deploydedeploiement.mdrépondent correctement.@ -48,0 +63,4 @@```bash# ➀ La restauration avec l'extension chargée, cas rencontré le 02/09sudo docker exec -e PGOPTIONS="-c shared_preload_libraries=timescaledb" \Cette commande ne peut pas s'exécuter. Trois échecs, tous reproduits sur
ml-stagiaire-02:1.
shared_preload_librariesest un paramètrePOSTMASTER. Il ne se change pas par session :PGOPTIONSfait refuser la connexion.Le geste correct pour restaurer une base TimescaleDB est
SELECT timescaledb_pre_restore();avant,timescaledb_post_restore();après.2. Le conteneur ne voit pas
/var/backups.Le chemin passé à
pg_restoreest un chemin hôte, exécuté dans le conteneur →could not open input file. C'est exactement la raison d'être du détour deverifier-sauvegardes.sh(son commentaire n°1).3. Ni
-u postgresniPGPORT=5433.Le second est le piège que
pg-backup.shdocumente lui-même comme « celui qui fait perdre le plus de temps sur cette base ».C'est le remède de la panne n°1 du tableau, celle déjà rencontrée le 02/09 : quelqu'un qui la suit en reprise réelle enchaîne trois erreurs. La ligne 56 du tableau porte le même conseil et tombe donc aussi.
@ -48,0 +92,4 @@sudo docker exec -i -e PGPORT=5433 -u postgres ev-postgres \pg_restore -U postgres -d enervision_prod --clean --if-exists \--no-owner --no-privileges --exit-on-error \< /var/backups/postgresql/filet/enervision_prod-<AAAA-MM-JJ>.dumpCes deux lignes échouent en
Permission denied, et c'est le seul chemin de retour arrière du manuel. Reproduit en tant quedeploysurml-stagiaire-02:Le répertoire est
drwxr-x--- root root(rôlebackup,mode: "0750") et les vidages sont en0640 root:root(umask 027 du script). La redirection<est ouverte par le shell appelant, pas parsudo: lepg_restoreéchoue avant même de démarrer.restore.ymls'en sort parce qu'il redirige sousbecome: true; ici non.Il faut passer la redirection à root, par exemple :
@ -77,2 +83,4 @@ansible.builtin.command:cmd: /usr/local/bin/pg-backup.shenvironment:PG_BACKUP_DEST: "{{ backup_dir }}/filet"Il manque
PG_BACKUP_TEXTFILE_DIRici, et ça fausse l'alerte #42.pg-backup.shappellepublier_metriquedans tous les cas, et cette fonction n'est pas pilotée parPG_BACKUP_DEST: elle écrit dansPG_BACKUP_TEXTFILE_DIR, resté à sa valeur de production. Reproduit avec le script de la branche (répertoire textfile détourné vers/tmppour ne pas polluer la prod) :Sans la surcharge, ces lignes partent dans
/var/lib/node_exporter/textfile(drwxrwxr-x, le script tourne en root, donc il écrit dedans). Conséquences :/var/backups/postgresqlest très souvent la raison même de la restauration ;Correctif, une ligne dans ce même bloc :
publier_metriqueet la purge des.prom.$$sortent proprement quand le répertoire est absent. Le.dernier-etat, lui, suit bien$DEST— le contrôle du matin n'est pas touché.(Vérifié au passage : le correctif du filet lui-même fonctionne. Simulé avec la version de cette branche,
mkdir -pcrée le répertoire, les trois vidages +globals.sql.gzy atterrissent, et le vidage du jour à la racine n'est pas touché.)Correctifs poussés sur la branche :
6453f5d. Les quatre points sont traités, et chaque commande réécrite a été rejouée surml-stagiaire-02avant d'être commitée.➀ La restauration TimescaleDB
En cherchant le bon geste, la cause supposée s'est révélée fausse : l'extension est déjà chargée au niveau du serveur.
Ce qui manquait le 02/09 n'était donc pas le chargement, mais le mode « restoring » :
timescaledb_pre_restore()avant,timescaledb_post_restore()après. Les deux fonctions existent bien en 2.29.2, et la séquence a été jouée de bout en bout à travers l'exactdocker execdu manuel, sur une base d'essai jetable créée puis supprimée — jamais surenervision_prod.Le
post_restore()est signalé à jouer même si lepg_restorea échoué : une base laissée en mode restoring a ses déclencheurs TimescaleDB désarmés, elle accepte les écritures sans les ranger. C'est le genre d'état qu'on ne remarque qu'une semaine plus tard.➁ Le retour arrière, et le
lsRedirection passée dans un
sh -c,sudoajouté auls. Vérifié en tant quedeploy:➂
PG_BACKUP_TEXTFILE_DIR: /nonexistentdans le filetUne ligne, avec le pourquoi en commentaire au-dessus.
➃ Le premier vidage du rôle
backupcreates:seul ne suffisait pas —.dernier-etatest un point-fichier. J'ai ajouté unfindsur*.dumpet unwhen: matched == 0. Sur la machine actuelle : 27 vidages à la racine, donc la tâche est sautée, aucune régression ; sur une machine réellement vierge elle joue comme avant.ansible-playbook --syntax-checkpasse surrestore.ymletsite.yml. Je n'ai pas pu faire tourner de--checkréel, il me manque le mot de passe du coffre — c'est le pipeline qui tranchera pouransible-lint/yamllint.Un point que je n'ai PAS corrigé, et qui mérite ton avis
restore.ymlrestaureenervision_prodavec unpg_restorenu, sanstimescaledb_pre_restore(). C'est exactement ce qui a fait échouer la restauration à la main du 02/09. Si le diagnostic ci-dessus est le bon, le playbook porte le même défaut, sur le chemin qui compte le plus.Je ne l'ai pas touché parce que ça ne se corrige pas à l'aveugle :
mlflown'a pas l'extension, donc l'appel doit être conditionnel par base, et je n'ai aucun moyen de tester une vraie restauration aujourd'hui. Ça vaut un ticket à part plutôt qu'un correctif non testé la veille du jury.Hors PR, et toujours en cours
node_textfile_scrape_error 1: les.promde sauvegarde datent du vidage de 07:53 et sont en0640 root:root,pg-backup.shn'ayant reçu lechmod 0644du #172 qu'au déploiement de 09:40. Aucune métriqueev_ops_sauvegarde_pg_*n'est exposée en ce moment. Ça se répare seul au vidage de 02:30, donc pas avant le jury —sudo chmod 0644 /var/lib/node_exporter/textfile/ev_ops_sauvegarde_pg*.promsi tu veux les voir tout de suite.