L'observabilité est la colonne vertébrale des systèmes distribués modernes, mais elle a un coût important en performance : la cardinalité. Alors que les développeurs ajoutent des étiquettes aux métriques pour permettre des requêtes granulaires, nous créons souvent involontairement des explosions combinatoires dans nos données de séries temporelles. Cette « explosion de cardinalité » peut entraîner des erreurs de mémoire insuffisante (OOM), des goulots d'étranglement en E/S disque et des coûts d'infrastructure exorbitants. Dans cet article, nous explorerons des stratégies pour optimiser l'ingestion de séries temporelles à haute cardinalité, en comparant l'architecture native de Prometheus à l'efficacité cloud-native de VictoriaMetrics.
Comprendre le piège de la cardinalité
La cardinalité désigne le nombre de séries temporelles uniques générées par une combinaison de noms de métriques et de paires d'étiquettes. Par exemple, exposer une métrique http_requests_total avec une étiquette user_id est dangereux. Si vous avez 1 million d'utilisateurs actifs, vous créez instantanément 1 million de séries temporelles uniques. Prometheus stocke toutes les données localement sur le disque dans un format optimisé pour les requêtes par plage de temps, mais pas pour les combinaisons massives d'étiquettes. Lorsque les taux d'ingestion augmentent ou que le nombre de valeurs d'étiquettes uniques devient trop important, le composant TSDB (Time Series Database) a du mal à gérer les segments du journal de pré-écriture (WAL) et les fichiers mappés en mémoire.
Stratégie 1 : Filtrage préventif des étiquettes dans Prometheus
La première ligne de défense consiste à empêcher les étiquettes à haute cardinalité d'entrer dans le système. Dans Prometheus, vous pouvez utiliser metric_relabel_configs dans votre configuration de scrape pour supprimer les métriques ou les étiquettes qui violent vos règles de cardinalité.
Par exemple, si vous scrapez accidentellement un point de terminaison qui expose des données personnelles (PII) comme les identifiants de session, vous devez supprimer cette étiquette avant le stockage. Voici comment configurer une règle de suppression dans votre fichier prometheus.yml :
scrape_configs:
- job_name: 'web_app'
metrics_path: '/metrics'
relabel_configs:
- source_labels: [__name__]
regex: 'my_app_(.+)'
action: drop
metric_relabel_configs:
# Supprimer les métriques avec des étiquettes à haute cardinalité comme session_id
- source_labels: [session_id]
regex: '.+'
action: drop
Cette approche garantit que la base de données n'alloue jamais de mémoire pour ces séries. Cependant, il s'agit d'une approche « avec perte » ; vous perdez la capacité de requêter ces séries spécifiques. Assurez-vous de ne supprimer que les étiquettes qui ne sont pas nécessaires à vos besoins de surveillance.
Stratégie 2 : Tirer parti de VictoriaMetrics pour une ingestion à grande échelle
Alors que Prometheus est excellent pour la surveillance à court terme et à haute résolution, il n'a pas été conçu pour le stockage à long terme de données à haute cardinalité. C'est là que VictoriaMetrics brille. Conçu spécifiquement pour répondre aux limites de Prometheus à grande échelle, VictoriaMetrics utilise un moteur de stockage et des algorithmes de compression plus efficaces.
VictoriaMetrics prend en charge "VMAlert" pour l'alerte et offre un protocole d'écriture distante compatible avec Prometheus. L'un de ses avantages clés est sa capacité à gérer de hauts taux d'ingestion sans nécessiter de partitionnement (sharding) ou de gestion de cluster complexe pour les déploiements sur nœud unique. Il utilise une architecture à nœud unique capable de gérer des milliards de séries temporelles uniques sur une seule machine, réduisant ainsi la complexité opérationnelle.
Pour migrer, vous pouvez simplement modifier le point de terminaison remote_write dans votre configuration Prometheus pour qu'il pointe vers VictoriaMetrics :
global:
scrape_interval: 15s
remote_write:
- url: 'http://victoriametrics:8428/api/v1/write'
queue_config:
max_samples_per_send: 5000
capacity: 25000
Stratégie 3 : Sous-échantillonnage et politiques de rétention des données
Peu importe le backend, stocker des données brutes au niveau de la milliseconde pendant des mois est souvent inutile. Prometheus et VictoriaMetrics prennent tous deux en charge le sous-échantillonnage. VictoriaMetrics, en particulier, permet des politiques de sous-échantillonnage agressives où les données plus anciennes sont automatiquement agrégées dans des résolutions d'une minute ou d'une heure.
Cela réduit considérablement l'empreinte disque. En configurant des périodes de rétention qui équilibrent coût et besoins d'observabilité, vous pouvez conserver des données haute résolution pendant quelques semaines (suffisant pour déboguer des incidents récents) et des données basse résolution pendant des années (utile pour l'analyse des tendances).
Conclusion
Optimiser l'ingestion de séries temporelles à haute cardinalité ne consiste pas seulement à mettre à l'échelle le matériel ; cela nécessite une discipline architecturale. Commencez par auditer vos métriques pour les « mauvaises » étiquettes comme les identifiants d'utilisateur, les adresses IP ou les identifiants de requête dynamiques. Utilisez les règles de relabeling de Prometheus pour supprimer ces étiquettes à la source. Pour le stockage à long terme et l'analyse historique, envisagez de décharger les données vers VictoriaMetrics, qui offre une compression et des performances d'ingestion supérieures. En combinant l'hygiène des étiquettes avec le bon backend de stockage, vous pouvez maintenir une pile d'observabilité robuste et rentable qui évolue avec la croissance de votre application.