Écrire soit même son outil de monitoring, partie 1

illustration de l'article

Dans le cadre personnel, je possède plusieurs Raspberry Pi (RPi) qui font tourner plusieurs services et je souhaitais comprendre ce qu’il se passait dessus. Voici, basiquement, à quoi ils servent :

flowchart LR; subgraph RPi-1 M[Serveur musique] S[(Disque)] P[Serveur photo] end subgraph RPi-2 CP[Convertisseur photo] CV[Convertisseur vidéo] end subgraph RPi-3 B[Backup serveur] MP[Lecteur musique] end P-->CP P-->CV M-->MP

Au travail, quand on pense monitoring, on pense immédiatement à de grosses solutions comme InfluxDB, ELK…mais est-ce ce dont j’ai besoin ?

Mais qu’est ce que le monitoring ?

Monitorer consiste à surveiller le bon fonctionnement d’un système et à réagir en fonction de critères : alerting, redémarrage de service… Cette surveillance peut se faire à différents niveaux : machine, applications (logs, événements), réseau…

Pour ma part, je souhaite :

  • savoir quel est l’état physique des machines : CPU, mémoire, espace disque
  • connaître la température du processeur, en particulier pour les RPi fanless qui peuvent chauffer
  • surveiller l’état de plusieurs services (heartbeat)

Point lexique : métrique, supervision et hypervision…

Un point sur les différents termes :

  • Une métrique est une mesure à un instant T. Exemple : Température CPU de 35.2° le 20220202-12:10:00
  • Un indicateur est une interprétation d’une ou plusieurs métriques. Température OK
  • La supervision consiste à surveiller l’évolution de métriques. C’est un terme ancien intégré au monitoring
  • Le monitoring englobe la supervision et ajoute la notion de surveillance et d’alerting
  • L'hypervision est la centralisation des outils de supervision

La solution que je recherche est un outil de supervision. Je ne souhaite pas pour l’instant être notifié en cas d’échec.

🔺 Dans le cadre d’un usage professionnel, afficher des graphiques n’a aucun intérêt : le nombre de services est trop important pour demander à un humain de les surveiller.
Il faut prévoir des alertes en définissant sur quels critères pertinents elles seront lancées. Les graphiques seront utilisés ponctuellement pour comprendre un problème, pourquoi une alerte a été levée.

Voyons les solutions du marché existantes ?

Elasticsearch, InfluxDB…

Plusieurs solutions existent pour faire du monitoring ou du stockage timeseries (évolution d’une mesure dans le temps).
Dans toutes ces solutions, il faut installer des agents sur les machines à surveiller afin de collecter les métriques et les envoyer à un serveur central :

  • Affichage de graphique avec Grafana et une base :
    • avec InfluxDB / Telegraf : LA base spécialisée dans les timeseries avec l’agent de collecte Telegraf
    • avec Prometheus : une alternative à la précédente
  • ELK : Elasticsearch / Kibana : cette base s’oriente depuis plusieurs années sur le monitoring (applicatif, infrastructure, logs…) grâce à de nombreux connecteurs comme filebeat, metricbeat, heartbeat
  • Datadog, Dynatrace, Splunk…

Ces outils sont performants, mais dans mon contexte :

  • Ce sont toujours des applications distribuées (même si elles peuvent tourner en mono-noeud)
  • L’application centrale est souvent lourde en termes de resource (2GB de ram, 2 coeurs)
  • De très nombreuses fonctionnalités que je n’utiliserai pas : création de dashboards, nombreux types de graphiques, alerting, analyse…
  • Plusieurs produits ne proposent pas de version gratuite… rédhibitoire

Alors que choisir ? Je ne vais quand même pas coder cette solution moi-même…et puis pourquoi pas ?

Challenge

Avant de coder une solution à la main, étudions le fonctionnement d’une base distribuée qui peut stocker des données temporelles, Cassandra.

Fonctionnement du stockage sur Cassandra

Quand on utilise une base de données NoSQL, la seule question que l’on doit se poser est “comment est ce que je veux retrouver mes données ?”. Il ne faut pas s’imaginer stocker des données de manière désordonnée pour espérer plus tard les retrouver.

comment_rechercher

Dans une base distribuée, le fait d’interroger, lors d’une requête, l’ensemble des nœuds, produira de mauvaises performances :

  • la durée de la requête dépendra de la machine la plus lente
  • l’utilisation du réseau est plus conséquente
  • l’agrégation de données des différents nœuds est coûteuse (elle s’effectue souvent sur une seule machine)

Si on veut avoir une lecture plus efficace, les données à lire doivent être colocalisées. En ayant les données à rechercher sur la même machine et contigües, on les lira en une seule fois. Cassandra illustre très bien ce mécanisme dans sa conception.

Cassandra est une base de données colonne, c’est-à-dire que pour une clé donnée, on va lire un certain nombre de colonnes.
La clé de partition (PK) permet de définir sur quelle machine se trouve les données tandis que la clé de cluster (clustering key / CK) est la clé d’unicité sur la machine. Les données sont également regroupées pour une même CK.

Schéma de stockage

sequenceDiagram participant User participant C* participant Memory participant CommitLog participant SSTables User->>C*:Save info C*->>Memory:Save info as structured C*->>CommitLog: Append data in file Note right of CommitLog: Used to retrieve data after crash C*-->>User:It's saved Memory->>SSTables:Flush files on disk Note right of SSTables: Data are copied frequently SSTables-->>CommitLog:Remove useless commits SSTables->>SSTables:Compact tables Note right of SSTables: Clean files an optimize when necessary

Comment Cassandra stocke ses données ? Cela se fait en plusieurs étapes :

  • Lors de la réception de nouvelles données sur un nœud :
    • Le driver détermine sur quelle(s) machine(s) / instance(s) (appelé replica) les données doivent être copiées, à partir de la clé de partition
    • Sur chaque machine, les données sont copiées
      • En mémoire de manière structurée, afin de pouvoir les rechercher
      • À la fin du commitLog (append) afin de pouvoir restaurer les données lors d’un crash.
    • À intervalle régulier les données sont “flushées” sur le disque dans les SSTables, structures de données organisées permettant une recherche rapide.
    • Régulièrement, les tables sont compactées afin de supprimer les données “tombstone” (suppression en deux temps) et réorganiser les données pour les colocaliser. Il existe plusieurs stratégies qui vont être plus ou moins consommatrices en ressources : l’espace disque, la mémoire ou le cpu.

Cassandra est rapide en écriture car les nouvelles données sont stockées en mémoire et dans un fichier non structuré de manière séquentielle. Ce qui est intéressant, c’est que pour proposer une écriture efficace, il ne faut pas écrire les données de manière systématique et l’écriture contigüe est plus efficace que l’écriture aléatoire (surtout sur des disques mécaniques).

En fonction de notre besoin et de notre capacité à accepter la perte de données, nous choisirons à quelle fréquence il faut écrire les données.

Pour déterminer la fréquence, il faut calculer ce que l’on va stocker :

  • 3 machines vont remonter des métriques
  • 4 métriques de base sont prévues : cpu, mémoire, disque et température
  • A raison d’une mesure par minute, on obtient par jour : 4 x 3 x 1440 = 17280 mesures par jour

Si l’on souhaite sauvegarder les données quand notre buffer atteint 100 valeurs, la perte maximum en cas de crash sera de 8 minutes. Il est possible, comme Cassandra, d’éviter de perdre des données en sauvegardant dans un fichier non structuré, utilisé uniquement pour la récupération, les métriques dès qu’elles arrivent.

Au terme de cet article, nous avons vu ce qu’était le monitoring, défini quel était mon besoin et étudier le fonctionnement d’une base distribuée.
Désormais, nous allons pouvoir passer aux choses en sérieuses en écrivant notre propre solution de monitoring dans la 2ème partie de cet article.

Date

Auteur

Avatar Jonathan BARANZINI

Jonathan BARANZINI

Développeur

Tags

#Golang #Monitoring