Phase 5 : observabilité (réutilise le Prometheus/Grafana partagé)
- Pas de stack dédiée : une instance Prometheus/Grafana existe déjà sur ce serveur pour les 5 autres projets. En déployer une seconde aurait dupliqué de la RAM sur une machine à 3.7 Go partagée, sans bénéfice - même raisonnement que pour Caddy en Phase 2. - Scrape job tripoli_edge (172.17.0.1:9000, même passerelle docker0 que Caddy) ajouté à la config Prometheus existante. - Règles d'alerte : TripoliEdgeDown (up == 0), HostDiskAlmostFull (< 10% d'espace libre sur / - au niveau de la machine, pas seulement de ce projet, puisqu'il n'y a qu'un disque pour tout le monde). - Sonde blackbox externe ajoutée pour https://tripoli.cloud/healthz. - Dashboard Grafana versionné (uid tripoli-cloud-edge), importé via l'API (POST /api/dashboards/db) pour rester reproductible, pas construit à la main dans l'UI. - Vérifié : tous les targets Prometheus up (dont tripoli_edge et la sonde tripoli.cloud), les deux règles d'alerte chargées et évaluées, les requêtes du dashboard retournent de vraies valeurs. - Limite assumée : les alertes se déclenchent dans Prometheus mais ne sont pas encore routées par email (pas d'Alertmanager, pas de policy de notification Grafana dédiée) - documenté comme prochain pas, pas fait pour éviter de modifier la politique de notification globale de l'instance partagée sans plus de tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
991f4dd04f
commit
db306433d5
5 changed files with 199 additions and 1 deletions
|
|
@ -32,7 +32,7 @@ tenté, non simulé.
|
||||||
| `tripoli-edge` (Rust, Phase 2) | Fait et déployé en prod — `tripoli-edge/`, service systemd, derrière Caddy, vérifié via `https://tripoli.cloud/healthz` et `/metrics` |
|
| `tripoli-edge` (Rust, Phase 2) | Fait et déployé en prod — `tripoli-edge/`, service systemd, derrière Caddy, vérifié via `https://tripoli.cloud/healthz` et `/metrics` |
|
||||||
| `tripoli-api` (Rust, Phase 3) | Fait et déployé en prod — `tripoli-api/`, auth par session (Argon2), upload/download, PostgreSQL dédié (Docker), vérifié via `https://tripoli.cloud/api/...` |
|
| `tripoli-api` (Rust, Phase 3) | Fait et déployé en prod — `tripoli-api/`, auth par session (Argon2), upload/download, PostgreSQL dédié (Docker), vérifié via `https://tripoli.cloud/api/...` |
|
||||||
| `tripoli-netctl` (Rust, Phase 4) | Fait — `tripoli-netctl/`, labo pédagogique (netns + veth via `rtnetlink`), testé sur le serveur (création, ping traversant la veth, destruction propre), **volontairement pas branché sur le trafic de prod** |
|
| `tripoli-netctl` (Rust, Phase 4) | Fait — `tripoli-netctl/`, labo pédagogique (netns + veth via `rtnetlink`), testé sur le serveur (création, ping traversant la veth, destruction propre), **volontairement pas branché sur le trafic de prod** |
|
||||||
| Observabilité dédiée (Phase 5) | Pas commencé (une stack Prometheus/Grafana existe déjà sur le serveur, partagée avec les autres projets) |
|
| Observabilité (Phase 5) | Fait — pas de stack dédiée (réutilise le Prometheus/Grafana partagé existant), scrape tripoli-edge + alertes (down, disque) + dashboard versionné (`monitoring/`), vérifié via l'API Prometheus/Grafana |
|
||||||
| Bird/BGP (Phase 6, bonus) | Pas commencé |
|
| Bird/BGP (Phase 6, bonus) | Pas commencé |
|
||||||
|
|
||||||
## Dépôt
|
## Dépôt
|
||||||
|
|
|
||||||
52
monitoring/README.md
Normal file
52
monitoring/README.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Observabilité
|
||||||
|
|
||||||
|
Pas de Prometheus/Grafana dédiés à Tripoli Cloud : une instance de
|
||||||
|
chacun existe déjà sur ce serveur, partagée avec les 5 autres projets
|
||||||
|
qui y tournent. En déployer une seconde aurait dupliqué de la RAM sur
|
||||||
|
une machine à 3.7 Go déjà partagée, pour un bénéfice nul - même
|
||||||
|
raisonnement que pour Caddy en Phase 2.
|
||||||
|
|
||||||
|
## Ce qui a été ajouté à l'instance existante
|
||||||
|
|
||||||
|
- **Scrape job `tripoli_edge`** (`prometheus-scrape-snippet.yml`, appliqué
|
||||||
|
à `/opt/monitoring/prometheus/prometheus.yml` sur le serveur) :
|
||||||
|
`172.17.0.1:9000/metrics` - même passerelle docker0 que Caddy utilise
|
||||||
|
pour joindre tripoli-edge.
|
||||||
|
- **Règles d'alerte** (`tripoli-cloud-alerts.yml`, montée dans le
|
||||||
|
conteneur Prometheus) :
|
||||||
|
- `TripoliEdgeDown` : `up{job="tripoli_edge"} == 0` pendant 2 minutes.
|
||||||
|
- `HostDiskAlmostFull` : moins de 10% d'espace libre sur `/` pendant
|
||||||
|
10 minutes - une alerte au niveau de la machine, pas seulement de
|
||||||
|
Tripoli Cloud, puisqu'il n'y a qu'un seul disque pour tous les
|
||||||
|
projets hébergés.
|
||||||
|
- **Sonde blackbox externe** : `https://tripoli.cloud/healthz` ajoutée
|
||||||
|
à la liste existante du job `blackbox_http` (vérifie que le site
|
||||||
|
répond réellement depuis l'extérieur, pas seulement que Prometheus
|
||||||
|
arrive à le scraper en interne).
|
||||||
|
- **Dashboard Grafana** (`grafana-dashboard-tripoli-edge.json`,
|
||||||
|
`uid: tripoli-cloud-edge`) : état up/down, requêtes en cours, latence
|
||||||
|
moyenne, requêtes par classe de statut, et l'espace disque de l'hôte.
|
||||||
|
Importé via l'API Grafana (`POST /api/dashboards/db`), pas par copier-
|
||||||
|
coller dans l'UI - c'est ce qui permet de le garder versionné ici et
|
||||||
|
de le réimporter à l'identique si besoin.
|
||||||
|
|
||||||
|
## Ce qui n'a pas été fait
|
||||||
|
|
||||||
|
Les règles d'alerte **existent et se déclenchent** dans Prometheus (vérifiable
|
||||||
|
via `/api/v1/rules`), mais rien ne les **notifie** encore par email - pas
|
||||||
|
d'Alertmanager déployé, et pas de policy de notification Grafana
|
||||||
|
configurée pour ces alertes spécifiquement. Grafana a déjà un SMTP
|
||||||
|
fonctionnel (utilisé par d'autres projets sur cette instance) ; y
|
||||||
|
brancher les alertes de Tripoli Cloud est le prochain pas naturel, pas
|
||||||
|
fait dans cette passe pour éviter de modifier la politique de
|
||||||
|
notification globale de l'instance partagée sans plus de tests.
|
||||||
|
|
||||||
|
## Vérifié
|
||||||
|
|
||||||
|
```
|
||||||
|
$ curl .../api/v1/targets -> tripoli_edge: up, blackbox tripoli.cloud/healthz: up
|
||||||
|
$ curl .../api/v1/rules -> groupe "tripoli-cloud" : TripoliEdgeDown, HostDiskAlmostFull
|
||||||
|
$ curl .../api/v1/query?query=up{job="tripoli_edge"} -> 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Dashboard accessible sur `https://grafana.belkacemi.me/d/tripoli-cloud-edge/`.
|
||||||
102
monitoring/grafana-dashboard-tripoli-edge.json
Normal file
102
monitoring/grafana-dashboard-tripoli-edge.json
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
{
|
||||||
|
"title": "Tripoli Cloud - tripoli-edge",
|
||||||
|
"uid": "tripoli-cloud-edge",
|
||||||
|
"tags": ["tripoli-cloud"],
|
||||||
|
"timezone": "browser",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"version": 1,
|
||||||
|
"time": { "from": "now-6h", "to": "now" },
|
||||||
|
"refresh": "30s",
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "tripoli-edge up",
|
||||||
|
"type": "stat",
|
||||||
|
"gridPos": { "h": 4, "w": 4, "x": 0, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "cfxoej9jr3ncwb" },
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "up{job=\"tripoli_edge\"}", "refId": "A" }
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"mappings": [
|
||||||
|
{ "type": "value", "options": { "0": { "text": "DOWN", "color": "red" }, "1": { "text": "UP", "color": "green" } } }
|
||||||
|
],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }, { "color": "green", "value": 1 }] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"title": "Requêtes en cours (in-flight)",
|
||||||
|
"type": "stat",
|
||||||
|
"gridPos": { "h": 4, "w": 4, "x": 4, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "cfxoej9jr3ncwb" },
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "tripoli_edge_in_flight_requests", "refId": "A" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"title": "Latence moyenne (ms)",
|
||||||
|
"type": "stat",
|
||||||
|
"gridPos": { "h": 4, "w": 4, "x": 8, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "cfxoej9jr3ncwb" },
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "tripoli_edge_request_duration_ms_avg", "refId": "A" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"title": "Espace disque libre sur / (hôte partagé)",
|
||||||
|
"type": "gauge",
|
||||||
|
"gridPos": { "h": 4, "w": 4, "x": 12, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "cfxoej9jr3ncwb" },
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "100 * node_filesystem_avail_bytes{mountpoint=\"/\",fstype!=\"tmpfs\"} / node_filesystem_size_bytes{mountpoint=\"/\",fstype!=\"tmpfs\"}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"unit": "percent",
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{ "color": "red", "value": null },
|
||||||
|
{ "color": "orange", "value": 10 },
|
||||||
|
{ "color": "green", "value": 25 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"title": "Requêtes par classe de statut (par seconde)",
|
||||||
|
"type": "timeseries",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 4 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "cfxoej9jr3ncwb" },
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "rate(tripoli_edge_responses_total[5m])",
|
||||||
|
"legendFormat": "{{class}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"title": "Requêtes totales (par seconde)",
|
||||||
|
"type": "timeseries",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 4 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "cfxoej9jr3ncwb" },
|
||||||
|
"targets": [
|
||||||
|
{ "expr": "rate(tripoli_edge_requests_total[5m])", "legendFormat": "req/s", "refId": "A" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
19
monitoring/prometheus-scrape-snippet.yml
Normal file
19
monitoring/prometheus-scrape-snippet.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Bloc ajouté à /opt/monitoring/prometheus/prometheus.yml sur le serveur
|
||||||
|
# (fichier partagé avec les 5 autres projets surveillés par cette même
|
||||||
|
# instance - donc pas commité dans son intégralité ici, même logique
|
||||||
|
# que le Caddyfile de tripoli-edge).
|
||||||
|
#
|
||||||
|
# rule_files pointe vers tripoli-cloud-alerts.yml (ce dossier), monté
|
||||||
|
# dans le conteneur Prometheus via un ajout au docker-compose.yml
|
||||||
|
# existant.
|
||||||
|
|
||||||
|
rule_files:
|
||||||
|
- /etc/prometheus/tripoli-cloud-alerts.yml
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: tripoli_edge
|
||||||
|
static_configs:
|
||||||
|
- targets: ['172.17.0.1:9000'] # passerelle docker0, même pattern que Caddy -> tripoli-edge
|
||||||
|
|
||||||
|
# Ajouté à la liste existante du job blackbox_http :
|
||||||
|
# - https://tripoli.cloud/healthz
|
||||||
25
monitoring/tripoli-cloud-alerts.yml
Normal file
25
monitoring/tripoli-cloud-alerts.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
groups:
|
||||||
|
- name: tripoli-cloud
|
||||||
|
rules:
|
||||||
|
- alert: TripoliEdgeDown
|
||||||
|
expr: up{job="tripoli_edge"} == 0
|
||||||
|
for: 2m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
project: tripoli-cloud
|
||||||
|
annotations:
|
||||||
|
summary: "tripoli-edge est down"
|
||||||
|
description: "Prometheus n'arrive plus à scraper tripoli-edge (job tripoli_edge) depuis 2 minutes."
|
||||||
|
|
||||||
|
# Alerte au niveau de la machine, pas seulement de Tripoli Cloud :
|
||||||
|
# un seul disque, partagé avec 6 autres projets - un disque plein
|
||||||
|
# affecterait tout le monde, pas que ce projet.
|
||||||
|
- alert: HostDiskAlmostFull
|
||||||
|
expr: node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"} / node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"} < 0.10
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
project: tripoli-cloud
|
||||||
|
annotations:
|
||||||
|
summary: "Disque du serveur presque plein"
|
||||||
|
description: "Moins de 10% d'espace libre sur / depuis 10 minutes."
|
||||||
Loading…
Add table
Add a link
Reference in a new issue