site-deployer-tout : l orchestration existait, rien ne la lancait
playbooks/site.yml ordonne les couches pour n importe quelle instance. Mais deployer-tout ne vise que l inventaire d un locataire, et le site n avait que site-appliquer GROUPE=<un seul>. Un hebergeur qu on ne peut remonter qu en enchainant onze groupes de memoire n est pas reconstructible : il est reparable par quelqu un qui se souvient. Et quatre gardes que --check rendait folles, toutes de la meme famille : une garde qui compare contre ce qu une tache du meme play vient de produire n a rien a dire tant que rien n a ete ecrit. Sept machines en echec sur un site sain, en suivant le conseil du Makefile lui-meme. Apres correction : 7/7, 0 echec, de 174 a 309 taches par machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
This commit is contained in:
parent
52b9d31a5d
commit
8eb482e0c6
6 changed files with 133 additions and 1 deletions
38
CHANGELOG.md
38
CHANGELOG.md
|
|
@ -1,5 +1,43 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-09-14 (6) — Le site avait l'orchestration, pas le moyen de la lancer
|
||||
|
||||
`playbooks/site.yml` est genere par `orchestrer.py` et ordonne les couches pour
|
||||
**n'importe quelle** instance — son en-tete le dit. Mais `deployer-tout` ne vise que
|
||||
l'inventaire d'un LOCATAIRE, et le site n'avait que `site-appliquer GROUPE=<un seul>`.
|
||||
|
||||
Le site ne se deployait donc que **groupe par groupe, a la main**, dans un ordre qu'il
|
||||
fallait se rappeler. Un hebergeur qu'on ne peut remonter qu'en enchainant onze groupes de
|
||||
memoire n'est pas reconstructible : il est reparable par quelqu'un qui se souvient. C'est
|
||||
nommement l'une des trois limites du jalon de reconstruction autonome — *« le SITE jamais
|
||||
reconstruit »*.
|
||||
|
||||
`site-deployer-tout` comble le manque. Trois differences avec son equivalent locataire,
|
||||
aucune cosmetique : l'inventaire est un **script** (un site se derive de son underlay, il
|
||||
ne se fige pas dans un `hosts.yml`), la voute vit **a cote de la carte**
|
||||
(`underlay.vault.yml`, hors depot), et le perimetre reste `hotes_actifs` — les
|
||||
hyperviseurs et la frontiere sont dans l'inventaire mais ne se deploient pas.
|
||||
|
||||
### Quatre gardes que `--check` rendait folles
|
||||
|
||||
Le Makefile CONSEILLE l'essai a blanc — *« tester d'abord en idempotent »*. Suivre ce
|
||||
conseil rendait **sept machines en echec** sur un site parfaitement sain. Quatre causes,
|
||||
une seule famille : **une garde qui compare contre ce qu'une tache du meme play vient de
|
||||
produire n'a rien a dire tant que rien n'a ete ecrit.**
|
||||
|
||||
| role | ce que `--check` cassait | remede |
|
||||
|---|---|---|
|
||||
| `hosts_statiques` | la lecture des deux fichiers etait sautee : `ne portent pas le meme nombre d'entrees ()` | `check_mode: false` sur la lecture |
|
||||
| `hosts_statiques` | l'assertion comparait l'AVANT a l'APRES : `/etc/hosts=13 \| tmpl=2` | `not ansible_check_mode` sur l'assertion |
|
||||
| `serveur_icinga` | le telechargement simule, l'installation cherchait un fichier absent | `check_mode: false` sur `get_url` |
|
||||
| `serveur_ops` | la version du controleur non lue : `Le controleur tourne Python ` | `check_mode: false` sur la lecture |
|
||||
|
||||
**Les parentheses vides et l'espace apres « Python » sont tout le diagnostic** : il n'y
|
||||
avait rien a comparer. Un essai a blanc qui ment est pire qu'aucun — il apprend a ne plus
|
||||
le lancer.
|
||||
|
||||
Apres correction : **7/7, 0 echec**, de 174 a 309 taches par machine.
|
||||
|
||||
## 2026-09-14 (5) — Le site ne savait pas se configurer lui-meme
|
||||
|
||||
Parti pour eprouver une sonde, arrive sur un defaut structurel : **le runner du SITE ne
|
||||
|
|
|
|||
39
Makefile
39
Makefile
|
|
@ -1054,6 +1054,45 @@ site-appliquer: ## Applique un role aux machines du site — GROUPE=<serveur_ops
|
|||
ansible-playbook -i scripts/site_inventaire.py "playbooks/groupes/$(GROUPE).yml" \
|
||||
"$${supp[@]}" $(ARGS)
|
||||
|
||||
.PHONY: site-deployer-tout
|
||||
site-deployer-tout: ansible-runtime ## Deploie TOUT le site dans l'ordre des couches — CONFIRMER=true
|
||||
@# LE SITE AVAIT L'ORCHESTRATION, PAS LE MOYEN DE LA LANCER (2026-09-14).
|
||||
@#
|
||||
@# `playbooks/site.yml` est genere par `orchestrer.py` et ordonne les couches pour
|
||||
@# N'IMPORTE QUELLE instance — son en-tete le dit : « le meme fichier sert toute
|
||||
@# instance ». Mais `deployer-tout` ne vise que l'inventaire d'un LOCATAIRE, et le
|
||||
@# site n'avait que `site-appliquer GROUPE=<un seul>`.
|
||||
@#
|
||||
@# CE QUE CA COUTAIT : le site ne se DEPLOYAIT que groupe par groupe, a la main, dans
|
||||
@# un ordre qu'il fallait se rappeler. Un hebergeur qu'on ne peut remonter qu'en
|
||||
@# enchainant onze groupes de memoire n'est pas reconstructible — il est reparable par
|
||||
@# quelqu'un qui se souvient. C'est nommement l'une des trois limites du jalon de
|
||||
@# reconstruction autonome : « le SITE jamais reconstruit ».
|
||||
@#
|
||||
@# TROIS DIFFERENCES AVEC `deployer-tout`, ET AUCUNE N'EST COSMETIQUE :
|
||||
@#
|
||||
@# l'inventaire est un SCRIPT (`site_inventaire.py`), pas un fichier : un site se
|
||||
@# derive de son underlay, il ne se fige pas dans un `hosts.yml`.
|
||||
@# la voute vit a cote de la carte (`underlay.vault.yml`), hors depot, et non
|
||||
@# dans `group_vars/all`. Sans le `-e @`, les roles partages echouent
|
||||
@# sur une assertion qui ne dit pas qu'il manque un FICHIER.
|
||||
@# le perimetre est `hotes_actifs`, comme chez un locataire — les hyperviseurs et
|
||||
@# la frontiere sont dans l'inventaire mais ne se deploient pas.
|
||||
@set -e; \
|
||||
if [[ "$(CONFIRMER)" != "true" ]]; then \
|
||||
printf '%s\n' 'Refus: deploiement ORCHESTRE de TOUT le site (action impactante).'; \
|
||||
printf '%s\n' 'Relancer avec CONFIRMER=true. Astuce: tester d abord en idempotent avec MODE_CHECK=1.'; \
|
||||
exit 2; \
|
||||
fi; \
|
||||
python3 scripts/verifier_genome_a_jour.py || exit 2; \
|
||||
python3 scripts/orchestrer.py verifier; \
|
||||
python3 scripts/orchestrer.py ecrire; \
|
||||
voute="$$(dirname "$$(readlink -f underlay.yml)")/underlay.vault.yml"; \
|
||||
supp=(); [[ -f "$$voute" ]] && supp+=( -e "@$$voute" ); \
|
||||
mode="$$([[ -n "$(MODE_CHECK)" ]] && printf -- '--check --diff' || true)"; \
|
||||
ansible-playbook -i scripts/site_inventaire.py playbooks/site.yml \
|
||||
--limit "$(GROUPE_HOTES_ACTIFS)" "$${supp[@]}" $$mode $(ARGS)
|
||||
|
||||
# --- LE GENOME REMONTE SUR LA FORGE DU SITE -----------------------------------
|
||||
#
|
||||
# La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant ne route
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 5 pool(s) Proxmox, 44 VM placee(s), aucun nom ni VMID en collision. |
|
||||
| P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 33 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 22, socle-identite 2, web-sso 5) ; 2 lacune(s) nommee(s) : serveur_loki, serv |
|
||||
| P30 | SDN EVPN : zones, VNets et sous-reseaux derives | AFF-112 | ✅ OK | CONFORME : SDN EVPN, 3 zone(s), 15 VNet(s), 15 sous-reseau(x), aucune collision. |
|
||||
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 65 scripts expliques et atteignables, 121 cibles make documentees, 68 roles avec README. |
|
||||
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 65 scripts expliques et atteignables, 122 cibles make documentees, 68 roles avec README. |
|
||||
| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 38 exigence(s) de role, toutes satisfaites (149 cle(s) declaree(s) par l'instance). |
|
||||
| P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 34 revendication(s) de port, aucune collision entre roles co-localises (36 groupes). |
|
||||
| P34 | Chaque document declare son lecteur | — | ✅ OK | 45 document(s) declarent leur lecteur (40 genere(s) exempte(s)). |
|
||||
|
|
|
|||
|
|
@ -196,6 +196,21 @@
|
|||
executable: /bin/bash
|
||||
register: hosts_statiques_accord
|
||||
changed_when: false
|
||||
# LIRE N'EST PAS CHANGER, ET `--check` NE DOIT PAS RENDRE LA GARDE FOLLE (2026-09-14).
|
||||
#
|
||||
# Sans `check_mode: false`, cette commande est SAUTEE en mode idempotent. La garde qui
|
||||
# suit compare alors du VIDE et refuse, sur les sept machines a la fois :
|
||||
#
|
||||
# ne portent pas le meme nombre d'entrees ()
|
||||
#
|
||||
# Les parentheses vides sont tout le diagnostic — il n'y avait aucun compte a comparer.
|
||||
# Le Makefile CONSEILLE pourtant ce mode (« tester d abord en idempotent »), donc un
|
||||
# essai a blanc rendait sept faux echecs a qui suivait le conseil.
|
||||
#
|
||||
# Cette tache ne fait que LIRE deux fichiers et compter des lignes. La faire tourner en
|
||||
# `--check` ne modifie rien et rend au mode idempotent ce qu'il promet : dire ce qui
|
||||
# changerait, pas inventer des pannes.
|
||||
check_mode: false
|
||||
when:
|
||||
- hosts_statiques_actif | bool
|
||||
- ansible_facts.os_family | default('') == 'Debian'
|
||||
|
|
@ -229,3 +244,17 @@
|
|||
# divergence la ou il n'y a plus qu'un seul fichier. Une garde qui survit a ce qu'elle
|
||||
# gardait ne mesure plus rien : elle invente.
|
||||
- hosts_statiques_gabarits_cloud_init.stat.isdir | default(false)
|
||||
# NI EN MODE IDEMPOTENT, POUR LA MEME RAISON (2026-09-14). Cette garde compare l'etat
|
||||
# que la tache « Poser le plancher dans le gabarit maitre » vient d'etablir vingt
|
||||
# lignes plus haut. En `--check`, cette ecriture est SIMULEE : le gabarit sur disque
|
||||
# porte encore l'etat d'AVANT, et la garde compare donc l'avant a l'apres.
|
||||
#
|
||||
# /etc/hosts=13 | /etc/cloud/templates/hosts.debian.tmpl=2
|
||||
#
|
||||
# Sept machines en echec sur un essai a blanc, alors que le deploiement reel passe.
|
||||
# Le Makefile CONSEILLE ce mode — « tester d abord en idempotent » — donc suivre le
|
||||
# conseil fabriquait sept fausses pannes.
|
||||
#
|
||||
# Une assertion qui porte sur une post-condition de son propre play n'a rien a dire
|
||||
# tant que ce play n'a rien ecrit.
|
||||
- not ansible_check_mode
|
||||
|
|
|
|||
|
|
@ -37,6 +37,22 @@
|
|||
url: "{{ serveur_icinga_keyring_url }}"
|
||||
dest: "/tmp/icinga-archive-keyring.deb"
|
||||
mode: "0644"
|
||||
# RECUPERER N'EST PAS INSTALLER, ET `--check` CASSAIT LA PAIRE (2026-09-14).
|
||||
#
|
||||
# Sans `check_mode: false`, ce telechargement est SIMULE en mode idempotent — et la
|
||||
# tache qui suit cherche alors un fichier qui n'existe pas :
|
||||
#
|
||||
# Unable to install package: E:Could not open file
|
||||
# /tmp/icinga-archive-keyring.deb - open (2: No such file or directory)
|
||||
#
|
||||
# Un essai a blanc rendait donc un echec sur la machine de supervision, alors que le
|
||||
# deploiement reel passe. Le Makefile conseille ce mode : suivre le conseil fabriquait
|
||||
# une fausse panne, et c'est la troisieme de cette famille dans le meme essai.
|
||||
#
|
||||
# Ce que ce `check_mode: false` autorise reellement : deposer un fichier dans `/tmp`.
|
||||
# Rien du systeme gere n'en depend, et c'est ce qui permet a l'installation d'ETRE
|
||||
# evaluee — donc au mode idempotent de dire ce qu'il promet.
|
||||
check_mode: false
|
||||
# LA CLE PASSE PAR LE CACHE, ELLE AUSSI (mesure du 2026-09-10).
|
||||
#
|
||||
# `get_url` ignore la configuration d'apt : le mandataire pose dans
|
||||
|
|
|
|||
|
|
@ -122,6 +122,16 @@
|
|||
become: false
|
||||
run_once: true
|
||||
changed_when: false
|
||||
# LIRE UNE VERSION N'EST PAS CHANGER, ET `--check` RENDAIT LA GARDE MUETTE (2026-09-14).
|
||||
#
|
||||
# Sans `check_mode: false`, cette commande est sautee en mode idempotent : la garde qui
|
||||
# suit compare alors contre du VIDE et refuse.
|
||||
#
|
||||
# Le controleur tourne Python et site-ops-01 tourne Python 3.13
|
||||
#
|
||||
# L'espace apres « Python » est tout le diagnostic — il n'y avait rien a comparer. Un
|
||||
# essai a blanc rendait donc un echec sur le runner, alors que le deploiement reel passe.
|
||||
check_mode: false
|
||||
register: serveur_ops_python_controleur
|
||||
|
||||
- name: Exiger que le controleur et la cible partagent leur version de Python
|
||||
|
|
|
|||
Loading…
Reference in a new issue