artefacts : deux filets — un cache mort ne doit plus rendre un tenant irreparable
CE CACHE EST UN MAILLON DONT DEPEND SA PROPRE RECONSTRUCTION. Toute la flotte y prend ses paquets. S il pointe vers un amont mort, apt echoue sur les quinze machines, donc le socle echoue, donc le deploiement n atteint jamais la couche qui poserait le bon amont. LE CORRECTIF SE RETROUVE DANS LA COUCHE QUE LA PANNE EMPECHE D ATTEINDRE, et il faut une main pour en sortir. C est arrive le 2026-08-31 : l amont pointait sur le cache de patient 0, eteint la veille pour liberer de la RAM. apt rendait « 503 Connection timeout » EN CITANT L ADRESSE DU CACHE LOCAL, jamais celle de l amont manquant — la panne accusait le maillon visible. DEUX FILETS, SYMETRIQUES. serveur_artefacts sonde l amont AVANT d ecrire, et refuse s il est muet : mieux vaut un cache qui garde sa configuration precedente qu un cache qu on vient de rendre inutilisable pour toute la flotte. client_artefacts sonde la source AVANT de detourner apt vers elle. Ce fichier ECRASE le plancher d amorcage pose par le socle — le poser sur un cache mort prive la machine du cache du SITE, qui lui fonctionnait. En refusant, le plancher reste : la flotte est degradee mais debout, et REPARABLE PAR UN DEPLOIEMENT. `ignore_errors` ET NON `failed_when: false` — la difference est toute la garde. failed_when: false REECRIT le verdict : la tache n est plus jamais failed, donc `is not failed` est toujours vrai, donc l assertion ne peut pas tirer. Ecrite ainsi, ma premiere version a declare « joignable » un amont mesure MUET la seconde d avant. Une garde qui ne peut pas echouer ne garde rien. Deux controles verifies sur la machine : amont eteint -> refuse ; amont reel -> pose. make verifier : vert. make prouver : CONFORME, 55 OK, 0 echec, 0 saute. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
This commit is contained in:
parent
e2bc235132
commit
0dd57ba995
3 changed files with 138 additions and 0 deletions
37
CHANGELOG.md
37
CHANGELOG.md
|
|
@ -1,5 +1,42 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-08-31 — Deux filets : un cache mort ne rend plus un tenant irreparable
|
||||
|
||||
**55 preuves.** Le cache d'un tenant est **un maillon dont depend sa propre
|
||||
reconstruction**. Toute la flotte y prend ses paquets ; s'il pointe vers un amont mort,
|
||||
`apt` echoue sur les quinze machines, donc le socle echoue, donc le deploiement n'atteint
|
||||
jamais la couche qui poserait le bon amont.
|
||||
|
||||
*Le correctif se retrouve dans la couche que la panne empeche d'atteindre* — et il faut
|
||||
une main pour en sortir. C'est exactement ce qui s'est passe : l'amont pointait sur le
|
||||
cache de patient 0, eteint la veille pour liberer de la RAM.
|
||||
|
||||
**`apt` rendait `503 Connection timeout` en citant l'adresse du cache LOCAL**, jamais
|
||||
celle de l'amont manquant. La panne accusait le maillon visible.
|
||||
|
||||
### Deux filets, symetriques
|
||||
|
||||
`serveur_artefacts` sonde l'amont **avant** d'ecrire, et refuse s'il est muet : mieux vaut
|
||||
un cache qui garde sa configuration precedente qu'un cache qu'on vient de rendre
|
||||
inutilisable pour toute la flotte.
|
||||
|
||||
`client_artefacts` sonde la source **avant** de detourner `apt` vers elle. Ce fichier
|
||||
ecrase le plancher d'amorcage pose par le socle — le poser sur un cache mort prive la
|
||||
machine du cache du SITE, qui lui fonctionnait. En refusant, le plancher reste : la flotte
|
||||
est degradee mais debout, et **reparable par un deploiement**.
|
||||
|
||||
### `ignore_errors` et non `failed_when: false` — la difference est toute la garde
|
||||
|
||||
`failed_when: false` **reecrit le verdict** : la tache n'est plus jamais `failed`, donc
|
||||
`is not failed` est toujours vrai, donc l'assertion qui suit ne peut pas tirer. Ecrite
|
||||
ainsi, ma premiere version a declare « joignable » un amont mesure **muet la seconde
|
||||
d'avant**.
|
||||
|
||||
*Une garde qui ne peut pas echouer ne garde rien.* Deux controles verifies sur la machine :
|
||||
amont eteint → refuse ; amont reel → pose.
|
||||
|
||||
make verifier : vert. make prouver : CONFORME, 55 OK, 0 echec, 0 saute.
|
||||
|
||||
## 2026-08-31 — Trois unites en echec sur chaque machine, et personne ne les voyait
|
||||
|
||||
**55 preuves.** Le deploiement rendait `15/15, failed=0`. Les machines portaient chacune
|
||||
|
|
|
|||
|
|
@ -8,6 +8,53 @@
|
|||
Déclarer le service au plan, ou forcer client_artefacts_actif=false.
|
||||
when: client_artefacts_actif | bool
|
||||
|
||||
# --- LE FILET, COTE CLIENT : NE PAS VISER UN CACHE QUI NE SERT PAS ------------
|
||||
#
|
||||
# Symetrique de la garde de `serveur_artefacts` (mesure du 2026-08-31). Celle-la protege
|
||||
# le CACHE d'un amont mort ; celle-ci protege LA FLOTTE d'un cache mort.
|
||||
#
|
||||
# Ce fichier ECRASE le plancher d'amorcage pose par le socle — il trie apres. Le poser
|
||||
# alors que le cache du tenant ne repond pas prive donc la machine du cache du SITE, qui
|
||||
# lui fonctionnait : on remplace une source qui marche par une qui ne marche pas.
|
||||
#
|
||||
# Quinze machines ont ainsi perdu `apt` d'un coup, et le deploiement ne pouvait plus
|
||||
# atteindre la couche qui aurait repare le cache. En laissant le plancher en place, elles
|
||||
# restent servies par le site — dégradé, mais debout, et reparable par un deploiement.
|
||||
- name: La source de l'écosystème répond-elle vraiment ?
|
||||
ansible.builtin.wait_for:
|
||||
host: "{{ client_artefacts_hote }}.{{ domaine_interne }}"
|
||||
port: "{{ client_artefacts_port }}"
|
||||
timeout: 10
|
||||
register: client_artefacts_sonde
|
||||
changed_when: false
|
||||
# `ignore_errors` ET NON `failed_when: false` — LA DIFFERENCE EST TOUTE LA GARDE.
|
||||
#
|
||||
# `failed_when: false` REECRIT le verdict : la tache n'est plus jamais `failed`, donc
|
||||
# `is not failed` est toujours vrai, donc l'assertion qui suit ne peut PAS tirer. Ecrite
|
||||
# ainsi, elle a declare « joignable » un amont mesure MUET la seconde d'avant
|
||||
# (2026-08-31). Une garde qui ne peut pas echouer ne garde rien.
|
||||
#
|
||||
# `ignore_errors` laisse le verdict intact et se contente de ne pas arreter le play :
|
||||
# c'est ce qu'il faut pour SONDER puis DECIDER.
|
||||
ignore_errors: true
|
||||
when:
|
||||
- client_artefacts_actif | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Refuser de detourner apt vers une source muette
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- client_artefacts_sonde is not failed
|
||||
fail_msg: >-
|
||||
{{ client_artefacts_hote }}:{{ client_artefacts_port }} ne repond pas. Diriger `apt`
|
||||
vers elle retirerait a cette machine le cache d'amorcage du SITE, qui fonctionne —
|
||||
et la flotte perdrait `apt` sans qu'un deploiement puisse la reparer.
|
||||
Deployer `serveur_artefacts` sur {{ client_artefacts_hote }} d'abord.
|
||||
success_msg: "Source d'artefacts {{ client_artefacts_hote }} joignable."
|
||||
when:
|
||||
- client_artefacts_actif | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Diriger apt vers la source de l'écosystème
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ client_artefacts_fichier }}"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,60 @@
|
|||
# dernier lu gagne. Le préfixe `zzz-` place donc notre configuration après celle du
|
||||
# paquet Debian et celle de debconf, sans avoir à les éditer — on ajoute, on ne remplace
|
||||
# pas. Une valeur posée ici l'emporte, et `apt purge` rend la machine à son état d'origine.
|
||||
# --- LE FILET : NE PAS POSER UN AMONT INJOIGNABLE ----------------------------
|
||||
#
|
||||
# CE CACHE EST UN MAILLON DONT DEPEND SA PROPRE RECONSTRUCTION (mesure du 2026-08-31).
|
||||
#
|
||||
# Toute la flotte du tenant prend ses paquets ici. Si ce cache pointe vers un amont mort,
|
||||
# `apt` echoue sur les QUINZE machines — donc le socle echoue, donc le deploiement
|
||||
# n'atteint jamais la couche qui poserait le bon amont. Le correctif se retrouve dans la
|
||||
# couche que la panne empeche d'atteindre, et il faut une main pour en sortir.
|
||||
#
|
||||
# C'est exactement ce qui est arrive : l'amont pointait sur le cache de patient 0, eteint
|
||||
# la veille pour liberer de la RAM. `apt` rendait `503 Connection timeout` EN CITANT
|
||||
# L'ADRESSE DU CACHE LOCAL, jamais celle de l'amont manquant — la panne accusait le
|
||||
# maillon visible.
|
||||
#
|
||||
# On mesure donc AVANT d'ecrire. Un amont injoignable est refuse : mieux vaut un cache
|
||||
# qui garde sa configuration precedente et un message clair, qu'un cache qu'on vient de
|
||||
# rendre inutilisable pour toute la flotte.
|
||||
- name: L'amont declare repond-il ?
|
||||
ansible.builtin.wait_for:
|
||||
host: "{{ serveur_artefacts_amont | urlsplit('hostname') }}"
|
||||
port: "{{ serveur_artefacts_amont | urlsplit('port') | default(3142, true) | int }}"
|
||||
timeout: 10
|
||||
register: serveur_artefacts_amont_sonde
|
||||
changed_when: false
|
||||
# `ignore_errors` ET NON `failed_when: false` — LA DIFFERENCE EST TOUTE LA GARDE.
|
||||
#
|
||||
# `failed_when: false` REECRIT le verdict : la tache n'est plus jamais `failed`, donc
|
||||
# `is not failed` est toujours vrai, donc l'assertion qui suit ne peut PAS tirer. Ecrite
|
||||
# ainsi, elle a declare « joignable » un amont mesure MUET la seconde d'avant
|
||||
# (2026-08-31). Une garde qui ne peut pas echouer ne garde rien.
|
||||
#
|
||||
# `ignore_errors` laisse le verdict intact et se contente de ne pas arreter le play :
|
||||
# c'est ce qu'il faut pour SONDER puis DECIDER.
|
||||
ignore_errors: true
|
||||
when:
|
||||
- serveur_artefacts_amont | length > 0
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Refuser un amont injoignable plutot que de rendre ce cache inutilisable
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- serveur_artefacts_amont_sonde is not failed
|
||||
fail_msg: >-
|
||||
L'amont declare ({{ serveur_artefacts_amont }}) ne repond pas. Le poser rendrait ce
|
||||
cache — et donc `apt` sur TOUTE la flotte de cet ecosysteme — inutilisable, et le
|
||||
deploiement ne pourrait plus atteindre la couche qui le corrigerait.
|
||||
Verifier que la machine d'amont tourne, ou vider `serveur_artefacts_amont` pour
|
||||
aller directement chez Debian (c'est une emancipation : voir
|
||||
docs/filiation-emancipation.md).
|
||||
success_msg: "Amont {{ serveur_artefacts_amont }} joignable."
|
||||
when:
|
||||
- serveur_artefacts_amont | length > 0
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Déployer la configuration Set-OPS
|
||||
ansible.builtin.template:
|
||||
src: zzz-setops.conf.j2
|
||||
|
|
|
|||
Loading…
Reference in a new issue