La moitie qui manquait. Les roles declaraient leurs panneaux, Prometheus en derivait ses cibles, les expressions repondaient, et rien ne les assemblait. serveur_grafana lit les memes meta/metriques.yml que serveur_prometheus et en assemble un tableau par role — la raison du panneau devient sa description dans Grafana. Moisson des tableaux orphelins, prefixe setops-role- pour ne jamais toucher un tableau ecrit a la main, JSON valide avant d etre pose (Grafana ne tombe pas sur un tableau illisible : il le saute en silence). client_metrique declare quatre panneaux sans exportateur — le cas symetrique. Celui qui compte : la memoire disponible, depuis que le ballon est actif. Eprouve sur le site : les deux tableaux charges dans le stockage unifie, un temoin orphelin retire, les quatre panneaux de flotte a 10 series chacun. Un panneau etait faux — /var/lib/lxcfs rapporte toujours zero octet libre et un min() en meurt. Corrige en liste blanche : un montage inconnu manque au graphe, ce qui se voit, au lieu de l ecraser. P77 garde la table des unites : une unite inventee retombe sur short, lisible et fausse. 76 OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
251 lines
12 KiB
Markdown
251 lines
12 KiB
Markdown
# Supervision dérivée des rôles
|
|
|
|
> **Pour qui :** celui qui ajoute un rôle à Set-OPS et se demande comment sa supervision
|
|
> arrive dans Icinga — et celui qui exploite et veut savoir d'où sortent les services
|
|
> qu'il voit.
|
|
|
|
> **La règle en une phrase.** Un rôle déclare les sondes de sa propre supervision ; le
|
|
> moteur en dérive les objets Icinga, la permission d'API et les preuves. Comme
|
|
> `meta/flux.yml` engendre nftables *et* OPNsense.
|
|
|
|
## Pourquoi
|
|
|
|
Le 2026-09-09, mesure du dépôt sur lui-même :
|
|
|
|
```
|
|
au 2026-09-09 :
|
|
39 rôles déclarent leurs flux -> nftables + OPNsense, dérivés
|
|
32 déclarent leur empreinte -> ressources des VM, dérivées
|
|
32 déclarent leur authentification -> habilitations, dérivées
|
|
19 groupes déclarent `surveillance:` -> RIEN
|
|
```
|
|
|
|
Au 2026-09-09, les dix-neuf lignes `surveillance:` de `docs/dependances-groupes.yml` sont écrites,
|
|
versionnées, relues — et **aucune n'est exécutée**. Icinga surveillait deux choses :
|
|
`sauvegarde` et `sante`.
|
|
|
|
C'est la classe d'échec que ce dépôt nomme partout ailleurs, en version documentaire : la
|
|
carte dit ce qui est surveillé, et personne ne surveille. *Une intention écrite n'est pas
|
|
une mesure.*
|
|
|
|
## Le contrat d'une sonde : c'est celui des greffons Nagios
|
|
|
|
Une sonde est un **script local**, déposé par le rôle qui la possède, dans
|
|
`/usr/local/lib/setops/sondes/<nom>.sh` (0750, root).
|
|
|
|
| | |
|
|
|---|---|
|
|
| **sortie standard** | `TEXTE lisible` puis, optionnellement, `\| métriques` |
|
|
| **code de sortie** | `0` OK · `1` AVERTISSEMENT · `2` CRITIQUE · `3` INCONNU |
|
|
| **réseau** | aucun besoin : c'est le porteur qui pousse le résultat |
|
|
| **durée** | courte ; le porteur passe toutes les 15 min |
|
|
|
|
> **Ce contrat n'est pas de nous.** C'est l'**API des greffons Nagios**, que
|
|
> `monitoring-plugins` implémente depuis vingt ans et qu'Icinga parle nativement. La
|
|
> première rédaction de ce document la décrivait sans la nommer — autrement dit la
|
|
> réinventait. `positionnement.md` dit l'inverse : *adopter aux seuils, ne pas
|
|
> réimplémenter*.
|
|
|
|
**La conséquence pratique est grande.** Un greffon standard **est** une sonde valide, sans
|
|
la moindre colle : `check_disk`, `check_load`, `check_procs`, `check_ntp_time`,
|
|
`check_file_age`, `check_smtp`… Une sonde ne s'écrit à la main que lorsque la vérité à
|
|
mesurer est propre à Set-OPS — et c'était le cas pour `client_pki/certificat`, qui compare
|
|
l'empreinte *servie* à celle du disque : aucun greffon ne sait ça.
|
|
|
|
### Ce que la flotte a vraiment sous la main — et ce qu'elle n'a pas
|
|
|
|
`client_sante` installe **`monitoring-plugins-basic`** : **53** greffons, mesurés le
|
|
2026-09-14 sur la flotte. Ce document a d'abord annoncé « 54 » et cité `check_pgsql` en
|
|
exemple. **`check_pgsql` n'en fait pas partie**, ni `check_dns`, ni `check_ldap` : ils sont
|
|
dans `monitoring-plugins-standard`.
|
|
|
|
Et ce paquet-là ne s'ajoute pas :
|
|
|
|
apt-get install -s monitoring-plugins-standard
|
|
→ samba, python3-samba, smbclient, snmp, tdb-tools…
|
|
|
|
Une pile Samba et une pile SNMP sur **chaque machine** de la flotte, pour obtenir trois
|
|
greffons. Le durcissement dit le contraire de ça.
|
|
|
|
**La conséquence pour qui écrit une sonde :** vérifier que le greffon appelé est dans
|
|
`-basic` avant de s'appuyer dessus. **Un greffon absent sort en 127** — qui n'est pas un
|
|
code Nagios (0/1/2/3) : la sonde devient illisible au lieu d'échouer proprement. Quand le
|
|
greffon manque, prendre l'outil natif du service (`dig` sur un résolveur, `psql` sur une
|
|
base) ; c'est déjà ce que fait `serveur_resolveur/resolution`.
|
|
|
|
Écrire du shell là où un greffon existe, c'est se donner du code à maintenir *et* se priver
|
|
de vingt ans de cas limites déjà rencontrés par d'autres.
|
|
|
|
Le rôle qui possède la sonde la **déploie lui-même** : il connaît ses chemins, ses
|
|
secrets, sa vérité de terrain. Il la **déclare** dans `meta/supervision.yml`, et c'est
|
|
cette déclaration que le moteur lit.
|
|
|
|
```yaml
|
|
# roles/<rôle>/meta/supervision.yml
|
|
sondes:
|
|
- nom: certificat
|
|
ttl: 5400
|
|
raison: "..."
|
|
```
|
|
|
|
## Passif, et à durée de vie — jamais actif
|
|
|
|
Un contrôle **actif** ne voit pas la machine **muette** : si elle ne répond plus, la sonde
|
|
échoue et on met ça sur le compte du réseau. Ici c'est le nœud qui parle, et le `ttl` de
|
|
son envoi fait la fraîcheur — sans nouvelle, Icinga périme le service tout seul.
|
|
|
|
**Le silence alerte autant que l'échec.** C'est exactement ce qui a manqué à
|
|
`openipmi.service` : une unité en échec à chaque démarrage pendant une semaine, et
|
|
`systemctl --failed` à zéro partout parce qu'aucune machine n'avait redémarré.
|
|
|
|
C'est aussi ce qu'impose *la vérification suit la clé* : la sonde tourne là où vit la
|
|
vérité, pas sur le superviseur. Un dépôt de sauvegarde chiffré côté client ne peut être
|
|
jugé que par qui détient la clé.
|
|
|
|
## Ce qui n'a rien à faire ici
|
|
|
|
Une **métrique à seuil** — durée de collecte, volume de journaux, taux d'occupation —
|
|
appartient à Prometheus et Grafana. Icinga répond à une seule question : *est-ce cassé ?*
|
|
Mélanger les deux rendrait les deux moins lisibles.
|
|
|
|
## L'autre moitié : `meta/metriques.yml`
|
|
|
|
Cette phrase appelle son pendant, et il porte le même patron — **le rôle déclare, le
|
|
moteur dérive**.
|
|
|
|
| fichier | ce qu'il produit | la question |
|
|
| --- | --- | --- |
|
|
| `meta/supervision.yml` | une **sonde** → un verdict, avec un TTL | *est-ce cassé ?* |
|
|
| `meta/metriques.yml` | un **exportateur** → une série ; des **panneaux** → un tableau | *depuis quand, et vers où ?* |
|
|
|
|
**Deux fichiers, deux consommateurs.** `serveur_prometheus` lit l'`exportateur` pour en
|
|
tirer sa cible de scrutation ; `serveur_grafana` lit les `panneaux` pour en assembler un
|
|
tableau par rôle. Les deux moitiés sont indépendantes : un rôle peut déclarer un
|
|
exportateur sans panneau (des séries collectées, regardées ailleurs), et des panneaux sans
|
|
exportateur (`client_metrique` — le job `node` est universel, écrit une fois, et le
|
|
dériver le ferait exister deux fois).
|
|
|
|
**Le flux n'est pas dérivé d'ici, et c'est voulu.** Le port de l'exportateur doit s'ouvrir
|
|
depuis l'observatoire, et c'est `meta/flux.yml` qui le déclare — là où vivent déjà tous les
|
|
flux du rôle. Deux fichiers pour un même fait finiraient par diverger.
|
|
|
|
### Le critère d'un panneau
|
|
|
|
*Une série a sa place si elle **précède** un verdict, ou si elle n'en aura **jamais**.*
|
|
|
|
Ce qui bascule d'un coup appartient à Icinga ; ce qui dérive lentement n'a que le graphe
|
|
pour se faire voir. Une base qui passe de 20 à 60 connexions en trois semaines n'a rien
|
|
cassé — elle annonce la date où elle cassera.
|
|
|
|
### La `raison` devient la description du panneau
|
|
|
|
C'est le seul champ qui ne produit aucun pixel de graphe, et c'est le plus important.
|
|
Grafana l'affiche au survol du titre. Sans elle, celui qui regarde six mois plus tard voit
|
|
une courbe sans savoir ce qu'elle annonce.
|
|
|
|
### Agréger, toujours
|
|
|
|
node_exporter publie une série par interface, par point de montage, par cœur : **339
|
|
séries** pour le seul trafic réseau du site, mesuré le 2026-09-14. Un panneau qui les
|
|
montre toutes ne montre rien. Et se méfier de `min()` / `max()` : un seul montage
|
|
pathologique — `/var/lib/lxcfs`, qui rapporte toujours zéro — suffit à rendre un panneau
|
|
faux **pour toujours**, avec une courbe plate parfaitement lisible. Filtrer par **liste
|
|
blanche** : un montage inconnu manque au graphe, ce qui se voit, au lieu de l'écraser, ce
|
|
qui ne se voit pas.
|
|
|
|
### Ce que les gardes tiennent
|
|
|
|
**P77** exige de chaque panneau un titre, une expression, une unité et une raison — et que
|
|
l'unité figure dans la table de traduction de `serveur_grafana`. Une unité inventée ne
|
|
casse rien : le panneau retombe sur `short`, et un graphe d'octets gradué en unités brutes
|
|
reste parfaitement lisible et parfaitement faux.
|
|
|
|
Ce que P77 **ne** dit pas : si l'expression répond. Aucune lecture statique ne le dira. Un
|
|
panneau se prouve comme une sonde — en le regardant rendre des données, et en le notant au
|
|
CHANGELOG.
|
|
|
|
## Chaque sonde vient avec son contrôle négatif
|
|
|
|
Une sonde qu'on n'a jamais vue échouer n'est pas une sonde, c'est une habitude. Dix-neuf
|
|
voyants verts non éprouvés seraient un recul par rapport à deux voyants prouvés : ils
|
|
rassureraient.
|
|
|
|
Toute sonde ajoutée doit donc être accompagnée de la manière de la faire échouer
|
|
**pour de vrai**, et cette manière doit être rejouée au moins une fois, sur une machine
|
|
réelle. Le CHANGELOG en porte la trace.
|
|
|
|
**Et contre un état sain, tout autant.** La première version de la sonde du certificat a
|
|
rendu **14 machines sur 14 en CRITIQUE** — sur une PKI qui se portait très bien. Elle
|
|
utilisait `openssl verify -CAfile racine`, alors que nos certificats sont signés par un
|
|
*intermédiaire* que seul `step certificate verify` sait retrouver. Une alarme toujours
|
|
allumée ne vaut pas mieux qu'une alarme jamais allumée : elle apprend à ne plus regarder.
|
|
Une sonde se prouve donc **deux fois** — verte sur le sain, rouge sur le cassé.
|
|
|
|
## Combien de sondes : une par CAUSE D'ACTION
|
|
|
|
Ni une par rôle, ni une par vérification. **Une par geste que le verdict appelle.**
|
|
|
|
Les quatorze premières sondes agrègent chacune de deux à six chemins d'échec, et ce choix
|
|
avait été fait **sans être écrit** — d'où cette section, ajoutée le 2026-09-10 après la
|
|
question : *« est-ce parce qu'elles agrègent plusieurs vérifications ? »*
|
|
|
|
**Ce que coûte une agrégation abusive**, dans le modèle d'Icinga : un service = **un état,
|
|
un historique, un acquittement**. Fondre deux causes qui appellent des gestes différents,
|
|
c'est ne plus pouvoir acquitter l'une pendant que l'autre alerte — et lire comme *un
|
|
service instable* ce qui est en réalité *deux faits distincts qui alternent*.
|
|
|
|
**Ce que coûte l'excès inverse** : un voyant de plus est un voyant de moins regardé. Le
|
|
dépôt le répète assez — *une supervision creuse est pire qu'aucune*.
|
|
|
|
Le test pratique, à appliquer sans état d'âme :
|
|
|
|
> Les deux échecs appellent-ils **le même geste, de la même personne, dans le même délai** ?
|
|
> Si oui, une seule sonde, et le message nomme lequel des deux a parlé.
|
|
> Si non, deux sondes.
|
|
|
|
**Exemple d'agrégation légitime** — `moteur` : `icinga2` mort, `icingadb` mort, état figé en
|
|
base. Trois causes, un seul geste : *va regarder la supervision*. Le message dit laquelle.
|
|
|
|
**Exemple d'agrégation abusive** — `cache-apt` : « ne répond pas » arrête tout `apt` de
|
|
l'écosystème, « volume à 90 % » est un billet pour demain. Même personne, gestes et
|
|
**délais** différents : deux sondes.
|
|
|
|
## Une sonde doit pouvoir être mise en défaut *par paramètre*
|
|
|
|
Corollaire des deux règles précédentes, et c'est ce qui rend la discipline tenable à
|
|
l'échelle : une sonde dont on ne peut prouver le rouge qu'en **cassant un service** ne sera
|
|
prouvée qu'une fois, puis plus jamais.
|
|
|
|
Chaque sonde expose donc sa cible et ses seuils en variables du rôle. On la met en défaut
|
|
en lui donnant un port fermé, un nom qui n'existe pas, un seuil impossible — sur une
|
|
machine réelle, sans rien abîmer, et aussi souvent qu'on veut.
|
|
|
|
## Où vit la sonde : là où vit la vérité, pas là où vit le symptôme
|
|
|
|
*« La vérification suit la clé. »* Un nœud sait qu'il a **lancé** sa sauvegarde ; seul le
|
|
dépôt sait qu'elle a **abouti**. Un nœud sait qu'il **expose** ses métriques ; seul
|
|
Prometheus sait qu'il les **collecte**.
|
|
|
|
D'où un choix qui peut surprendre : *« ce nœud est-il bien collecté ? »* est une sonde de
|
|
**`serveur_prometheus`**, pas de `client_metrique`. Une seule sonde y voit les N nœuds à la
|
|
fois — et surtout, elle voit le cas **silencieux** : celui qui a cessé d'être collecté et
|
|
qui, par définition, ne peut pas s'en plaindre lui-même.
|
|
|
|
## Un contrôle négatif ne doit pas pouvoir abîmer
|
|
|
|
Éprouver la sonde du certificat, le 2026-09-09, a consisté à **remplacer le certificat
|
|
d'hôte** par un auto-signé. La sonde a bien viré au rouge — et le script de synchronisation
|
|
a propagé ce certificat vers `node_exporter`, dont la clé était restée l'ancienne :
|
|
|
|
```
|
|
failed to load X509KeyPair: tls: private key does not match public key
|
|
```
|
|
|
|
Un service réel est tombé pour éprouver une sonde. Le contrôle avait un **rayon d'action**
|
|
que je ne lui avais pas donné volontairement.
|
|
|
|
La règle qui en découle : un contrôle négatif se fait sur une **copie**, ou sur un chemin
|
|
que la sonde accepte en paramètre — jamais en substituant l'artefact que d'autres
|
|
consomment. Quand c'est impossible, on le fait sur la machine la moins critique, on
|
|
l'annonce, et on vérifie l'état des consommateurs **après**, pas seulement celui de la
|
|
sonde.
|