# 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 ▼ llama-server-monitor (gpu-01:1237, CPU 14 threads) │ Répond dans les logs du service ▼ journalctl -u alertmanager-webhook "ask-agent response: SERVICE SAIN — aucune action requise" ``` **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 : ```json { "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 ```python # 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 ```bash # É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 ```bash # 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 ```bash # 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 ```bash # 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 : ```yaml 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 ```bash # 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) : ```bash 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` : ```python 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` : ```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). ```bash 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 : ```bash 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 : ```bash # 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 ```bash # 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. ```bash # 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) |