From 0de5294a20958d9286cbf090d02bb1e57f132732 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Sun, 9 Aug 2026 11:55:41 -0400 Subject: [PATCH] client_unbound : survivre a la perte de connexion sans la masquer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le deploiement s'interrompait autour du redemarrage d'Unbound (« banner exchange »), et Ansible abandonnait alors TOUTES les couches suivantes de l'hote — alors qu'il repondait de nouveau une minute plus tard. Ma premiere explication etait fausse et je l'ai verifiee avant de coder : sshd -T dit usedns no, il n'y a pas de resolution inverse. Et la cause reste INCONNUE — j'avais ecrase le journal du deploiement rate en relancant. Faute de methode, pas de raisonnement. Ce que le depot sait de ce symptome est deja dans le Makefile : a travers la frontiere le TCP s'etablit par proxy SYN, et l'echec se lit « banner exchange » meme quand l'hote n'est pas la. Le message accuse SSH pour un probleme d'accessibilite. Corrige sans pretendre connaitre la cause : ignore_unreachable sur le handler, puis wait_for_connection qui EXIGE le retour (180 s). Si l'hote ne revient pas, la tache suivante echoue franchement — on ne masque rien. Regle pour moi : ne plus ecraser le journal d'un echec avant de l'avoir lu. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 29 ++++++++++++++++++++++++++ roles/client_unbound/defaults/main.yml | 4 ++++ roles/client_unbound/handlers/main.yml | 12 +++++++++++ roles/client_unbound/tasks/main.yml | 8 +++++++ 4 files changed, 53 insertions(+) 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: