# Runbook — Supervision et alertes ## Ce qui tourne | Service | Adresse (interne, `10.10.0.1`) | Déployé par | |---|---|---| | Prometheus | `:9091` | Kolla (`enable_prometheus: "yes"`) | | Alertmanager | `:9093` | Kolla | | Grafana | `:3000` | Kolla | | node_exporter | `:9100` | Kolla (+ collecteur textfile, rôle `supervision`) | | openstack-exporter | `:9198` | Kolla | | cAdvisor, libvirt/mysqld/memcached exporters | ports divers | Kolla | | Relais Alertmanager → ntfy | `127.0.0.1:9099` | rôle Ansible `supervision` | | Uptime Kuma | `127.0.0.1:3001` | rôle Ansible `supervision` (conteneur Docker en réseau hôte, écoute forcée sur 127.0.0.1 par `UPTIME_KUMA_HOST`) | Rien de tout cela n'est exposé sur `eno1` (vérifié : seuls 22/80/443 répondent depuis Internet). **Tant qu'il n'y a pas de domaine, l'accès se fait par tunnel SSH.** ## Accéder aux interfaces (tunnel SSH depuis le Mac) ``` ssh -L 3000:10.10.0.1:3000 -L 9091:10.10.0.1:9091 -L 9093:10.10.0.1:9093 -L 3001:127.0.0.1:3001 paillasse ``` Puis dans le navigateur : `http://localhost:3000` (Grafana), `:9091` (Prometheus), `:9093` (Alertmanager), `:3001` (Uptime Kuma — premier accès : créer le compte admin toi-même, c'est une étape interactive). Piège (2026-10-09) : Docker tourne avec `"bridge": "none"` et `"iptables": false` (étape 5). Un conteneur sur le pont par défaut n'a donc pas de réseau, et son `ports:` n'est jamais publié — le conteneur reste « healthy » (son contrôle de santé interroge son propre localhost) mais rien n'écoute sur l'hôte. Vérifier avec `sudo ss -tlnp | grep 3001` : attendu `127.0.0.1:3001` seulement. Identifiants Grafana/Prometheus/Alertmanager : utilisateur `admin`, mot de passe dans `/etc/kolla/passwords.yml` sur le serveur (`grafana_admin_password`, `prometheus_password`, `prometheus_alertmanager_password`) — jamais affichés ici, à lire toi-même : ``` sudo grep '^grafana_admin_password:' /etc/kolla/passwords.yml ``` ## Alertes en place Fichier `kolla/config/prometheus/alertes.rules` (poussé par le rôle `supervision`, chargé par Prometheus) : | Alerte | Condition | Sévérité | |---|---|---| | `DisqueSature` | occupation de `/` > 80 % pendant 5 min | avertissement | | `MemoireSaturee` | RAM utilisée > 90 % pendant 5 min | avertissement | | `ServiceOpenStackArrete` | un agent Nova ou Neutron à l'état différent de `up` pendant 2 min | critique | | `SauvegardeAncienne` | dernière sauvegarde Dedibackup réussie il y a plus de 26 h | critique | `SauvegardeAncienne` dépend d'une métrique maison (`syllabus_derniere_sauvegarde_reussie_timestamp`), écrite par `sauvegarde-dedibackup.sh` dans `/var/lib/node_exporter/textfile/sauvegarde.prom` à chaque sauvegarde réussie (collecteur "textfile" de node_exporter). **Limite connue, assumée pour l'instant : pas d'alerte « serveur injoignable ».** Toute la chaîne (Prometheus, Alertmanager, le relais, ntfy) tourne sur le même serveur que ce qu'elle surveille : si le serveur tombe complètement, rien ne peut prévenir personne. C'est exactement pour ça que CLAUDE.md prévoyait à l'origine une sonde **hors du serveur** (un petit Hetzner CX23). Dans ce déploiement (un seul serveur Scaleway), ce n'est pas fait — à décider avec Adam s'il veut un jour un point de supervision externe. ## Le relais Alertmanager → ntfy Alertmanager ne sait pas parler nativement le format ntfy. Un petit service Python (`/usr/local/sbin/alertmanager-ntfy.py`, service systemd `alertmanager-ntfy`, écoute uniquement sur `127.0.0.1:9099`) reçoit le webhook JSON standard d'Alertmanager et le retraduit en notification ntfy. - L'URL ntfy (avec le topic) est lue à chaque notification depuis `/root/.alertes-webhook` (`600 root:root`) — jamais mise en cache, jamais journalisée, jamais dans Git. - Configuration Alertmanager : `kolla/config/prometheus/prometheus-alertmanager.yml` (receveur unique `ntfy`, webhook vers le relais local). ### Déclencher une alerte de test Sans toucher à rien de réel sur le serveur, via l'API d'Alertmanager : ``` ssh paillasse sudo bash -c ' PASS=$(awk -F": " "/^prometheus_alertmanager_password:/{print \$2}" /etc/kolla/passwords.yml) MAINTENANT=$(date -u +%Y-%m-%dT%H:%M:%S.000Z) FIN=$(date -u -d "+5 minutes" +%Y-%m-%dT%H:%M:%S.000Z) curl -s --user "admin:$PASS" -XPOST http://10.10.0.1:9093/api/v2/alerts -H "Content-Type: application/json" -d "[{ \"labels\": {\"alertname\": \"TestManuel\"}, \"annotations\": {\"description\": \"Test manuel.\"}, \"startsAt\": \"$MAINTENANT\", \"endsAt\": \"$FIN\" }]" unset PASS ' ``` **Vérifié le 2026-10-07 : alerte de test reçue par Adam sur ntfy**, par ce mécanisme et en testant aussi le relais directement (`curl -XPOST http://127.0.0.1:9099/alertmanager ...`). ## Après tout changement à `kolla/config/prometheus/*` ou `kolla/globals.yml` ``` cd ansible && script -q /dev/null ansible-playbook kolla.yml -i inventory.ini cd ansible && script -q /dev/null ansible-playbook supervision.yml -i inventory.ini ssh paillasse "sudo -i bash -c 'export PATH=/opt/kolla-venv/bin:\$PATH; kolla-ansible reconfigure -i /etc/kolla/all-in-one --tags prometheus'" ``` **Piège vécu le 2026-10-07 :** modifier `kolla/globals.yml` ou un fichier de `kolla/config/` dans le dépôt ne suffit pas : il faut d'abord rejouer `kolla.yml`/`supervision.yml` pour le copier sur le serveur, **puis** `kolla-ansible reconfigure`. Oublier la première étape fait tourner `reconfigure` sur l'ancienne config, sans erreur visible. ## Mettre à jour l'image Uptime Kuma Figée par **digest**, pas par le tag flottant `louislam/uptime-kuma:1` (qui peut changer de contenu à tout moment, sans avertissement ni changelog attaché au tag) : `supervision_image_uptime_kuma` (`ansible/roles/supervision/defaults/main.yml`). Version actuelle : 1.23.17, sous son propre tag versionné depuis le 2026-10-14 (avant cette date, le digest figé était celui du tag flottant `:1` au même contenu — build différent, avec un script d'avertissement sans impact). 1. Choisir la version visée sur (préférer un tag de version exacte, ex. `1.23.18`, jamais `1` ou `latest`) et lire les notes de version . 2. Trouver son digest exact (pas celui d'un tag flottant) : ``` curl -s "https://hub.docker.com/v2/namespaces/louislam/repositories/uptime-kuma/tags/1.23.18" \ | python3 -c "import json,sys; print(json.load(sys.stdin)['digest'])" ``` 3. Mettre à jour `supervision_image_uptime_kuma` dans `defaults/main.yml` (`louislam/uptime-kuma@sha256:...`) et le commentaire de version. 4. `cd ansible && script -q /dev/null ansible-playbook supervision.yml -i inventory.ini` (tire la nouvelle image, recrée le conteneur ; le volume `uptime-kuma-data` est conservé, rien n'est perdu). 5. Vérifier : `ss -tlnp | grep 3001` (toujours 127.0.0.1 seulement), rouvrir le tunnel SSH, se connecter, vérifier que les sondes existantes sont toujours là et actives. Rejouer `visio-e2e.mjs`/`parcours-lab.py` n'est pas nécessaire (Kuma ne fait pas partie du chemin critique d'un lab).