Funk-lab/admin/ia/alertmanager-webhook.md
ALI YESILKAYA 470c69881c
chore(gpu-01): retire les serveurs llama CPU system/monitor/dev (inutilisés) (#31)
Trois instances llama-server CPU manuelles (hors Ansible) tournaient sur gpu-01
sans servir : déjà orphelines de LiteLLM (alias absents de config.yaml, d'où le
bruit "Invalid model name"). Suppression complète :

gpu-01 (opérationnel, déjà fait) :
- systemctl disable --now + rm des units llama-server-{system,monitor,dev}
- ports firewall 1235/1236/1237 fermés

Repo :
- monitoring : scrape jobs (values.yaml) + alertes LlamaServer{System,Monitor}Down
  (alerts-ai.yaml) retirés → plus de "target down"/alertes fantômes ; panneaux de
  statut dashboard-infrastructure recyclés (system→llama-embed, monitor supprimé).
- docs admin/ + hermes-skills (souls funk-ai/brain, SKILL agent-delegation) mises à
  jour : inventaire modèles, profils Hermès system/monitor sans backend (à repointer
  sur qwen3-8b), litellm, ops, monitoring.

Les profils Hermès system/monitor existent toujours mais sans backend dédié.
Dashboards Grafana dashboard-ai (panneaux graphiques CPU) laissés tels quels
(cosmétique, séries vides, aucune alerte).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 13:25:50 +02:00

10 KiB

AlertManager Webhook — Pont Prometheus → Hermes

Service Python sur storage-01 qui reçoit les alertes Prometheus via AlertManager et les transmet au profil monitor de Hermes pour analyse IA.


Architecture et flux

Prometheus (k8s, namespace monitoring)
  │  Seuil dépassé (CPU, RAM, disk, pod crash...)
  ▼
AlertManager (k8s, namespace monitoring)
  │  POST http://192.168.10.1:9093/webhook
  │  Content-Type: application/json
  ▼
alertmanager-webhook.service (storage-01, port 9093)
  │  Répond 200 immédiatement
  │  Lance ask-agent en thread daemon
  ▼
ask-agent monitor "Alertes Prometheus reçues à HH:MM:SS : ..."
  │  POST http://127.0.0.1:4000/v1/chat/completions
  ▼
LiteLLM Proxy (:4000)
  │  modèle : qwen3-1.7b-monitor  ⚠️ backend retiré le 2026-06-20
  ▼
(ex-llama-server-monitor gpu-01:1237 — SUPPRIMÉ)
  │  Répond dans les logs du service
  ▼
journalctl -u alertmanager-webhook
  "ask-agent response: SERVICE SAIN — aucune action requise"

⚠️ 2026-06-20 : le serveur CPU monitor (:1237) a été supprimé. Le résumé d'alerte par ask-agent monitor ne fonctionne donc plus tel quel — pour le réactiver, ajouter dans LiteLLM un alias qwen3-1.7b-monitor (ou changer l'agent du webhook) pointant sur qwen3-8b (GPU).

Point clé : le webhook répond HTTP 200 immédiatement, avant d'appeler ask-agent. ask-agent tourne en arrière-plan (~20-60s) — AlertManager ne reste pas bloqué en attente.


Fonctionnement du webhook.py

1. Réception de l'alerte

AlertManager envoie un payload JSON de cette forme :

{
  "alerts": [
    {
      "status": "firing",
      "labels": {
        "alertname": "NodeHighCPU",
        "severity": "warning",
        "instance": "192.168.10.1:9100"
      },
      "annotations": {
        "summary": "CPU élevé sur storage-01",
        "description": "CPU > 90% depuis 5 minutes (valeur : 93.2%)"
      }
    }
  ]
}

2. Formatage du message

Chaque alerte est formatée en texte lisible :

[FIRING] NodeHighCPU — severity=warning instance=192.168.10.1:9100
CPU élevé sur storage-01
CPU > 90% depuis 5 minutes (valeur : 93.2%)

Le message final envoyé à Hermes :

Alertes Prometheus reçues à 21:35:03 :
[FIRING] NodeHighCPU — severity=warning instance=192.168.10.1:9100
...

Analyse ces alertes : sont-elles critiques ? Quelles actions recommandes-tu ?

3. Exécution asynchrone

# HTTP 200 envoyé immédiatement → AlertManager libéré
self.send_response(200)
self.end_headers()
self.wfile.write(b"ok")

# ask-agent lancé en thread daemon
threading.Thread(target=run_agent, daemon=True).start()

ask-agent est lancé avec NO_COLOR=1 et TERM=dumb pour éviter les codes ANSI dans les logs.

4. Réponse Hermes dans les logs

La réponse du modèle monitor apparaît dans journalctl ~20-60s après l'alerte :

INFO ask-agent response: SERVICE SAIN — CPU revenue à 45% après pic temporaire.
Aucune action requise. Surveiller sur 30 min.

Service systemd

# État
sudo systemctl status alertmanager-webhook

# Logs en direct
sudo journalctl -u alertmanager-webhook -f

# Logs récents
sudo journalctl -u alertmanager-webhook -n 50 --no-pager

# Redémarrer
sudo systemctl restart alertmanager-webhook

Le service tourne sous l'utilisateur alertmanager-webhook avec des permissions minimales.


Tester le webhook

Test curl manuel

# Depuis le poste perso ou storage-01
curl -s -X POST http://192.168.10.1:9093/webhook \
  -H "Content-Type: application/json" \
  -d '{
    "alerts": [{
      "status": "firing",
      "labels": {
        "alertname": "TestAlert",
        "severity": "warning",
        "instance": "storage-01:9100"
      },
      "annotations": {
        "summary": "Test alerte manuelle",
        "description": "Vérification du pipeline webhook → Hermes"
      }
    }]
  }'
# Réponse attendue : ok

# Suivre la réponse Hermes
ssh storage-01 "sudo journalctl -u alertmanager-webhook -f"
# Attendre ~30-60s → la réponse ask-agent apparaît

Vérifier la connexion AlertManager → webhook

# Alertes actives dans AlertManager
curl -s http://alertmanager.lab.local/api/v2/alerts | python3 -m json.tool

# Récepteurs configurés dans AlertManager
curl -s http://alertmanager.lab.local/api/v2/receivers | python3 -m json.tool

# Statut du webhook dans AlertManager (UI)
# http://alertmanager.lab.local/#/status → section "receivers"

Déclencher une vraie alerte

# Forcer une alerte Watchdog à passer par hermes-monitor (test de bout en bout)
# En modifiant temporairement la route dans values.yaml (à faire sur branche test)

# Ou créer un fichier flag d'alerte manuellement dans Prometheus
# (déconseillé en prod)

Configuration AlertManager

Le webhook est enregistré dans k8s/infra/monitoring/values.yaml comme receiver AlertManager :

alertmanager:
  config:
    route:
      receiver: 'null'        # receiver par défaut (Watchdog)
      routes:
        - matchers:
            - alertname = "Watchdog"
          receiver: 'null'
        - receiver: 'hermes-monitor'   # toutes les autres alertes → Hermes

    receivers:
      - name: 'null'
      - name: 'hermes-monitor'
        webhook_configs:
          - url: 'http://192.168.10.1:9093/webhook'
            send_resolved: true        # envoie aussi les alertes résolues

send_resolved: true — quand une alerte passe de firing à resolved, AlertManager envoie un nouveau payload avec "status": "resolved" — Hermes est informé de la résolution.


Déploiement et mise à jour

Fichiers

Fichier Emplacement Rôle
webhook.py ansible/roles/alertmanager_webhook/files/webhook.py Code source (versionné)
webhook.py (déployé) /opt/alertmanager-webhook/webhook.py (storage-01) Instance active
Rôle Ansible ansible/roles/alertmanager_webhook/ Déploiement, service systemd

Redéployer après modification

# Depuis le poste perso
scp ansible/roles/alertmanager_webhook/files/webhook.py \
    storage-01:/tmp/webhook.py

ssh storage-01 "sudo cp /tmp/webhook.py /opt/alertmanager-webhook/webhook.py \
    && sudo systemctl restart alertmanager-webhook \
    && sudo systemctl status alertmanager-webhook --no-pager"

Ou via Ansible (une fois le rôle hermes_user en place) :

cd /mnt/nvme0n1/nvme0n1p3/Projets/lab
.venv/bin/ansible-playbook -i ansible/inventory.yml ansible/playbooks/site.yml \
    --tags alertmanager_webhook

Modifier le message envoyé à Hermes

Le prompt est construit dans webhook.py, fonction do_POST :

message = "\n".join(lines) + "\n\nAnalyse ces alertes : sont-elles critiques ? Quelles actions recommandes-tu ?"

Pour personnaliser l'instruction donnée à Hermes, modifier cette ligne et redéployer.


Ajouter un filtre d'alertes

Pour que certaines alertes n'arrivent pas à Hermes (trop bruyantes), ajouter une route spécifique avant hermes-monitor dans values.yaml :

routes:
  - matchers:
      - alertname = "Watchdog"
    receiver: 'null'
  - matchers:
      - severity = "info"       # silencer les alertes info
    receiver: 'null'
  - receiver: 'hermes-monitor'  # tout le reste → Hermes

git push → ArgoCD applique en ~3 minutes.


Dépannage

BrokenPipeError dans les logs

Symptôme : BrokenPipeError: [Errno 32] Broken pipe dans journalctl.

Cause : ancienne version du webhook qui envoyait le HTTP 200 après ask-agent (bloquant ~54s → AlertManager fermait la connexion avant).

Solution : vérifier que le webhook.py déployé correspond bien à la version actuelle (200 envoyé immédiatement, ask-agent en thread).

ssh storage-01 "grep -n 'send_response\|threading' /opt/alertmanager-webhook/webhook.py"
# Doit afficher send_response AVANT threading.Thread

Codes ANSI dans les logs (output illisible)

Symptôme : ask-agent response: 790G'*%G+>,<... (caractères parasites).

Cause : ask-agent utilise des couleurs terminal capturées brutes par subprocess.

Solution : vérifier que NO_COLOR=1 est passé à subprocess :

ssh storage-01 "grep 'NO_COLOR' /opt/alertmanager-webhook/webhook.py"
# Doit afficher : "NO_COLOR": "1"

Pas de réponse Hermes dans les logs (timeout)

ask-agent monitor a expiré après 120s. Causes possibles :

# LiteLLM répond ?
ssh storage-01 "curl -s http://localhost:4000/health \
    -H 'Authorization: Bearer lm-studio'"

# llama-server-monitor tourne ?
ssh gpu-01 "systemctl status llama-server-monitor --no-pager"

# Logs ask-agent (stderr capturé)
ssh storage-01 "sudo journalctl -u alertmanager-webhook -n 30 --no-pager" \
    | grep -E "stderr|error|timeout"

Le webhook ne reçoit pas les alertes AlertManager

# 1. Le service écoute sur le bon port ?
ssh storage-01 "ss -tlnp | grep 9093"

# 2. nftables autorise le pod CIDR ?
ssh storage-01 "sudo nft list ruleset | grep 9093"
# Doit contenir : 10.42.0.0/16

# 3. AlertManager atteint storage-01 ?
kubectl logs -n monitoring \
    alertmanager-kube-prometheus-stack-alertmanager-0 \
    | grep -i webhook | tail -20

Hermes répond mais l'analyse est mauvaise

Le profil monitor utilise Qwen3-1.7B (petit modèle CPU). Pour des analyses plus poussées, modifier ask-agent pour utiliser brain (Claude Sonnet) sur les alertes critiques — ou ajuster le SOUL.md du profil monitor.

# SOUL.md du profil monitor
ssh storage-01 "cat /srv/data/hermes/profiles/monitor/SOUL.md"

Points d'attention

Sujet Détail
Réponse asynchrone Hermes répond dans les logs 20-60s après l'alerte — pas de retour vers AlertManager
Alertes résolues send_resolved: true — Hermes reçoit aussi les résolutions, utile pour confirmer le retour à la normale
Port 9093 nftables doit autoriser 10.42.0.0/16 (pod CIDR) ET 192.168.10.0/24 sur ce port
Modèle monitor Qwen3-1.7B CPU (~21 tok/s) — rapide mais limité. Convient pour des verdicts courts (OK/WARNING/ERROR)
Pas de stockage Les analyses Hermes ne sont pas persistées — elles apparaissent uniquement dans journalctl
Watchdog L'alerte Watchdog (heartbeat interne Prometheus) est routée vers null — ne pas la router vers Hermes (spam toutes les minutes)