- gpu-fleet: Koby key updated (sk-lDTsWy7H3T...), config table (ornith service + masked services), benchmarks (prompt 209→532 tok/s), ROCm→Vulkan status - gpu-monitor: topology (sidecars :8090 removed, .15 via router), subsystem polling (router /health/unified as source of truth), execution steps, alert threshold (sidecar-unreachable downgraded from critical)
5.9 KiB
5.9 KiB
kind, name, description, agent
| kind | name | description | agent |
|---|---|---|---|
| responsibility | gpu-monitor | Comprehensive GPU fleet monitor — polls every subsystem (sidecars, router, LiteLLM, Strix Halo, dashboard) every 15s, renders a live HTML dashboard, checks alert thresholds, and exposes a JSON API for downstream consumers. | abiba |
Maintains
- gpu-fleet-data: { gpus: array, strix: object, router: object, litellm: object, summary: object, alerts: array } — Full fleet snapshot refreshed every 15s
- dashboard: live HTML at
/root/dashboard/gpu-fleet.html, served on port 9100 - gpu-data-api: JSON at
GET /gpu-dataon port 9100 - health-endpoint:
GET /healthon port 9100 → 200 if cache populated, 503 if warming up
GPU Fleet Topology
┌─────────────────────────────────────────────────────────┐
│ GPU Monitor Server (:9100) — 192.168.68.65 │
│ Polls every 15s, serves dashboard + JSON API │
└──┬──────────┬──────────┬────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────┐ ┌──────┐ ┌────────┐
│.8:8080│ │.110 │ │.116:80 │
│RTX3090│ │:8080 │ │nginx │
│gemma │ │RTX5070│ │router │
└──────┘ │qwen27B│ │LiteLLM │
└──────┘ │dashboard│
└────────┘
Note: JSON sidecar exporters at :8090 were never deployed on any
GPU host. Router falls back to GPU /health direct probe. Monitor
should use router /health/unified as source of truth for GPU status.
Strix Halo :8080 is firewalled to .116 only — monitor on .65 cannot
poll .15:8080 directly; must go through router on .116.
Subsystems Polled
| Subsystem | Endpoint | Frequency | Metrics |
|---|---|---|---|
| GPU Status (all, via router) | http://192.168.68.116/health/unified |
15s | models, CB, scores, GPU status (router probes each GPU /health directly) |
| Router (unified) | http://192.168.68.116/health/unified |
15s | models, CB, scores, GPU status |
| Router (basic) | http://192.168.68.116/health |
15s | basic aliveness |
| LiteLLM | http://192.168.68.116/litellm/health |
15s | proxy health, model count |
| Strix Halo | http://192.168.68.116/health/unified (router) |
15s | ornith status via router — cannot poll .15:8080 directly (firewalled to .116 only) |
| Dashboard | http://192.168.68.116/dashboard/ |
15s | harness-dashboard aliveness |
Alert Delivery
All alerts are sent to #agent-hub stream topics:
alerts-gpu— GPU fleet alerts (temp, VRAM, utilization)alerts-pm2— PM2 process health (restarts, crashes)alerts-infra— Infrastructure health (LiteLLM, Zulip, containers)
This replaces the previous DM-only delivery. All agents on the mesh can see and respond to alerts.
Alert Thresholds
| Metric | Warning | Critical |
|---|---|---|
| GPU Temp | >80°C | >90°C |
| VRAM Usage | >90% | >95% |
| GPU Util | >95% | >98% |
| Sidecar Unreachable | — | info (sidecars not deployed — use router /health/unified) |
| Model Down | — | critical (circuit breaker open) |
JSON API Response Schema (/gpu-data)
{
"gpus": [{ "name", "gpu_name", "temp_c", "vram_used_mb", "vram_total_mb",
"gpu_util_pct", "power_w", "power_limit_w", "fan_pct",
"models", "hostname", "active_requests", "health_score",
"circuit_open" }],
"strix": { "status", "cpu_load", "llama_health" },
"router": { "available_models", "circuit_breaker", "gpus", "scores",
"status", "redis", "_basic" },
"litellm": { ... },
"dashboard": { "reachable": bool },
"summary": { "fleet_status", "models_available", "models_total",
"circuit_breakers_open", "gpu_count", "gpu_errors",
"strix_running", "router_reachable", "litellm_reachable" },
"alerts": [{ "gpu", "metric", "level", "value", "threshold" }],
"updated": "ISO8601",
"monitor_version": "2.0.0"
}
Operations
list
curl http://localhost:9100/gpu-data | jq — Full fleet status
check-health
curl http://localhost:9100/health — Monitor self-check
view-dashboard
Open http://localhost:9100/ in browser — Live HTML dashboard
restart
pkill -f gpu-monitor-server.py
python3 /root/scripts/gpu-monitor-server.py &
Or via PM2: pm2 restart gpu-monitor
check-router
The router health is accessed through nginx on port 80 (NOT port 9000 directly).
curl http://192.168.68.116/health/unified — Router unified health via nginx proxy
curl http://192.168.68.116:9000/health/unified — ❌ WILL FAIL (port bound to 127.0.0.1 only)
Configuration Files
| File | Host | Purpose |
|---|---|---|
/root/scripts/gpu-monitor-server.py |
pi (.65) | Monitor server v2.0.0 |
/root/dashboard/gpu-fleet.html |
pi (.65) | Live HTML dashboard |
/etc/nginx/nginx.conf |
CT 116 | Routes /health/* → router |
Execution
- Poll router (every 15s): GET .116/health/unified — single source of truth for all GPU status (router probes each GPU /health directly via sidecar fallback)
- Poll router (every 15s): GET .116/health via nginx:80
- Poll LiteLLM (every 15s): GET .116/litellm/health via nginx:80
- Poll Strix (every 15s): via router /health/unified (cannot poll .15:8080 directly — firewalled to .116 only)
- Poll dashboard (every 15s): GET .116/dashboard/
- Check alerts: Compare metrics against thresholds
- Compute summary: Fleet-wide health aggregation
- Render dashboard: Generate HTML at /root/dashboard/gpu-fleet.html
- Serve API: HTTP server on port 9100
- Repeat every 15 seconds