Shinken : quand un Python rencontre Nagios

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
49
Mois de parution
août 2010
Domaines


Résumé
Nagios est encore aujourd'hui la star des logiciels de supervision open source, même si de sérieux concurrents le talonnent. Si ses qualités sont indéniables, il souffre tout de même de problèmes dans la gestion des très grands environnements qui sont dus principalement à son implémentation actuelle. Le projet Shinken est une nouvelle implémentation de Nagios qui tente de lever ce problème et d'apporter un nouveau souffle à ce projet. Regardons son histoire et ce qu'il propose.

Body

1. Un début de projet à l'histoire atypique

Avant de nous lancer tête baissée dans notre étude de Shinken et de son architecture, prenons quelques instants pour voir pourquoi et comment il a vu le jour.

1.1 Nagios : un projet au ralenti

L'histoire de Shinken ne peut se comprendre qu'en revenant sur celle de Nagios au cours de ces dernières années. Ce dernier a commencé sa grande aventure il y a 10 ans sous le nom Netsaint. Sa modularité lui apporte au fil du temps une forte renommée dans le monde open source. Après un renommage en Nagios pour cause de nom déjà déposé, il continue son développement et cristallise autour de lui une très forte communauté qui lui confère un statut de star de la supervision qui commence à dépasser le cadre des seuls logiciels libres.

Cependant, depuis plus de deux ans, le développement s'est fortement ralenti. L'auteur de Nagios n'étant presque plus présent sur la mailing list du projet, les apports de la communauté sur le cœur du projet se sont faits de moins en moins nombreux. Cette absence s'explique facilement : après de nombreuses années à gérer ce logiciel open source, l'auteur de Nagios, Ethan Galstad, a légitimement créé une société de services pour vivre de ce grand projet. Son absence prolongée a irrité une partie de la communauté qui a lancé un fork il y a plus d'un an : Icinga.

Ce dernier n'a pas réussi à s'attirer une grande part de la communauté restée fidèle à Nagios car les motivations des « forkers » semblaient troubles : une part importante de ses membres est employée par une société directement concurrente de celle de l'auteur de Nagios. Les craintes d'un « fork » plus commercial qu'autre chose ont effrayé beaucoup de possibles contributeurs. De plus, les apports du fork se sont révélés limités sur le cœur de l'application, se limitant à une nouvelle interface et un export en base Oracle.

1.2 Un proof of concept innovant

1.2.1 Une identification des améliorations

Dans ce contexte agité, la communauté n'est pas restée inerte. Au sein de celle-ci, et après avoir écrit un ouvrage sur Nagios, votre serviteur a identifié les principaux problèmes de Nagios : si la gestion de configuration de Nagios est très puissante pour gérer les grands environnements, les performances et les possibilités d'architectures distribuées et hautement disponibles sont en retrait. Un serveur Nagios standard peut gérer environ 1000 hôtes en comptant 10 services par hôte. Si ses performances sont bonnes, il est relativement facile d'atteindre pour un grand environnement une telle configuration. Si la mise en place d'architectures distribuées est possible, elle n'est pas aisée, encore moins si l'on souhaite avoir en plus de la haute disponibilité, même en utilisant des outils tiers comme Centreon.

1.2.2 Les problèmes de performances

Le problème de performances est dû au mécanisme qu'utilise Nagios pour obtenir ses informations : il se forke afin que son fils lance lui-même une sonde (un simple script shell ou un exécutable) qui réalise la vérification. Le processus fils lit la sortie standard de la sonde et son code retour pour obtenir l'état de l'élément surveillé. Ce fils écrit ces résultats dans un fichier plat, qui sera lu et parsé par le démon principal. Une fois le fichier écrit, le fils meurt.

Dans ces deux dernières phrases réside le cœur du problème de performances de Nagios :

- Le parsage de fichiers plats est une opération extrêmement coûteuse.

- Pourquoi tuer le processus fils après son travail si c'est pour le relancer à la prochaine sonde ? Un fork est une opération coûteuse.

Le premier point se règle avec un export des données du processus fils vers une socket du processus maître. La communication étant directement en mémoire, et sans traitement de chaîne de caractères, le gain est substantiel.

Le second est conceptuellement simple également : le démon possède un pool de processus qui écoutent ses ordres. Le nombre de forks est ainsi divisé de moitié.

1.2.3 Les problèmes des environnements distribués

Le problème des environnements distribués est bien plus problématique : Nagios dispose nativement d'une méthode pour mettre en place des environnements distribués hautement disponibles, mais elle a un impact très important sur les performances. Des solutions comme Centreon existent, mais ne gèrent que la partie distribuée, pas nécessairement la haute disponibilité.

Si les problèmes de performances sont dus à l'implémentation, ici c'est un problème d'architecture globale qui pose souci, c'est-à-dire un problème de conception, pas si simple à régler.

1.2.4 Le choix d'un nouveau langage

Les premières propositions d'améliorations n'ayant pas reçu de la part des développeurs principaux de Nagios un accueil chaleureux, votre cher serviteur se lance dans l'écriture d'un proof of concept. Le démon étant écrit en C, la mise en place de ses idées n'est pas aisée, même non fignolées. Les idées de base de Nagios sont quant à elles simples à implémenter. C'est pourquoi le proof of concept a été implémenté dans un langage plus souple : Python. Réimplémenter le cœur Nagios en Python et y ajouter de nouvelles idées étaient plus simples que de partir directement dans le code actuel, qui est constitué de gros fichiers .c avec des fonctions très longues. Le but initial était de tester les idées en Python puis les réimplémenter par la suite en C.

Le Python permet également une portabilité très aisée. Nagios fonctionne très bien pour les environnements de tailles moyennes, c'est-à-dire entre 100 et 1000 serveurs. Ses performances et ses problèmes d'architectures sont un frein pour les environnements plus importants. Les petites entreprises ont un peu du mal à avoir un vrai service informatique, et notre cher système libre bien aimé n'est pas encore très répandu en leur sein. Une compatibilité avec le système de Redmond serait donc un plus non négligeable pour Nagios, ce qui est chose faite avec un proof of concept en Python.

Cette première étape s'est faite très rapidement : l'application des méthodes de data driven a permis d'obtenir un « cœur Nagios » en un nombre de lignes très faible, le tout en ayant une souplesse de développement très agréable.

Viennent ensuite les phases proprement dites d'étude et mise en place des pools de processus et l'architecture distribuée hautement disponible. C'est ce que nous allons voir de suite en commençant par la partie la plus structurante : l'architecture globale.

2. Un Nagios coupé en pièces : « The Unix way »

Afin de mieux comprendre l'architecture globale, suivons un peu le raisonnement qui lui a permis de voir le jour.

2.1 Les rôles de Nagios

Faisons un rapide rappel sur la vie d'un démon Nagios : il lit la configuration de l'administrateur dans un fichier plat, il ordonnance et lance régulièrement des sondes qui effectuent les vérifications, en cas de souci, il lance une commande pour notifier les utilisateurs de problèmes, le tout en exportant toutes ces données par un mécanisme de modules. Ces derniers remplissant le plus souvent une base de données accédée par la suite par une application web.

Tout ceci est effectué par le même démon. Après tout, ce fonctionnement a bien marché pour les environnements de taille moyenne depuis près de 10 ans. Mais regardons un peu ce qu'il se passe lorsque l'administrateur a besoin d'avoir plusieurs Nagios, pour des besoins de performances, de haute disponibilité, ou le plus souvent des deux. Ce fonctionnement est illustré par le diagramme suivant :

nagios-architecture

Fig. 1 : Architecture Nagios distribuée.

2.2 Les problèmes de cette architecture monolithique

Divers problèmes sont posés par cette architecture. La gestion des configurations n'est pas aisée. Une modification d'un contact à prévenir, par exemple, doit l'être sur tous les serveurs. Même avec des solutions comme Centreon, qui facilite grandement cette gestion, il reste un problème : c'est à l'administrateur de choisir quel Nagios va surveiller tel ou tel serveur, et il ne doit pas se tromper sur les liens qui existent entre ses éléments (comme des relations de dépendances), sous peine de ne plus pouvoir relancer ses serveurs, ou pire, d'avoir des informations manquantes sur certains.

De plus, en cas de problème de performances, l’ajout d'un nouveau serveur Nagios pour alléger la charge demande de rééquilibrer les configurations de manière manuelle. Ceci peut être pesant et complexe si l'on a plus de 100 serveurs à surveiller.

De même, les messages de notifications partent de chaque service Nagios, ce qui multiplie les autorisations SMTP et limite fortement la mise en place d'autres moyens de notifications comme un flux RSS commun.

Concernant la partie hautement disponible, un Nagios peut en suppléer un autre au prix d'une baisse de performances si l'on souhaite avoir des informations relativement à jour lors de la bascule. Cette relation est à un pour un. Ceci oblige à multiplier par deux les ressources là où un démon en spare aurait suffi pour la quasi majorité des cas.

N'en jetons plus : l'architecture Nagios dans un environnement distribué n'est pas idéale. Le fait qu'un démon gère tous les rôles est pratique lorsqu'il est seul, mais est un frein lorsqu'il s'agit de les multiplier. Il est quasi impossible dans cette situation d'avoir un point unique et simple d'administration.

2.3 « The Unix Way »

Un des objectifs du proof of concept était de revoir cette architecture globale. Fidèle aux principes qui ont fait la force d'Unix au cours de ces 40 dernières années, le découpage doit suivre celui des rôles : un rôle, un élément.

Regardons un peu le nom et les rôles de ces éléments :

- Arbiter : il lit, traite et dispatche la configuration globale vers les autres éléments ;

- Scheduler : il ordonnance les vérifications ;

- Poller : il lance les vérifications comme planifiées par les schedulers ;

- Reactionner : il centralise les notifications levées par les schedulers et les lance ;

- Broker : il centralise les données des autres éléments et les fournit à des modules pour traitement.

L'architecture finale est observable sur le schéma suivant :

shinken-architecture

Fig. 2 : Architecture de Shinken

Regardons de plus près le fonctionnement et le rôle de chaque partie.

2.4 L'Arbiter : un démon pour les contrôler tous

Il est le gardien du temple : il gère la configuration et se situe en amont de tous les autres éléments. Il ne fait pas beaucoup d'actions, mais sa position centrale lui permet d'être un point d'administration unique pour toute la solution.

2.4.1 Le découpage intelligent de la configuration

Sa connaissance de tout le monde lui permet de savoir combien de schedulers sont définis. Ayant cette information, il est alors capable de « couper » la configuration de l'administrateur en autant de morceaux et de les propager vers ces démons. Cette capacité lui a donné son nom : Shinken. C'est le nom donné au Katanas les plus coupants.

Ce découpage n'est pas simpliste. Nagios possède de nombreuses relations possibles entre les éléments, comme les hôtes et les services. Le découpage est réalisé en connaissant toutes ces relations, et crée des packs, indépendants entre eux, d'hôtes et de services. Il agrège ensuite ces packs en N configurations pour les N schedulers.

Les diagrammes suivants illustrent ce principe :

pack-creation

Fig. 3 : Création des packs indépendants

pack-agregation

Fig. 4 : Agrégation des packs en configurations

Il est important de noter que le découpage se fait suivant les hôtes : tous les services d'un hôte seront dans la même configuration que lui, et donc gérés par le même ordonnanceur. De plus, les configurations sont équilibrées tant que possible entre les différents schedulers. Ainsi, l’ajout d'un nouveau démon ne demande pas de changement notable pour l'administrateur : l'outil réalise pour lui la nouvelle répartition des éléments automatiquement.

De plus, des poids peuvent être définis pour les schedulers afin d'aider à équilibrer plus justement la charge entre deux serveurs de puissance non identique. Nous en verrons un exemple par la suite.

Au final, l'administrateur n'a plus à se soucier de l'association d'un hôte avec tel ou tel démon. Ces derniers ne sont qu'une ressource permettant de supporter la charge, et l’ajout d'une nouvelle d'entre elles augmente la capacité globale, sans demander d'effort particulier en termes de reconfiguration.

2.4.2 Gestionnaire des liens entre les éléments

De même, l'Arbiter est également capable de prévenir les éléments « satellites » (pollers, reactionners et brokers) de la localisation des schedulers sur le réseau. De cette manière, lors de l’ajout d'un nouvel ordonnanceur, la configuration des satellites n'a pas besoin d'être modifiée.

2.4.3 Gestionnaire de la haute disponibilité

Tous les éléments peuvent être soit maître, soit spare, l'Arbiter ne faisant pas exception à cette règle. Un maître va être un élément actif. Son homologue va, quant à lui, être une « roue de secours » en cas de perte d'un maître. L'administrateur est libre de choisir le nombre de maîtres et de spare suivant le niveau de robustesse qu'il désire. Chaque type d'élément est indépendant. Un administrateur peut définir par exemple deux schedulers maîtres et un seul spare. Il pourra gérer la perte d'un seul des deux schedulers, mais c'est acceptable dans la majorité des situations.

Cette gestion de qui est encore en vie et de l'aspect hautement disponible en règle générale est dévouée à l'Arbiter. Il « ping » régulièrement les éléments, et si l'un d'entre eux ne donne plus de signe de vie, il dispatche sa configuration vers un spare. C'est un mécanisme simple, mais très efficace.

Voici un exemple de perte d'un scheduler :

scheduler-lost

Fig. 5 : Perte d'un scheduler

Point important, lorsqu'une configuration a été distribuée à un nouveau nœud, l'Arbiter s'assure que l'ancien, lorsqu'il reviendra, ne la gère toujours pas. En effet, si ce dernier était indisponible suite à une simple perte réseau, il possède toujours la configuration en mémoire et sans la surveillance constante du maître des lieux, nous pourrions nous retrouver avec une duplication de supervision.

2.4.4 Gestionnaire des commandes externes

Les administrateurs peuvent influer sur Nagios lorsqu'il fonctionne par l'intermédiaire des commandes externes. Elles permettent par exemple de spécifier l'état d'un service à Nagios, ce qui est la base de la supervision passive. Dans l'architecture que nous étudions, les hôtes et les services sont dispatchés sur les schedulers. Il est inconcevable de demander à l'administrateur de connaître celui qui gère le service en question pour qu'il envoie sa commande au bon démon. Nous avons un point d'administration unique avec l'Arbiter, autant en profiter.

Ce dernier va donc recevoir toutes les demandes de commandes externes. Il va déterminer si celles-ci sont spécifiques pour un scheduler (comme dans notre exemple de vérification passive d'un service particulier) ou globales à tous (comme le fait d'arrêter la supervision active). Il transfère ensuite la demande à qui de droit, comme illustré sur le diagramme suivant :

external-commands

Fig. 6 : Gestion des commandes externes

2.4.5 La configuration de l'Arbiter

Optionnelle, la configuration de l'Arbiter dans la configuration globale permet de définir, par exemple, un Arbiter maître et un spare. Elle prend la forme suivante :

define arbiter{

       arbiter_name     Arbiter-Master

host_name serveur-1 ;result of the hostname command under Unix

address serveur-1

       port     7770

       spare    0

       }

Les paramètres address et port permettent à l'Arbiter de savoir sur quelle interface ouvrir un port d'écoute pour les communications en provenance des satellites. host_name est utile, quant à lui, dans le cas où l'on définit plusieurs Arbiters, typiquement deux (un maître, un spare). Vu que la configuration sera strictement identique entre les deux machines, il faut un moyen au démon de savoir s'il est le maître ou l'esclave. Pour cela, on utilise tout simplement le nom de la machine où il se situe, renvoyée par la commande hostname.

Ceci implique qu'il ne peut y avoir qu'un seul Arbiter par serveur, mais en mettre plusieurs serait de toute manière un non-sens car le seul intérêt réside dans la haute disponibilité, pas les besoins de performances qui sont plus que minimes pour ce démon central.

2.5 Les Schedulers

2.5.1 Leur rôle : ordonnancer

Ils ont pour rôles d'ordonnancer les vérifications, d'en lire les résultats et d'en tirer les conséquences, comme demander une nouvelle vérification ou proposer une notification. Il est important de voir qu'ils ne lancent aucune action par eux-mêmes. Ils proposent aux autres éléments des files d'attente d'actions à effectuer ou de données à ingérer.

Ils peuvent être aussi nombreux que l'administrateur le souhaite.

2.5.1 La configuration

Voici un exemple de configuration d'un scheduler :

define scheduler{

       scheduler_name   scheduler-master

       address serveur-1

       port     7768

       spare    0

weight 1

}

Les paramètres address et port permettent à l'Arbiter de retrouver le démon sur le réseau. Le paramètre weight permet quant à lui de donner un poids à un scheduler. Plus le poids est élevé par rapport à ses petits camarades, plus il va gérer d'hôtes.

2.6 Les Pollers

2.6.1 Leur rôle : lancer les sondes

Ils ont pour rôle de lancer les sondes de vérifications. Ils récupèrent leur travail depuis les schedulers et placent ces actions à lancer dans leur propre file d'attente où vont venir piocher des processus « workers » qui sont le pool de processus évoqués au début. Python aide particulièrement sur ce point, deux lignes suffisant pour obtenir un pool de processus qui dialoguent sur une pile d'actions gérant les accès concurrents. Une fois la sonde lancée, ils replacent le résultat dans la file, résultat qui va être renvoyé vers le scheduler qui a fait la demande.

Tout comme ces derniers, les pollers peuvent être aussi nombreux que l'administrateur le souhaite. Ils peuvent également avoir un « poids » différent, afin d'équilibrer leur charge suivant la puissance des machines sur lesquelles ils se trouvent.

2.6.2 La configuration

Voici un exemple de configuration de poller :

define poller{

       poller_name     poller-All

       address serveur-1

port 7771

min_workers 4

max_workers 4

processes_by_worker 256

polling_interval 1

}

Comme pour les schedulers, address et port sont utiles pour l'Arbiter afin de retrouver son satellite sur le réseau. Le paramètre polling_interval permet de définir l'intervalle de temps entre deux interrogations des ordonnanceurs de la part du poller. De cette manière, il suffit d'augmenter cette valeur pour qu'il travaille moins par rapport à ses petits camarades.

Les paramètres min_workers, max_workers et processes_by_worker concernent quant à eux la taille du pool de processus et sont donc en première ligne dans les paramètres de tuning. Un processus worker va pouvoir suivre l'exécution de processes_by_worker processus à la fois. Il est important de savoir qu'un suivi demande deux ouvertures de file descriptors. Si l'administrateur souhaite augmenter cette valeur au-dessus de 512, il devra penser à changer le paramètre nofile du fichier de son utilisateur car il risque de dépasser la valeur par défaut qui est de 1024.

Pour l'instant, Shinken ne permet pas encore (en fait ne permet plus) d'augmenter à la volée le nombre de processus workers. Il est donc conseillé d'avoir des valeurs min_workers et max_workers identiques. Les performances étant déjà au rendez-vous, ce point sera traité plus tard.

2.7 Les Reactionners

2.7.1 Leur rôle : lancer les notifications

Leur rôle est de prendre les demandes de notifications ou d'actions de réaction (comme relancer un service tombé) auprès des schedulers et de lancer ces actions. Idéalement, l'administrateur définit un reactionner maître et un autre en spare afin de centraliser le plus possible ses notifications. La charge de ces services étant très limitée, ce n'est pas un problème de n'en avoir qu'un seul d'actif à la fois.

2.7.2 La configuration

Le code des reactionners et des pollers étant commun, leur configuration est identique.

2.8 Les Brokers

2.8.1 Leur rôle : fournir toutes les données à des modules

Leur rôle consiste à récupérer les données d'état et d'informations auprès des autres membres. Ils fournissent ensuite ces informations à des modules. Ces derniers sont multiples. On note, par exemple, des modules d'export en fichier plat (le classique fichier status.dat de Nagios) ou en base MySQL, Oracle et même Couchdb, même si pour ce dernier, aucun client n'existe actuellement.

Tout comme pour les reactionners, idéalement il y aura un Broker maître et un spare afin de centraliser toutes les informations en un seul point. De cette manière, il n'y aura par exemple qu'un seul fichier de données de performances, et ce peu importe le nombre de schedulers et de pollers définis. Il n'y aura plus besoin de s'embêter à rapatrier les fichiers sur toutes les machines pour les traiter les uns à la suite des autres.

2.8.2 La configuration des brokers et de leurs modules

Les Brokers ne savent rien faire sans module. Ce sont de simples codes Python chargés par le démon et activés par l'Arbiter. Ces modules peuvent prendre n'importe quelle configuration. Elle est contenue dans la configuration globale afin d'être facile à gérer. A cette configuration des modules, l'Arbiter ajoute l'adresse des ordonnanceurs auxquels il doit demander des informations.

Voici un exemple de configuration de module, ici celui de l'export en base Oracle :

define module{

module_name ToNdodb_Oracle

module_type ndodb_oracle

       database         XE

       user             system

       password         password    ;Yes, default password

oracle_home      /usr/lib/oracle/xe/app/oracle/product/10.2.0/server ;optional

}

Deux paramètres sont obligatoires dans la définition d'un module : module_name et module_type. Le premier permet de retrouver le module dans la configuration des satellites, le second permet au démon de savoir quel fichier .py il doit charger et faire correspondre cette configuration.

Les autres paramètres ne sont pas interprétés par l'Arbiter qui les envoie tels quels au Broker qui les passe au module.

La définition du broker ressemble quant à elle à :

define broker{

       broker_name      broker-All

       address serveur-1

port     7772

       spare    0

       manage_arbiters 1

modules Status-Dat,ToNdodb_Oracle

       }

Le paramètre modules permet de faire le lien avec les modules précédemment définis. manage_arbiters est à définir sur au moins un broker : il l'autorise à aller chercher les informations d'états auprès de l'Arbiter. Ces informations sont principalement des logs.

2.9 La configuration locale des démons

Nous avons vu que les démons ont besoin de dialoguer les uns avec les autres. Pour cela, il faut qu'ils ouvrent des ports d'écoute. Cette configuration est locale à chaque démon, mais heureusement, elle n'a pas vocation à changer dans le temps, contrairement à la configuration globale située aux côtés de l'Arbiter.

Voici un exemple de configuration pour un scheduler situé dans le fichier /usr/local/shinken/etc/schedulerd.cfg. La configuration des pollers, reactionners et brokers est similaire :

[daemon]

workdir=/usr/local/shinken/src/var

pidfile=%(workdir)s/schedulerd.pid

port=7768

host=0.0.0.0

user=nagios

group=nagios

idontcareaboutsecurity=0

Les paramètres notables sont host et idontcareaboutsecurity. Le premier désigne une IP sur laquelle va écouter le démon. Si c'est 0.0.0.0 comme ici, il va écouter sur toutes les interfaces disponibles. idontcareaboutsecurity permet à l'administrateur suicidaire d'autoriser le démon à fonctionner avec des droits root. Si c'est à 1, il sera autorisé à le faire, même si c'est totalement inutile et dangereux. Il se fera légèrement insulter par le programme au passage, mais au moins il acceptera de se lancer.

La configuration de l'Arbiter est quant à elle directement définie dans la configuration globale.

2.10 Échanges entre les satellites

Au final, ces échanges d'informations entre les satellites se résument par le diagramme suivant :

action-queues

Fig. 7 : Échange de jobs

2.11 Des configurations optionnelles

Shinken est prévu pour fonctionner avec une configuration Nagios classique, qui ne définit pas de tels objets arbiter ou scheduler. Ainsi, si l'administrateur le lance sans que ces objets soient présents dans la configuration, il va les créer à la volée avec les valeurs par défaut. L'administrateur se retrouvera avec un système qui fonctionne sur une seule machine et sans haute disponibilité, mais qui a le mérite de fonctionner.

3. Un nouveau niveau : les Realms

3.1 Une trop grande visibilité

L'architecture présentée jusqu'ici, bien qu'intéressante, n'est pas complète. Elle est pratique lorsque l'on a un seul site et que l'on souhaite avoir une supervision distribuée hautement disponible (facilement). Mais un souci se pose avec les sites distants : nous n'avons pas défini sur les pollers auprès de quels schedulers ils vont chercher leur travail. Et pour cause : les pollers, reactionners et brokers accèdent à tous les schedulers sans se poser de question le temps qu'ils sont actifs.

Mais que se passe-t-il avec ce mode de fonctionnement lorsque l'on possède des sites distants ? Il n'est pas acceptable qu'un poller en Chine prenne ses vérifications sur un scheduler en France pour lancer ses sondes sur un serveur américain, par exemple. Les latences entre les différents réseaux sont le plus souvent bien trop importantes pour que le système soit efficace. Définir un nouveau scheduler en Asie n'aidera pas, car comme nous l'avons vu, les pollers prennent le travail de tous, sans exception.

De plus, si un prestataire possède des schedulers/pollers dans plusieurs entreprises, il ne souhaite pas trop qu'un poller de l'une cherche ses vérifications sur l'ordonnanceur d'une autre. La séparation est ici plus organisationnelle que technique.

Il nous faut un moyen de cloisonner un peu les architectures que nous mettons en place, mais sans perdre la facilité d’ajouts de ressources, comme un scheduler ou un poller en plus, et le tout sans sacrifier une administration et une récupération des données centralisées.

C'est justement le rôle des Realms.

3.2 La gestion des lieux : les Realms

3.2.1 Leur rôle

Les Realms (royaume dans la lange de Shakespeare) sont un moyen de faire un pack de satellites. Les hôtes et/ou les groupes d'hôtes vont pouvoir être accrochés à l'un d'eux. Ils seront alors automatiquement dispersés sur les satellites contenus dans ce royaume. Si un hôte est mis dans un royaume différent que celui d'un de ses groupes d'hôtes, c'est la valeur de l'hôte qui prime, même si un avertissement est levé.

Il est important de noter que l'Arbiter n'est pas concerné par cela. Il ne fait pas partie d'un royaume particulier, il n'y a toujours à un instant t qu'un seul Arbiter d'actif qui est en charge de gérer tous les royaumes.

Si plusieurs realms sont définis, il sera nécessaire d'en définir un qui sera celui par défaut pour les hôtes non tagués. Le paramètre utilisé pour cela est default.

L'administration centralisée et la distribution de charge automatique sont toujours assurées avec ce système. Les environnements petits et moyens n'ont pas nécessairement besoin de définir un realm car ils vont tout mettre dans le même. Dans ce cas, s'il n'en définissent pas, Shinken va en créer un à la volée et va tout simplement placer tous les éléments dedans.

3.2.2 Leur définition

La définition d'un realm est simple :

define realm{

       realm_name All

       default          1

}

Le lien entre les satellites et les realms l'est également. Ici, par exemple, pour un reactionner :

define reactionner{

       [...]

       realm    All

       manage_sub_realms 1

}

Pour les hôtes et les groupes d'hôtes, la configuration est toujours aussi simple :

define host{

       [...]

       realm    All

       }

3.3 Les sub-realms

3.3.1 Une hiérarchie de realms

Il nous manque un élément dans notre mini-cahier des charges : la possibilité d'avoir toujours une centralisation des données. Un satellite ne peut être placé que dans un realm et un seul. Comment faire en sorte que nos reactionners et nos brokers puissent toujours accéder à tous les schedulers si c'est le souhait de l'administrateur ?

C'est le rôle des sous-royaumes, ou sub-realms. Leur définition est simple : un realm peut en inclure d'autres avec la propriété realm_members. Les satellites d'un royaume peuvent ou non accéder aux ressources des sous-royaumes suivant leur configuration. Par défaut, les reactionners et les brokers sont configurés pour, les pollers non.

Les hôtes d'un realm seront toujours gérés par les schedulers du royaume en question. Pour eux, la présence de sous-royaumes ne change rien.

De cette manière, un administrateur peut définir un royaume global qui englobe tous les autres. Il contiendra un reactionner et un broker (ainsi que leur spare). Les sous-royaumes seront eux remplis de schedulers et de pollers, suivant la localisation des éléments à surveiller.

3.3.2 La configuration

La configuration des sub-realms se fait avec la propriété realm_members :

define realm{

       realm_name World

realm_members Europe

       default          1

}

define realm{

       realm_name Europe

       default          0

}

3.3.3 Exemple de hiérarchie

Voici un exemple de ce que peut donner une telle architecture dans un très grand environnement :

architecture-global-realm

Fig. 8 : Realm global avec plusieurs sub-realms

4. La mise en place et lancement

4.1 La méthode rapide

Pour les plus impatients d'entre vous, il est possible d'avoir un environnement Shinken déjà configuré. Sur le site du projet se trouve une VM à télécharger et lancer avec son outil de virtualisation favori. Une fois la machine lancée, il suffit de s'y connecter avec le compte shinken/shinken. Il suffit de lancer la commande :

./launch_all.sh

Et ensuite, vous pouvez suivre la supervision des hôtes et services définis par l'interface graphique déjà installée, Ninja. Cet accès se fait par le Web, à l'adresse http://ipdelavm/ninja/, le compte à utiliser est monitor/monitor.

Vous obtenez alors une page semblable à celle-ci :

ninja

Fig. 9 : Interface Ninja avec un backend Shinken

Le fichier README_FIRST.txt aidera les administrateurs à tester un peu le programme avec la configuration proposée.

4.2 La méthode (un peu) plus longue

Pour ceux qui n'aiment pas lancer une VM inconnue, ou qui recherchent ce sentiment si particulier que l'on ressent lors du premier lancement d'un nouveau démon, il reste la méthode par les sources. Bien entendu, si vous avez bien suivi jusqu'ici, vous savez que l'étape de compilation sera rapide : elle n'existe pas.

Les sources du projet s'obtiennent avec la commande :

git clone git://shinken.git.sourceforge.net/gitroot/shinken/shinken

Les seules dépendances du projets sont :

- Python >= 2.6 ;

- Pyro, disponible par votre distribution favorite, ou avec easy_install pyro.

La configuration des démons se passe au niveau des fichiers etc/*d.cfg. Pour un lancement simple, il n'y a pas besoin de les modifier pour l'instant si vous possédez déjà un compte système nommé nagios. Si par contre, vous souhaitez lancer les processus en background, il faudra penser à modifier le paramètre de working directory.

Si vous avez déjà une configuration Nagios, le reste de la configuration sera bref : il suffit de reporter les valeurs status_file et object_cache_file de votre fichier nagios.cfg dans la configuration du module StatusDat du fichier etc/brokers.cfg. Dans un proche avenir, cette étape sera réalisée automatiquement.

Si vous ne possédez pas de configuration Nagios préexistante, il vous en est fournie une d'exemple dans src/etc. Vous devez l'éditer et changer les occurrences de /home/shinken/shinken/src par le chemin du répertoire où se trouvent vos sources.

Le lancement à la main sans mise en tâche de fond nécessite 5 shells, un pour chaque démon.

cd src/

python shinken-scheduler.py

python shinken-poller.py

python shinken-reactionner.py

python shinken-broker.py

python shinken-arbiter.py -c etc/nagios.cfg -c etc/shinken-specific.cfg

Vous devriez avoir cinq programmes pleinement lancés. Vous pouvez suivre l'évolution de l'état de vos hôtes avec le fichier de sortie status_file configuré précédemment.

Vous pouvez lancer les processus en tâche de fond en ajoutant simplement le paramètre -d lors du lancement et avec -c pour le chargement d'un fichier de configuration.

4.3 Aller plus loin

Avec la configuration montée précédemment, vous obtenez un équivalent du Nagios standard, mais sans aucune redondance. L'intérêt de ce programme étant justement les architectures distribuées, nous allons monter rapidement une répartition de charge simple : deux pollers. Cette configuration se passe au niveau du fichier etc/pollers.cfg en ce qui concerne la configuration des liens vus de l'Arbiter. La configuration des démons pour l'écoute se passe dans les fichiers etc/*d.cfg. Chaque démon ayant le sien, et vu que nous avons déjà un poller de configuré, vous pouvez dupliquer le fichier pollerd.cfg en pollerd-2.cfg. Dans ces copies, changez simplement le port afin de ne pas avoir deux démons avec le même port d'écoute, ainsi que le paramètre pidfile afin que ce démon ait son propre fichier de lock. Disons que vous utilisez le port 7999 pour ce nouveau poller.

Dans les fichiers etc/pollerd.cfg, ajoutez simplement le bloc suivant :

define poller{

      poller_name poller-2

      address      localhost

port 7999

}

Relancez maintenant vos démons en ajoutant l'appel suivant :

python shinken-poller.py -c etc/pollerd-2.cfg

Et voilà. Il n'y a rien à ajouter. Votre nouveau poller est opérationnel. Vous pouvez faire de même avec les autres démons. Un bon exemple consiste à ajouter un scheduler en spare, de lancer le tout et de tuer le scheduler maître. Vous verrez alors l'Arbiter crier un peu et distribuer la configuration qui n'est plus gérée au spare. Les satellites se connecteront alors automatiquement à leur nouvelle source d'informations.

5. Et dans le futur ?

Outre des paquets pour les distributions principales et un script de service pour lancer simplement l'application, les améliorations de Shinken sont loin d'être finies. L'architecture étant satisfaisante dans son état actuel, d'autres manques de Nagios vont pouvoir être comblés, comme nous allons le voir ici. Nous prendrons également un peu de hauteur afin de voir où en est le projet Shinken par rapport à Nagios.

5.1 Des modifications d'états à la volée

5.1.1 La situation actuelle

Une fonctionnalité intéressante est la modification d'états à la volée. Par exemple, tous les administrateurs ont des serveurs en production, et d'autres en qualification. Si le niveau d'alerte critique est souhaitable pour les premiers, il n'est pas justifié pour les seconds. Abaisser le niveau critique en simple avertissement pour eux est bien suffisant. De cette manière, si une couleur rouge est visible sur les consoles, les administrateurs seront certains qu'elle concerne un serveur de production, et qu’elle nécessite donc une action immédiate. Si les serveurs de qualifications pouvaient également lever de telles alertes, les administrateurs devraient regarder en détail l'alerte avant de savoir si elle nécessite une action immédiate ou pas.

Avec Nagios, nous sommes obligés pour l'instant de passer par une surcouche de sonde pour obtenir le résultat. C'est typiquement un script shell qui lance la sonde et change le code retour du niveau critique (2) en simple niveau d'avertissement (1). Le problème réside dans la configuration de Nagios. Une telle mise en place multiplie par deux le nombre de commandes définies et de services, ce qui est lourd à gérer.

5.1.2 Une prémisse déjà présente dans Shinken

Shinken dispose déjà d'un embryon de solution pour résoudre cela : les objets result_modulations. Appelés sur les hôtes ou les services, ils permettent de ne pas changer les commandes de supervision, mais d'appliquer une règle de changement avant d'intégrer le résultat de la commande. Un exemple de définition est :

define resultmodulation{

       resultmodulation_name     critical_is_warning           ;required

exit_codes_match 2 ;optionnal, list of code to change

exit_code_modulation 1 ;code that will be put if the code match

modulation_period 24×7 ;period when to apply the modulation

}

Et il se définit simplement dans les hôtes ou les services :

define service{

    […]

    resultmodulations   critical_is_warning

[…]

}

Avec cet exemple, si le code retour de la commande est 2 (exit_codes_match), elle sera changée en 1 (exit_code_modulation). On remarque le paramètre modulation_period : il permet de définir la période de temps où cette modulation doit s'appliquer.

Par exemple, un serveur de paye n'est critique que pendant la période de paye, qui ne dure que quelques jours. De cette manière, l'administrateur définit une période qui est valide tout le temps, sauf ces quelques jours, et n'applique les modulations que sur cette période. Lorsque le serveur est critique, les alertes pourront atteindre ce niveau, mais tout le reste du temps, elles seront de simples avertissements.

Dans le futur, il est prévu de pouvoir changer à la volée la sortie texte des sondes.

5.2 Un moteur de corrélation

Actuellement, avec Nagios, il est possible de définir des relations de dépendances entre les hôtes ou les services. Si ces relations sont pratiques pour ne pas recevoir des alertes inutiles (comme être alerté que le service web ne fonctionne pas alors que c'est la base qui est tombée) qui font perdre du temps lors de la recherche d'erreur, elle ne sont pas aussi puissantes que ce que permet de faire, par exemple, Zabbix avec ses triggers, ni ce qu'offre un SEC.

Il manque un véritable moteur de corrélation dans Nagios, et c'est un des objectifs forts de Shinken dans son futur proche.

5.3 Des envois « passifs » de configurations

Nous avons vu l'architecture distribuée avec Shinken. La configuration globale est située aux côtés de l'Arbiter, qui est chargé de la découper et la redistribuer sur tous les nœuds. Cette distribution se fait à l'initiative de l'Arbiter qui va contacter tous ses petits camarades. Si ce fonctionnement est pratique lorsque l'on se situe au sein de la même entreprise, il peut poser problème lorsqu'un prestataire souhaite mettre un couple scheduler/poller chez un client dont il assure la supervision. Les clients ne sont, en général, pas ravis de devoir ouvrir un port vers un serveur hébergé en interne qui supervise tous les autres.

Il serait ainsi préférable d'offrir la possibilité de définir des satellites comme « passifs » du point de vue de l'Arbiter : au lieu que l'Arbiter envoie la configuration, les satellites chez le client l'interrogent régulièrement afin de savoir s'ils ont une nouvelle configuration, et l'applique si c'est le cas.

Ce mode de fonctionnement n'est pas rédhibitoire du point de vue du code de Shinken, il devrait donc être disponible dans une toute prochaine version.

5.4 Nagios, Icinga, Shinken, Zabbix : une future guerre dans les étoiles ?

5.4.1 Un projet fantôme

Reprenons un peu l'histoire où nous l'avions laissée. Début décembre 2009, Shinken était encore un proof of concept. L'architecture distribuée était fonctionnelle et les performances étaient au rendez-vous : un serveur standard arrive à gérer 150000 vérifications en 5 minutes, là où Nagios n'en gère que 10000, ou 30000 avec toutes les options de tuning activées et l'export en base enlevé. Un mail est envoyé en privé aux auteurs de Nagios afin de leur présenter l'outil et d'avoir leur sentiment sur les idées proposées. Sans réponse, un autre mail est envoyé, à la mailing list du projet cette fois-ci. Il contient une proposition plutôt étonnante : une demande de branche de développement sur Nagios afin d'incorporer le proof of concept et arriver à terme à prendre le meilleur des deux implémentations pour remettre Nagios sur la voie de l'innovation.

De nombreux échanges font suite avec divers membres de la communauté, mais l'auteur principal ne répond pas. L'incorporation n'est pas acceptée, car le code est en Python, langage que les développeurs principaux ne connaissent pas, et sans l'aval de l'auteur, aucun d'eux ne prendra le risque.

5.4.2 La guerre des clones

Shinken se lance donc dans le grand bain, en tant que projet indépendant, mais toujours à l'écoute de son grand frère pour une inclusion future. Peut-être que s'il fait ses preuves tant en termes d'innovation (ce qui ne sera pas complexe) que de stabilité (c'est en test, mais plutôt prometteur), il sera incorporé dans le grand projet Nagios.

Espérons que son architecture lui permette de lutter efficacement face aux mastodontes qui l'entourent. Sa souplesse devrait être un véritable avantage si l'on considère que seule la loi de Darwin s'applique dans le monde impitoyable des logiciels libres.

5.4.3 L'« Enterprise » contre attaque

Une ombre se profile cependant à l'horizon, l'auteur principal de Nagios semble plus intéressé par un cœur Nagios qui n'évolue pas trop plutôt que par un grand chamboulement : lors d'une demande sous forme de lettre ouverte de la communauté sur la direction que semble prendre le projet, l'auteur a annoncé ses desseins : la société éditrice de Nagios est en train de lancer Nagios XI, solution fermée utilisant des briques open source, dont le démon Nagios actuel. L'auteur ne semble plus avoir trop d'intérêt à faire évoluer le cœur, laissant les principales améliorations pour cette solution, sous licence payante.

Nagios semble évoluer vers un modèle 50/50 dans l'avenir proche, comme l'est déjà son concurrent Zenoss : une version « Enterprise » payante et fermée, et une « Community » libre, mais fortement limitée.

5.4.4 Shinken : un nouvel espoir ?

Est-ce un bien ou un mal, je laisse notre Jean-Pierre Troll donner son avis, notamment sur la position de la communauté dans cette histoire. Ceci semble cependant diminuer fortement les chances d'inclusion de l'implémentation Shinken pour Nagios. Sans son grand frère, Shinken sera seul avec le fork Icinga à prendre la relève de Nagios dans le monde des logiciels libres. L'avenir des logiciels libres de supervision est incertain, mais une chose est sûre : les administrateurs ne pourront, à terme, qu'y gagner de cette lutte, en obtenant des outils libres toujours plus performants et efficaces. Et après tout, c'est bien ce qui compte.




Articles qui pourraient vous intéresser...

Scikit-image, une alternative à OpenCV pour la reconnaissance d'images

Magazine
Marque
GNU/Linux Magazine
Numéro
244
Mois de parution
janvier 2021
Domaines
Résumé

Une fois n'est pas coutume, nous allons découvrir et utiliser une alternative à OpenCV, scikit-image communément appelé skimage. Nous implémenterons la reconnaissance d'images avec la méthode des histogrammes de gradients orientés (HOG : Histogram of Oriented Gradients) associée à une machine à vecteurs de support (SVM : Support Vector Machine). Cette méthode est employée dans bien des applications telles que l'automobile, pour la détection de piétons [1].

Jenkins, Docker et Kubernetes pour déployer en CI/CD

Magazine
Marque
Linux Pratique
Numéro
123
Mois de parution
janvier 2021
Domaines
Résumé

La mise en place d'un processus d'intégration continue et de déploiement continu nécessite une réflexion sérieuse avant de la concrétiser dans la vraie vie d'une organisation. La diversité des méthodes agiles, la panoplie des outils DevOps disponible sur le marché et le choix de l'infrastructure sous-jacente pour créer vos projets nécessitent de prendre du recul avant de se lancer. Découvrez dans cet article comment créer un CI/CD.