Shinken : Les grandes lignes

Posted in Nagios by Nap on October 6, 2009 2 Comments

Il y a quelques temps j’ai présenté dans les grandes lignes mon proof of concept Shinken, le Nagios en Python. Et bien il a plutôt bien avancé depuis. En voici un état des lieux et une idée de là où il va.

Architecture générale

Shinken est pensé pour les environnements distribués. Il est bien sûr possible de faire tourner tous ses composants sur une seule et même machines. Les composants justement, parlons en.

Architecture de Nagios

Nagios est (quasiment) monolithique. Il lit la conf, la traite, ordonnance les checks, les lance ainsi que les actions qui en résultent (les notifications et les event handlers). Il exporte également des informations vers un daemon externe pour mise en base de données.

Lorsque l’on a un petit environnement, tout marche bien, c’est pratique et presque rapide. Le problème se pose avec les grands environnements : Nagios est capable de gérer facilement jusqu’à 10000checks/5minutes sur un serveur moyen de gamme. Avec du tuning on peu arriver à 30000, mais gère plus, même en rajoutant pleins de CPU sur le serveur. La mise en place des environnements distribués n’est pas triviale (la preuve, elle demande un chapitre à part entière dans mon livre :) ). La tâche est encore plus hardue pour les environnements distribué ET hautement disponibles. Cette dernière exigence est très complexe à gérer si on ne veux pas perdre trop en performances, voir pas faisable du tout pour les très gros environnements sauf à mettre une armée de serveurs.

C’est là que vient Shinken : mettre en place un environnement distribué hautement disponible facilement. Le côté facile doit venir aussi de la gestion de conf. Nagios a une gestion de la configuration impressionnante, mais qui nécessite un gros travail manuel lorsqu’il est question d’environnements distribués.

De même pour donner des ordres à Nagios, il faut passer par le pipe nommé nagios.cmd situé sur le même serveur. Pour un serveur ça va, mais pour une dizaine, se souvenir sur quel serveur Nagios se trouve l’hôte que vous voulez rescheduler devient un peu plus complèxe…

Pour résumer la situation, l’architecture de Nagios est la suivante:

nagios-architecture

Architecture de Shinken

Shinken propose une solution à ces problèmes : le découplage des rôles de Nagios. Ces rôles sont éparpillés sur différents processus. Voici le schémas global, le rôle de chaque élément sera précisé plus bas:

shinken-architecture

  • Arbiter : lit la configuration, la découpe en N partie et l’envoi vers les autres processus. Il lit l’unique fichier nagios.cmd de l’architecture, et transmet les ordres à qui il faut. Il est également le garant de la haute disponibilité et la répartition de charge.
  • Schedulers (nom de processus Shinken) : il lit la conf que lui envoi Arbiter. Il peux y avoir N schedulers, chacun avec ses propres éléments (hôtes/services). Il est en charge d’ordonnancer les checks, de les proposer aux autres éléments, récupère le retour des checks, et propose des notifications/event handlers si besoin qui seront lancé par des éléments externes.
  • Pollers : Il peux y en avoir autant qu’on veut. Ils récupèrent les checks auprès des schedulers, les lance et renvoi le retour aux scheduler en question. Il n’y a pas intelligence ici. Ils récupèrent des checks, les lancent, renvoient le résultat. Point barre.
  • Actionner : De préférence il n’y en a qu’un (et un spare). Il est en charge de lancer les notifications et les event handlers. Il fonctionne de la même manière que les pollers, mais il est à part car on préfère en avoir un et un seul qui fait les notifications (pour les problèmes d’acès aux serveur SMTP ou les flux RSS par exemple).
  • Broker : Unique avec un spare, Les schedulers exportent des informations dans des ‘broks’, des morceaux d’informations. Ils sont récupérés par le Broker qui en fait ce qu’il veut après, suivant les plugins qu’il a. Chaque plugin traite l’information comme il le veut. Les plugins actuellement développés sont l’export du fichier service-perfdata et l’export dans la base merlin. La base ndo ne devrait pas tarder, mais ca sera plus long que pour celle de merlin, car elle est vraiment mal fichue!
  • Bah c’est tout. C’est déjà pas mal non? :)

Les éléments de charge sont éclatés d’où le load balancing. L’arbiter est le garant de la haute dispo, il réparti les conf aux vivants, et envoi les conf des éléments morts aux spare si un membre actif vient à mourrir (bah ca peut arriver hein, personne n’est parfait). L’administrateur n’a pas à se soucier de quel scheduler va gérer son élément (hôte), l’arbiter va découper la conf pour lui de manière automatique, et en faire des paquets les plus équilibrés possible en terme de charge. Shinken tiens son nom de là d’ailleurs :)

La configuration

Qui dit nouveaux éléments dit nouvelle configuration. L’arbiter mis à part, chaque élément a un élément de configuration qui lui est dédié. Elle est de la forme (par exemple ici pour les scheduler):

define scheduler{

name     scheduler-main

address      192.168.0.1

port      7768

spare        0

}

define poller{

name      poller-main

schedulers     scheduler-main, scheduler-spare

address      192.168.0.1

port      7771

}

Ceci doit être donné à l’arbiter dans le fichier nagios.cfg, comme n’importe quel autre configuration d’éléments dans Nagios. Ceci va permettre à l’Arbiter d’envoyer les configuration et de gérer les liens avec les schedulers, pollers and co. Je n’ai pas encore prévu de configuration locale au poller and co. Mais à part le port d’ouverture, il n’y aura pas gand chose à configurer.

Je prévois de faire en sorte de créer automatiquement un élément en local s’il n’est pas défini dans la configuration, genre dans le cas de l’import d’une configuration existante sans avoir à la modifier.

Les performances

J’en vois déja arriver avec leur grands sabots : “c’est en python donc c’est tellement lent qu’on ne va pas pouvoir tester sur de vrais environnements”. Ca aurait été sacrément inutile si c’était le cas. Je n’aime pas trop perdre mon temps. Allons directement à la mesure dans de vraies conditions : serveur Xeon bi-coeurs 3ghz. J’ai utilisé une configuration générée tout comme dans le chapitre 9 de mon livre (quoi,vous ne l’avez pas encore lu?). La latence nous permet de savoir si le programme a assez de ressources ou non.

  • Nagios dans sa configuration standard a stagnée a 9500 checks/5min, avec du tunning poussé, 25000. Je n’ai pas encore fait les tests avec export en base de données avec ndo2db;
  • Shinken arrive à 50000 avant que j’ai eu à faire du tunning de code…Et l’export en base de données fait en prime, le tout sur la même machine bien sûr.

Il n’y a pas de secret ici : La charge de Nagios vient du lancement de nouveaux process Nagios qui doivent lancer les plugins et le fait de “reaper” les résultats dans des fichiers plats. Shinken utilise un pool de process (les pollers ont un pool de workers) donc pas de surcharge ici, et les pollers envoient directement les résultats des checks en mémoire (technique d’objets distribués de type Corba, mais en autrement plus simple à utiliser). Pas de fichiers à parser, beaucoup moins de charge. “Et voila”.

Par contre ce n’est pas parfait : le lancement de l’Arbiter est légèrement plus lent que Nagios pour la lecture de la configuration, mais rien de rédhibitoire. Je vois revenir les gros sabots pour la consommation mémoire : Oui, ceci consomme plus de RAM que Nagios. Nagios est vraiment bien optimisé sur ce point, Shinken est “seulement” 3 fois plus consommateur, genre 250Mo pour les 50000 checks. C’est tout à fait acceptable à mon goût.

Bref, c’est testable même avec des grands environnements. Et ca veut dire que l’on peut encore améliorer Nagios. Bon reste à faire la partie Worker en C. Je l’aurais bien prise chez Apache, mais question de licence, ça le fait pas je pense. Puis le code est .. complexe pour juste une gestion de worker, mais bon c’est le C hein…

Ce qui est déjà fait

Les fonctionnalités principales de Nagios sont déjà dans Shinken:

  • ordonnancement de Nagios (HARD, SOFT, etc)
  • gestion des périodes de temps Nagios (sauf les exclusions)
  • checks passif
  • gestion des dépendances
  • macros
  • vérification de la fraicheur des états
  • export des données de performances
  • export des données dans une base MySQL de type Merlin
  • la gestion du flapping
  • le cache de checks pour les dépendances
  • services volatiles (pour les logs)
  • gestion du fichier de rétention

Pas si mal hein?

Ce qu’il reste à faire

Avant de le présenter “officiellement” aux auteurs de Nagios, je tiens à ce que la gestion des spares soient complète. De même que l’export vers la base ndo. Après je le présente, avec dans l’espoir de voir les bonnes idées s’il y en a (comme le pool de process) intégrée dans Nagios si c’est possible. (Bon tout est possible, mais en C ça devient beaucoup plus long à faire… beaucoup plus long à faire même…et pourtant j’aime le C, faut pas croire).

Ah oui, il faut que je fasse une VM de type VirtualBox avec Shiken et Ninja pour l’interface. En fait plusieurs VM seraient mieux pour l’aspect distribué.

Related Posts:

Comments
  • > Par contre ce n’est pas parfait :le lancement de l’Arbiter
    > est légèrement plus lent que Nagios pour la lecture de la
    > configuration, mais rien de rédhibitoire.

    Cela est peut être dû au format de fichier non? Par exemple, l’interface de Nagios codé en C est très très lente car elle doit systématiquement parser du fichier texte. Imaginons que ton format de fichier soit plus normalisé, avec un style CSV:
    host;nom_host;nom_long_host;ip_host;…. (toutes les autres options Nagios)
    service;nom_service;nom_host_attaché;… (toutes les autres options Nagios)

    Le parsing de ce genre de fichier serait à mon avis beaucoup, beaucoup plus rapide que le format actuel.

    Qu’en penses-tu?

    A+

    (note: j’ai pas trop réfléchi là sur le formalisme de la configuration, ce devra être creusé un peu plus bien sûr)

    • Nap:

      En fait c’est la partie application de l’héritance que je perds du
      temps, par forcément la lecture des fichiers et leur découpage.

      Je sais comment contourner certaines lenteurs de Python et ici je vais
      devoir faire des fonctions un poils plus grandes. En effet les appels
      de fonctions sont lentes en Python, donc au lieu de faire une fonction
      d’héritage par propriété, je vais faire une fonction qui prend toute
      la liste des propriétés, et juste faire un for dessus. Mais bon,
      j’arrive à quelques secondes pour des conf monstrueuses de 75000
      services et ce que lorsque je défini vraiment 75000 vrais services. Si
      par exemple j’avais 75000 hôtes dans un host group et que j’appliquais
      un unique service sur ce groupe, ca irait super vite pour la partie
      héritage et pas beaucoup plus pour la création des 75000 services.

      Mais bon déjà je termine quelques fonctionnalités importantes comme la
      gestion des spares et l’export en base NDO (qu’est ce qu’elle est
      tordue comme base! Un calvaire, Merlin/CentreonBroker c’est vraiment
      mieux foutu) puis je me lance dans le grand bain :)

      Jean