đ Monitoring de la stack d'infĂ©rence
Architecture de monitoring
flowchart TD
subgraph Sources["Sources de métriques"]
A["vLLM /metrics"]
B["nvidia-smi"] --> C["nvidia-dcgm-exporter"]
D["OS"] --> E["node-exporter"]
end
Sources --> P["Prometheus\n(scrape + store)"]
P --> G["Grafana\n(dashboards + alertes)"]
1. Stack Docker Compose complĂšte
services:
prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=30d' ports: - "9090:9090" restart: unless-stopped
grafana: image: grafana/grafana-oss:latest container_name: grafana volumes: - grafana_data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=changeme - GF_USERS_ALLOW_SIGN_UP=false ports: - "3000:3000" restart: unless-stopped depends_on: - prometheus
nvidia-dcgm-exporter: image: nvcr.io/nvidia/k8s/dcgm-exporter:latest container_name: dcgm-exporter runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all ports: - "9400:9400" restart: unless-stopped cap_add: - SYS_ADMIN
node-exporter: image: prom/node-exporter:latest container_name: node-exporter volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' ports: - "9100:9100" restart: unless-stopped
volumes: prometheus_data: grafana_data:docker compose -f docker-compose.monitoring.yml up -d2. Configuration Prometheus
global: scrape_interval: 15s evaluation_interval: 15s
scrape_configs:
- job_name: 'vllm' static_configs: - targets: ['host.docker.internal:8000'] # adapter si vLLM sur autre machine metrics_path: '/metrics'
- job_name: 'nvidia-gpu' static_configs: - targets: ['dcgm-exporter:9400']
- job_name: 'node' static_configs: - targets: ['node-exporter:9100']
# Si Ollama (pas de /metrics natif â utiliser l'exporter communautaire) - job_name: 'ollama' static_configs: - targets: ['host.docker.internal:9462'] # port de l'exporter ollama3. MĂ©triques vLLM â les essentielles
vLLM expose ses métriques sur GET /metrics1. Voici celles à surveiller en priorité :
DĂ©bit et files dâattente
| MĂ©trique | Description | Seuil dâalerte |
|---|---|---|
vllm:num_requests_running | RequĂȘtes en cours de traitement | > 80% de --max-num-seqs |
vllm:num_requests_waiting | RequĂȘtes en file dâattente | > 0 pendant > 30 s |
vllm:avg_generation_throughput_toks_per_s | Débit moyen tokens/s | < seuil défini par usage |
vllm:prompt_tokens_total | Tokens de prompt traitĂ©s (cumulĂ©) | â (trend) |
vllm:generation_tokens_total | Tokens gĂ©nĂ©rĂ©s (cumulĂ©) | â (trend) |
KV Cache
| MĂ©trique | Description | Seuil dâalerte |
|---|---|---|
vllm:gpu_cache_usage_perc | % KV Cache occupé | > 90% |
vllm:cpu_cache_usage_perc | % KV Cache swap CPU | > 0 (indique du swap) |
vllm:num_preemptions_total | RequĂȘtes prĂ©emptĂ©es (KV Cache plein) | > 0 rĂ©gulier |
Latences
| Métrique | Description |
|---|---|
vllm:time_to_first_token_seconds | Distribution TTFT par requĂȘte |
vllm:time_per_output_token_seconds | Latence par token généré |
vllm:e2e_request_latency_seconds | Latence end-to-end |
4. Métriques GPU (DCGM Exporter)
NVIDIA DCGM Exporter expose des métriques GPU détaillées3 :
| MĂ©trique DCGM | Description | Seuil dâalerte |
|---|---|---|
DCGM_FI_DEV_GPU_UTIL | Utilisation GPU (%) | < 10% pendant > 5 min (gaspillage) |
DCGM_FI_DEV_MEM_COPY_UTIL | Utilisation bus mémoire (%) | > 90% soutenu |
DCGM_FI_DEV_FB_USED | VRAM utilisée (MiB) | > 95% de la VRAM totale |
DCGM_FI_DEV_GPU_TEMP | Température GPU (°C) | > 83°C (throttling probable) |
DCGM_FI_DEV_POWER_USAGE | Consommation (W) | > TDP déclaré |
DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL | DĂ©bit NVLink (Go/s) | â (trend sur clusters) |
RequĂȘte Prometheus â VRAM utilisĂ©e par GPU
DCGM_FI_DEV_FB_USED{gpu=~".*"}5. Dashboards Grafana recommandés
Import depuis Grafana.com
- Ouvrir Grafana â Dashboards â Import
- Entrer lâID du dashboard :
| Dashboard | ID Grafana | Usage |
|---|---|---|
| NVIDIA DCGM Exporter | 12239 | GPU utilization, mémoire, température4 |
| Node Exporter Full | 1860 | CPU, RAM, réseau, disque hÎte5 |
Panels essentiels Ă construire manuellement
Panel âDĂ©bit tokens/sâ :
rate(vllm:generation_tokens_total[1m])Panel âKV Cache %â :
vllm:gpu_cache_usage_perc * 100Panel âFile dâattenteâ :
vllm:num_requests_waitingPanel âTTFT P95â (95e percentile) :
histogram_quantile(0.95, rate(vllm:time_to_first_token_seconds_bucket[5m]))6. Alertes Prometheus
# alerts.yml â Ă rĂ©fĂ©rencer dans prometheus.yml sous rule_files:groups: - name: inference-alerts rules:
- alert: VLLMKVCacheHigh expr: vllm:gpu_cache_usage_perc > 0.90 for: 2m labels: severity: warning annotations: summary: "KV Cache vLLM > 90%" description: "Le KV Cache est à {{ $value | humanizePercentage }}. Risque de swap ou de préemption."
- alert: VLLMRequestQueueBacklog expr: vllm:num_requests_waiting > 0 for: 1m labels: severity: warning annotations: summary: "File d'attente vLLM non vide" description: "{{ $value }} requĂȘtes en attente depuis plus d'1 minute."
- alert: GPUTemperatureHigh expr: DCGM_FI_DEV_GPU_TEMP > 83 for: 5m labels: severity: critical annotations: summary: "GPU {{ $labels.gpu }} en surchauffe" description: "TempĂ©rature GPU Ă {{ $value }}°C â throttling probable."
- alert: VRAMAlmostFull expr: (DCGM_FI_DEV_FB_USED / DCGM_FI_DEV_FB_TOTAL) > 0.95 for: 2m labels: severity: critical annotations: summary: "VRAM GPU {{ $labels.gpu }} critique" description: "{{ $value | humanizePercentage }} de VRAM utilisée."Pour activer les alertes dans Prometheus :
# prometheus.yml â ajouterrule_files: - "alerts.yml"
alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] # si Alertmanager déployé7. Monitoring Ollama (sans Prometheus natif)
Si vous utilisez Ollama, quelques commandes de monitoring immédiat :
# ModÚles chargés et VRAM occupéeollama ps
# Logs en temps réel (incluent les durées de génération)ollama logs -f
# MĂ©triques dans la rĂ©ponse API (durĂ©es en nanosecondes)curl -s http://localhost:11434/api/generate \ -d '{"model":"llama3.2","prompt":"test","stream":false}' \ | python3 -c "import sys, jsonr = json.load(sys.stdin)print(f'TTFT: {r[\"prompt_eval_duration\"]/1e9:.2f}s')print(f'GĂ©nĂ©ration: {r[\"eval_duration\"]/1e9:.2f}s')print(f'DĂ©bit: {r[\"eval_count\"]/(r[\"eval_duration\"]/1e9):.1f} tok/s')"8. Traces vs. MĂ©triques â OpenTelemetry pour les stacks agentiques
Prometheus et Grafana rĂ©pondent Ă la question âLe serveur va-t-il bien ?â. Ils ne rĂ©pondent pas Ă âPourquoi cette requĂȘte a-t-elle pris 30 secondes ?â.
Le problĂšme agentique
Dans un pipeline RAG ou multi-agents, une requĂȘte traverse plusieurs services avant de produire une rĂ©ponse. Si un utilisateur se plaint dâune latence de 30s, Grafana vous dira que le GPU Ă©tait Ă 70% dâutilisation â ce qui ne suffit pas Ă diagnostiquer la cause. Ce quâil faut, câest la trace de la requĂȘte complĂšte :
RequĂȘte utilisateur (30s total)âââ VectorDB Qdrant â 4s (recherche sĂ©mantique)âââ Agent routing â 2s (choix de l'outil)âââ SearXNG web search â 20s (timeout rĂ©seau â ïž)âââ LLM generation â 4s (200 tokens @ 50 tok/s)Sans traces, lâingĂ©nieur cherche dans les logs de chaque service sĂ©parĂ©ment. Avec des traces OpenTelemetry, la requĂȘte complĂšte est visualisĂ©e en un seul waterfall dans un outil dĂ©diĂ©.
OpenTelemetry (OTEL) â intĂ©gration native vLLM et LiteLLM
LiteLLM et vLLM supportent OpenTelemetry nativement67 :
# vLLM â activer OTEL (exporte vers un collector local)vllm serve meta-llama/Llama-3.1-70B-Instruct \ --otlp-traces-endpoint http://localhost:4317
# LiteLLM â activer dans litellm_config.yamlgeneral_settings: otel: true otel_endpoint: http://localhost:4317 # OTLP gRPCStack dâobservabilitĂ© LLM recommandĂ©e
Pour une infrastructure on-premise souveraine, deux options :
| Outil | Type | Points forts | Déploiement |
|---|---|---|---|
| Langfuse (self-hosted) | Traces + éval LLM | Interface dédiée LLM, coûts par token, évaluation qualité | Docker Compose6 |
| Jaeger | Traces distribuées | Standard CNCF, léger, intégré Kubernetes | Docker jaegertracing/all-in-one |
| Arize Phoenix | Traces + debug agent | Spécialisé agents/RAG, gratuit et open-source | pip install arize-phoenix7 |
Stack minimale recommandée pour un agent custodien :
# docker-compose.yml â ajouter au stack existantlangfuse: image: langfuse/langfuse:latest ports: - "3001:3000" environment: DATABASE_URL: "postgresql://langfuse:langfuse@postgres:5432/langfuse" NEXTAUTH_SECRET: "votre-secret" SALT: "votre-salt"
otel-collector: image: otel/opentelemetry-collector-contrib:latest volumes: - ./otel-config.yaml:/etc/otel-config.yaml command: ["--config=/etc/otel-config.yaml"] ports: - "4317:4317" # OTLP gRPC - "4318:4318" # OTLP HTTPSauvegarde de lâĂ©tat applicatif (DRP)
Le monitoring dĂ©tecte les pannes â mais sans sauvegarde, le redĂ©marrage aprĂšs incident peut prendre des heures ou perdre des donnĂ©es. Voici les Ă©tats Ă protĂ©ger dans une stack dâinfĂ©rence locale.
Ce quâil faut sauvegarder
| Composant | Données critiques | Méthode recommandée |
|---|---|---|
| Qdrant (base vectorielle) | Collections + snapshots dâindex | POST /collections/{name}/snapshots â snapshot local ; copier vers stockage externe |
| Milvus (base vectorielle) | Collections, segments, métadonnées | Milvus Backup CLI (milvus-backup create) vers S3 local ou NAS |
| SQLite (Memory Tree, historiques) | Fichier .db | cp avec rotation quotidienne ou sqlite3 .backup en chaud |
| Configuration vLLM / Ollama | config.yaml, scripts de dĂ©marrage | VersionnĂ© dans Git â dĂ©jĂ couvert |
| ModÚles et adaptateurs | Poids GGUF, LoRA fine-tunés | Poids de base = immuables (retélécharger) ; adaptateurs fine-tunés = sauvegarder sur NAS |
Fréquences suggérées
Qdrant snapshot â quotidien (cron 02:00), conservation 7 joursMilvus backup â quotidien (cron 03:00), conservation 7 joursSQLite Memory Tree â toutes les heures (si Ă©criture frĂ©quente), sinon quotidienAdaptateurs LoRA â Ă chaque fin d'entraĂźnementExemple de snapshot Qdrant (curl)
# Créer un snapshotcurl -X POST http://localhost:6333/collections/my_collection/snapshots
# Lister les snapshots disponiblescurl http://localhost:6333/collections/my_collection/snapshots
# Copier vers stockage externe (exemple NAS monté)cp /qdrant/snapshots/my_collection/*.snapshot /mnt/backup/qdrant/Procédure de reprise (RTO indicatif)
- RedĂ©marrer le conteneur vLLM ou Ollama â rechargement des poids depuis SSD (~15â120 s selon modĂšle)
- Restaurer Qdrant depuis le dernier snapshot â
PUT /collections/{name}/snapshots/recover - Restaurer SQLite â copier le fichier
.dbde sauvegarde Ă la place du fichier corrompu - VĂ©rifier lâendpoint de santĂ© (
/healthou/v1/models)
Voir aussi
- âïž Configurer vLLM multi-GPU â endpoint
/metricset paramĂštres - đ„ïž ScĂ©nario C â monitoring Exo/Thunderbolt
- đ ScĂ©nario D â monitoring datacenter RoCE
Sources et Références
Footnotes
-
vLLM Project, Production Metrics (endpoint
/metrics, liste complĂšte des mĂ©triques Prometheus exposĂ©es, histogrammes de latence). https://docs.vllm.ai/en/stable/serving/metrics.html â© â©2 -
vLLM Project, Engine Arguments â
gpu-memory-utilization(comportement swap KV Cache CPU, impact performances). https://docs.vllm.ai/en/stable/serving/engine_args.html â© -
NVIDIA, DCGM Exporter â Metrics Reference (liste des mĂ©triques DCGM_FI_DEV_*, GPU utilization, memory, tempĂ©rature, NVLink). https://github.com/NVIDIA/dcgm-exporter â©
-
Grafana Labs, NVIDIA DCGM Exporter Dashboard (ID 12239, GPU metrics visualization). https://grafana.com/grafana/dashboards/12239 â©
-
Grafana Labs, Node Exporter Full Dashboard (ID 1860, system metrics â CPU, memory, disk, network). https://grafana.com/grafana/dashboards/1860 â©
-
Langfuse, Self-Hosting Guide & LiteLLM Integration (Docker Compose, OTEL ingestion, LLM observability). https://langfuse.com/docs/deployment/self-host â© â©2
-
Arize AI, Arize Phoenix â Open-source LLM Observability (traces agentiques, RAG debugging, OTEL-compatible). https://docs.arize.com/phoenix â© â©2