mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-09 01:34:41 +02:00
BrokenPipeError corrigé : send_response(200) envoyé avant subprocess. ask-agent lancé en threading.Thread daemon — AlertManager n'attend plus. NO_COLOR=1 + TERM=dumb pour éviter les codes ANSI dans les logs. docs: alertmanager-webhook.md — architecture, flux, test, dépannage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
362 lines
10 KiB
Markdown
362 lines
10 KiB
Markdown
# 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) |
|