diff --git a/CHANGELOG.md b/CHANGELOG.md index bee5568..6631902 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # CHANGELOG — Set-OPS +## 2026-08-09 — `client_unbound` : survivre à la perte de connexion, sans la masquer + +Le déploiement de `web-dorsal-01` s'était interrompu autour du redémarrage d'Unbound — +« Connection timed out during banner exchange ». Ansible marque alors l'hôte injoignable et +**abandonne toutes ses couches suivantes**, alors que la machine répondait de nouveau une +minute plus tard. + +**Ma première explication était fausse, et je l'ai vérifiée avant de coder** : je pensais à +la résolution inverse de `sshd` au moment où le résolveur bascule. `sshd -T` répond +`usedns no` — elle n'a pas lieu. Et **la cause reste inconnue** : j'avais écrasé le journal +du déploiement raté en relançant, donc il n'est plus lisible. Faute de méthode, pas de +raisonnement. + +Ce que le dépôt sait déjà de ce symptôme est consigné dans le `Makefile` (`_attendre-hote`) : +à travers la frontière, le TCP s'établit par proxy SYN, et l'échec se lit « banner +exchange » **même quand l'hôte n'est simplement pas là**. Le message accuse SSH pour un +problème d'accessibilité. + +**Corrigé sans prétendre connaître la cause** : le handler de redémarrage tolère la perte +(`ignore_unreachable`), et une tâche **exige ensuite le retour** de l'hôte +(`wait_for_connection`, 180 s). On attend une condition, pas une durée. + +Ce n'est **pas** masquer une panne : si l'hôte ne revient pas, la tâche suivante échoue +franchement. Ce qui change, c'est qu'une absence d'une minute n'annule plus une heure de +déploiement. + +**Et une règle pour moi** : ne plus écraser le journal d'un échec avant de l'avoir lu. Le +diagnostic de cette course a été rendu impossible par un `rm -f` de confort. + ## 2026-08-09 — Le plan bascule sur le gabarit recapturé, prouvé par une VM réelle `proxmox_clone_source_nom` / `proxmox_clone_vmid_modele` pointent désormais sur diff --git a/roles/client_unbound/defaults/main.yml b/roles/client_unbound/defaults/main.yml index 46bb71a..32b08fe 100644 --- a/roles/client_unbound/defaults/main.yml +++ b/roles/client_unbound/defaults/main.yml @@ -22,3 +22,7 @@ client_unbound_transitaires: [] client_unbound_apply: false client_unbound_confirm: false client_unbound_resolv_conf: "/etc/resolv.conf" + +# Delai maximal pour que l'hote reponde apres le redemarrage d'Unbound. Depasser reste +# un ECHEC : on attend une machine qui revient, pas une panne qu'on tait. +client_unbound_attente_reconnexion: 180 diff --git a/roles/client_unbound/handlers/main.yml b/roles/client_unbound/handlers/main.yml index 7df4880..12427db 100644 --- a/roles/client_unbound/handlers/main.yml +++ b/roles/client_unbound/handlers/main.yml @@ -1,6 +1,18 @@ --- +# `ignore_unreachable` : le redemarrage a deja fait perdre la connexion en cours de +# deploiement — « Connection timed out during banner exchange », le 2026-08-09 sur +# web-dorsal-01. La CAUSE n'est pas etablie : `usedns no` ecarte la resolution inverse +# de sshd, et le journal du deploiement rate a ete ecrase avant d'etre lu. Ce que le +# depot sait deja de ce symptome (Makefile, `_attendre-hote`) : a travers la frontiere, +# le TCP s'etablit par proxy SYN et l'echec se lit ainsi meme quand l'hote n'est +# simplement pas la. +# +# On ne masque donc pas une panne : une perte ICI n'abandonne plus les couches +# suivantes, et `wait_for_connection` exige que l'hote revienne pour de bon. S'il ne +# revient pas, la tache suivante echoue — franchement. - name: Redémarrer unbound ansible.builtin.systemd: name: "{{ client_unbound_service }}" state: restarted when: not ansible_check_mode + ignore_unreachable: true diff --git a/roles/client_unbound/tasks/main.yml b/roles/client_unbound/tasks/main.yml index 63daadf..d847b1a 100644 --- a/roles/client_unbound/tasks/main.yml +++ b/roles/client_unbound/tasks/main.yml @@ -36,6 +36,14 @@ - name: Appliquer les redémarrages Unbound avant toute validation/bascule ansible.builtin.meta: flush_handlers +# Attendre une CONDITION — que l'hote reponde — et non une duree. Si la connexion a +# saute pendant le redemarrage, on la retablit ici ; sinon la tache passe aussitot. +- name: Exiger que l hote reponde avant de poursuivre + ansible.builtin.wait_for_connection: + timeout: "{{ client_unbound_attente_reconnexion }}" + sleep: 5 + when: not ansible_check_mode + # --- Bascule du resolver : PROTÉGÉE + validée (ne casse jamais un nœud) --- - name: Refuser la bascule du resolver sans confirmation explicite ansible.builtin.assert: