client_unbound : survivre a la perte de connexion sans la masquer
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 <noreply@anthropic.com>
This commit is contained in:
parent
9cdfcc5deb
commit
0de5294a20
4 changed files with 53 additions and 0 deletions
29
CHANGELOG.md
29
CHANGELOG.md
|
|
@ -1,5 +1,34 @@
|
||||||
# CHANGELOG — Set-OPS
|
# 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
|
## 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
|
`proxmox_clone_source_nom` / `proxmox_clone_vmid_modele` pointent désormais sur
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,7 @@ client_unbound_transitaires: []
|
||||||
client_unbound_apply: false
|
client_unbound_apply: false
|
||||||
client_unbound_confirm: false
|
client_unbound_confirm: false
|
||||||
client_unbound_resolv_conf: "/etc/resolv.conf"
|
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
|
||||||
|
|
|
||||||
|
|
@ -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
|
- name: Redémarrer unbound
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: "{{ client_unbound_service }}"
|
name: "{{ client_unbound_service }}"
|
||||||
state: restarted
|
state: restarted
|
||||||
when: not ansible_check_mode
|
when: not ansible_check_mode
|
||||||
|
ignore_unreachable: true
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,14 @@
|
||||||
- name: Appliquer les redémarrages Unbound avant toute validation/bascule
|
- name: Appliquer les redémarrages Unbound avant toute validation/bascule
|
||||||
ansible.builtin.meta: flush_handlers
|
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) ---
|
# --- Bascule du resolver : PROTÉGÉE + validée (ne casse jamais un nœud) ---
|
||||||
- name: Refuser la bascule du resolver sans confirmation explicite
|
- name: Refuser la bascule du resolver sans confirmation explicite
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue