Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)
CérénIT vient de finaliser la migration pour un de ses clients d’un socle InfluxDB/Chronograf/Kapacitor vers InfluxDB2. Ce billet est l’occasion de revenir sur la partie alerting et de la migration de Kapacitor vers des alertes dans InfluxDB2.
Dans le cadre du socle InfluxDB/Chronograf/Kapacitor, le fonctionnement était le suivant :
Avant d’envisager la migration InfluxDB2, un point de vocabulaire :
Avec la migration InfluxDB2, nous avons voulu maintenir le même mécanisme. Toutefois :
Heureusement, la documentation mentionne la possibilité de faire des “custom checks” et un billet très détaillé intitulé “InfluxDB’s Checks and Notifications System” permet de mieux comprendre ce qu’il est possible de faire et donne quelques exemples de code.
Dès lors, il s’agit de :
Pour se faire, nous allons nous appuyer sur les mécanismes mis à disposition par Influxdata, à savoir les fonctions monitor.check(), monitor.from() et monitor.notify() et les mécanismes induits.
C’est ce que nous allons voir maintenant :
Le cycle de vie d’une alerte est le suivant :
monitor.check()
en définissant les informations d’identification du check, le type de check que l’on utilise (threshold, deadman, custom), les différents seuils dont on a besoin, le message à envoyer au endpoint, les données issues de la requête flux.monitor.check()
va alors stocker l’ensemble de ces données dans un measurement statuses
dans le bucket _monitoring
et il s’arrête là.monitor.from()
prend le relais, regarde s’il y a de nouveaux status depuis sa dernière exécution et en fonction des règles de notifications qui ont été définies, il va passer le relais monitor.notify()
.monitor.notify()
enverra une notification si la règle est validée et il insérera une entrée dans le measurement notifications
du bucket _monitoring
Une première version des alertes ont été implémentées sur cette logique. Des dashboards ont été réalisés pour suivre les status et les notifications. Cela fonctionne, pas de soucis ou presque.
Il se peut qu’il y ait un délai entre le moment où l’insertion issue du monitor.check()
se fait et le moment où le monitor.from()
s’exécute. Si monitor.from()
fait sa requête avant l’insertion de données, alors l’alerte ne sera pas immédiatement levée. Elle sera levée à la prochaine exécution de la task, ce qui peut être problématique dans certains cas. Pour une tâche qui s’exécute toutes les minutes, cela ne se voit pas ou presque. Pour une tâche toutes les 5 minutes, ça commence à se voir.
Une version intermédiare de la task est alors née : une fois le monitor.check()
exécuté, nous faisons appel à monitor.notify()
pour envoyer le message vers le endpoint.
Avantage :
Inconvénients :
notifications
de la même façon que précédemment (d’où les pointillés) vu que les données insérées dans le measurement statuses
n’existent pas encore. On perd la visibilité sur les notifications envoyées (mais on a toujours le suivi des statuts ; nous supposons que si on a le statut, alors on sait si la notification a été envoyée)Une variante non essayée à ce stade : elle consiste à faire cette notification au plus tôt mais de conserver le mécanisme de monitor.from() + monitor.notify()
pour avoir le measurement notifications
correctement mise à jour. A voir si les alertes ne sont pas perturbées par ce double appel à monitor.notify()
. Dans le cas présent, c’est l’application métier qui envoie les alertes après que la task InfluxDB ait appelé son API HTTP. Si chaque monitor.notify()
en vient à lever une alerte, cela est sans impact pour l’utilisateur. En effet, une fois qu’une alerte est levée, elle est considérée comme levée tant qu’elle n’est pas acquittée. Donc même si la task provoque 2 appels, seul le premier lévera l’alerte et la seconde ne fera rien de plus.
Enfin dernière variante (testée) : s’affranchir complètement de monitor.notify()
pour faire directement appel à http.endpoint() et http.post() et faire complètement l’impasse sur le suivi dans notifications
.
Tout est une histoire de compromis.
En conclusion, nous pouvons retenir que :
_monitoring
et les measurements statuses
et notifications
.monitor.check()
et monitor.from()
peuvent conduire à des décalages de levées d’alertesCérénIT a été contacté pour mener l’audit d’une instance InfluxDB 1.8 OSS utilisée dans un projet IoT lié à l’énergie. L’audit avait plusieurs objectifs :
De l’audit, on notera que :
Avant d’aller plus loin, précisons un peu cette notion de shard et les notions liées pour bien appréhender le sujet :
Nous pouvons représenter la logique instance > database > shard(s) > tsm files de la façon suivante :
Par défaut, InfluxDB applique les shard duration suivantes en fonction des retention policy :
Retention policy | Default shard duration |
---|---|
<= 2 days | 1 hour |
<= 6 months | 1 day |
> 6 months | 7 days |
Source : InfluxData - Shard group duration
Dès lors, une base de données avec une retention policy infinie aura une shard duration de 7 jours. Ainsi, si cette base contient 10 ans d’hisorique (soit 10 * 52 semaines = 520 semaines), elle contiendra 520 shards.
Du coup, InfluxData recommande les valeurs suivantes (au moins en 1.x ; on peut supposer que cela reste valable en 2.x):
Retention policy | Default shard duration |
---|---|
<= 1 day | 6 hour |
<= 7 days | 1 day |
<= 3 months | 7 days |
> 3 months | 30 days |
infinite | >= 52 weeks |
Source : Shard group duration recommendations
Selon cette perspective, la base de données avec 10 ans d’historique ne contiendra plus 520 shards mais 10 shards en prenant une shard duration de 52 semaines. L’écart entre la valeur par défaut et la valeur recommandée est plus que significatif.
Pour bien dimensionner vos shard duration, InfluxData recommande :
Pourquoi nous en arrivons là ? C’est assez simple :
Dès lors, un nombre important de shards va augmenter d’autant plus la consommation mémoire et le nombre de fichiers ouverts pour manipuler les données associées.
Si on recoupe ces données avec les recommendations pour InfluxDB Entreprise, à savoir 30/40 bases par data nodes et 1.000 shards par node, le bon réglage des retention policy et des shard durations n’est pas à négliger pour la bonne santé de votre instance.
En outre, s’il est possible de mettre à jour la retention policy et la shard duration en 1.x, cela ne s’appliquera que pour les nouveaux shards. Les anciens shards ne seront pas “restructurés” en fonction des nouvelles valeurs.
Pour mettre à jour les shards existants, il faut :
Ultime question, la version 2.x OSS change-t-elle la donne sur le sujet :
report
et report-disk
.En conclusion, ce qu’il faut retenir :
Mise à jour : le client reporte les gains suivants post restructuration des bases pour le serveur de recette et production :
SELECT DISTINCT
entre 28x et 8000x. Cela est valable tant pour les données Timescale que les données natives Postgres. Une contribution upstream est prévue.compose
devrait devenir une sous-commande officiel de la CLI Docker ; on pourra alors faire docker compose up -d
jq
pour les données relationelles. Du SQL ou des fichiers Excel/CSV/JOSN/XML en entrée et les mêmes formats en sortie (et un peu plus).vector top
, la source internal_logs
et l’API GraphQL. Un guide de mise à jour vers la nouvelle syntaxe est disponible.