LA SCISSION. cache-apt fondait deux causes aux DELAIS differents : « ne repond pas » arrete tout apt de l ecosysteme, on agit dans la minute ; « volume a 90 % » est un billet pour demain. Les fondre obligeait soit a reveiller quelqu un pour un disque, soit a traiter une panne comme un billet. Deux sondes, chacune avec son etat, son historique, son acquittement — et prouvees INDEPENDANTES : port ferme -> cache-apt CRITIQUE, cache-apt-volume OK seuil impossible -> cache-apt OK, cache-apt-volume AVERTISSEMENT CE QUE LA VERIFICATION A REVELE. Un resultat pousse et accepte (code 200) n apparaissait pas en base. Hypothese testee et confirmee : IcingaDB n ECRIT service_state QUE SUR CHANGEMENT D ETAT. Un OK identique repete ne produit aucune ecriture ; un AVERTISSEMENT pousse ensuite est ecrit en 13 s. Or la sonde moteur, ecrite quelques heures plus tot, lisait exactement max(last_update) de service_state pour juger de la fraicheur. Elle mesurait le CHANGEMENT. Sur un ecosysteme parfaitement STABLE — celui qu on veut — plus rien ne change, last_update vieillit, et elle serait passee en avertissement a 15 min puis en critique a 90. Une alarme qui se declenche PARCE QUE tout va bien, avec un delai qui l aurait rendue difficile a rattacher a sa cause. La bonne source existait : icingadb_instance porte le battement du synchroniseur, ecrit en continu. Releve a 1 s sur un systeme sain. Seuils ramenes de 15/90 min a 1/5 min. Controle negatif rejoue. Dix-huit services, tous verts sauf sauvegarde 7/9 (deja connu). make prouver : CONFORME, 64 OK, 0 echec, 0 saute. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
55 lines
3.1 KiB
Django/Jinja
55 lines
3.1 KiB
Django/Jinja
#!/bin/bash
|
|
# GENERE par Set-OPS (role serveur_icinga). Ne pas editer a la main.
|
|
#
|
|
# SONDE « moteur » — l'etat des controles arrive frais jusqu'a IcingaDB
|
|
#
|
|
# Contrat : docs/supervision-conception.md (API des greffons Nagios) — une ligne, 0/1/2.
|
|
# Mise en defaut PAR PARAMETRE : `serveur_icinga_sonde_age_crit` (age impossible).
|
|
set -uo pipefail
|
|
|
|
CONF={{ serveur_icinga_sonde_config_db }}
|
|
AVERT={{ serveur_icinga_sonde_age_avert }}
|
|
CRIT={{ serveur_icinga_sonde_age_crit }}
|
|
|
|
systemctl is-active --quiet icinga2 || { echo "Le moteur Icinga n'est pas actif."; exit 2; }
|
|
systemctl is-active --quiet icingadb || { echo "La synchronisation IcingaDB n'est pas active."; exit 2; }
|
|
|
|
# ON NE SE FIE PAS A `is-active` SEUL — c'est le mensonge que ce depot a deja paye avec
|
|
# les sauvegardes : un service vert sur un travail qui n'aboutit pas. On demande a la BASE
|
|
# depuis combien de temps elle n'a pas ete rafraichie.
|
|
hote=$(grep -m1 -A5 '^database:' "${CONF}" 2>/dev/null | grep -m1 'host:' | awk '{print $2}')
|
|
mdp=$(grep -m1 'password:' "${CONF}" 2>/dev/null | awk '{print $2}')
|
|
base=$(grep -m1 -A5 '^database:' "${CONF}" 2>/dev/null | grep -m1 'database:' | awk '{print $2}')
|
|
util=$(grep -m1 -A6 '^database:' "${CONF}" 2>/dev/null | grep -m1 'user:' | awk '{print $2}')
|
|
[[ -n "${hote}" && -n "${mdp}" ]] || { echo "Configuration IcingaDB illisible (${CONF})."; exit 2; }
|
|
|
|
# LE BATTEMENT D'ICINGADB, PAS LA FRAICHEUR DES ETATS (correction du 2026-09-10).
|
|
#
|
|
# La premiere version lisait `max(last_update)` de `service_state`. Mesure : IcingaDB
|
|
# n'ECRIT QUE SUR CHANGEMENT D'ETAT. Un resultat identique repete ne produit aucune
|
|
# ecriture — verifie en poussant un OK (rien ne bouge) puis un AVERTISSEMENT (ecrit en
|
|
# 13 s).
|
|
#
|
|
# La sonde mesurait donc le CHANGEMENT, pas la fraicheur. Sur un ecosysteme parfaitement
|
|
# STABLE — celui qu'on veut — plus rien ne change, `last_update` vieillit, et la sonde
|
|
# serait passee en avertissement a 15 min puis en critique a 90 min. Une alarme qui se
|
|
# declenche PARCE QUE tout va bien : exactement le piege que ce document interdit, avec
|
|
# un delai qui l'aurait rendue difficile a comprendre.
|
|
#
|
|
# `icingadb_instance` porte le battement du synchroniseur, ecrit en continu qu'il y ait
|
|
# ou non des changements. C'est lui qui dit « la chaine moteur -> Redis -> base est
|
|
# vivante » — releve a 1 seconde sur un systeme sain.
|
|
age=$(PGPASSWORD="${mdp}" psql -h "${hote}" -U "${util:-icingadb}" -d "${base:-icingadb}" -Atc \
|
|
"select coalesce((extract(epoch from now()) - max(heartbeat)/1000)::bigint, 999999) from icingadb_instance" 2>/dev/null)
|
|
[[ "${age}" =~ ^-?[0-9]+$ ]] || { echo "La base de supervision ne repond pas (${hote})."; exit 2; }
|
|
(( age < 0 )) && age=0
|
|
|
|
if (( age >= CRIT )); then
|
|
echo "Synchronisation FIGEE : IcingaDB n'a pas battu depuis ${age} s — la supervision montre le passe.|age=${age}s;${AVERT};${CRIT};0;"
|
|
exit 2
|
|
fi
|
|
if (( age >= AVERT )); then
|
|
echo "Battement d'IcingaDB vieillissant : ${age} s (seuil ${AVERT}).|age=${age}s;${AVERT};${CRIT};0;"
|
|
exit 1
|
|
fi
|
|
echo "Moteur et synchronisation vivants : IcingaDB a battu il y a ${age} s.|age=${age}s;${AVERT};${CRIT};0;"
|