Il y a peu de temps de ça, j'ai eu à mettre en place un suivi des PDUs (Power Distribution Unit) pour un de mes clients. En faisant bien attention de ne pas réinventer la roue, je me suis donc appuyé sur le script développé par boreal labs (http://www.boreal-labs.com/joomla/index.php/en/downloads-menu/view.download/18-pdu/9-checkpwnetrpduload.html). Ci-dessous un petit exemple d'exécution de ce dernier :
./check_pwnet_rpdu_load.pl -H 192.168.0.1 -C public -b 1,2 -m A -w n,12 -c 16,o
PWNET_RPDU_LOAD OK - PDU 'PDU-IT-R5-A' bank #1 load = 3.3A; bank #2 load = 0.0A; | PDUBank1Load=3.3A;13.0;16.0;0;16 PDUBank2Load=0.0A;12.0;16.0;0;16
Une fois intégré dans nagios, mon ami PNP a commencé à produire le résultat suivant :
Seulement voilà, certains PDUs avaient un capteur de température/humidité et j'avais besoin de faire un suivi là dessus. C'est donc à cette occasion, j'ai écrit un script permettant de remonter ces informations. Ce script est disponible à l'adresse suivante : http://code.google.com/p/plugin-nagios-yannig/source/browse/trunk/pdu/check_pdu_sensors.pl
Il vous faudra récupérer la mib du constructeur (le fichier powernet405.mib) et le rendre disponible à snmpwalk (en renseignant son emplacement avec la variable d'environnement MIBDIRS par exemple). Ci-dessous un exemple de test de communication :
./check_pdu_sensors.pl -H 192.168.0.1 -C public
Temperature/Humidity sensor status is OK - temperature = 22.4°C, humidity = 56%|temperature=22.4 humidity=56%
Ce dernier va vous renvoyer la température et/ou l'humidité (fonction du type de capteur sur votre matériel) à un instant T de votre PDU. Le résultat prend la forme suivante :
J'ai ensuite intégré tout ceci dans nagios et l'ami PNP a commencé à produire des graphiques assez sympas. En voici ci-dessous un petit exemple de suivi sur 2 semaines de l'humidité :
Les trucs sur lesquels je bosse en tant qu'ingénieur Unix et mes lubies du moment.
Affichage des articles dont le libellé est perl. Afficher tous les articles
Affichage des articles dont le libellé est perl. Afficher tous les articles
vendredi 26 octobre 2012
mercredi 3 octobre 2012
Mise en place selenium
Ces derniers temps, on m'a demandé de mettre en place de scénario de surveillance sur une application typiquement horrible : code HTML horrible, Internet Explorer only etc.
Bref, j'ai donc commencé à vouloir faire ça en cucumber mais je me suis rapidement frotté à des problèmes mon cher concombre masqué refusant catégoriquement mes noms de formulaires fantaisiste (il faut dire qu'on trouve des dollars ('$') dedans ...).
Bien triste, j'ai commencé à chercher quelque chose d'autre qui pourrait répondre à mon besoin et je suis tombé sur selenium (http://seleniumhq.org/) et son IDE (qui est une simple extension à installer dans firefox).
J'ai commencé à faire joujou avec l'IDE et - malgré un rendu HTML catastrophique - j'ai réussi à faire un scénario de test avec Firefox.
En trifouillant un peu, j'ai vu qu'il existait un serveur selenium (un process java) et qu'il pouvait tourner dans un serveur X virtuel. Devant tant de beauté, j'ai donc commencé à mettre ça en place :D.
apt-get install python-pip python-dev build-essential
Maintenant que nous avons pip, nous pouvons procéder à l'installation de la librairie selenium :
pip install -U selenium
Passons maintenant à la suite (et y'a du monde !)
DISPLAY=:1 Xvfb :1 -screen 0 1024x768x24
Bien penser à le rendre utilisable depuis n'importe où avec la commande xhost :
DISPLAY=:1 xhost +
ATTENTION : L'utilisation de xhost + va rendre le serveur X visible depuis l'extérieur !!! Il est conseillé de mettre en place un parefeu pour bloquer les accès externes.
L'installation se fait avec un apt-get install xvfb (et x11-server-utils pour disposer de l'utilitaire xhost)
Récupérer ensuite la dernière version de selenium serveur sous la forme d'un JAR. Vous pouvez ensuite le lancer avec la ligne de commande suivante :
export DISPLAY=:1
java -Djava.security.egd=file:/dev/./urandom \
-jar /path/to/jar/selenium-server-standalone-2.25.0.jar \
-browserSessionReuse
A noter la présence de l'option -browserSessionReuse qui permet d'éviter de relancer le navigateur à chaque lancement de scénario et l'option biscornu java.security.egd qui permet de passer du device aléatoire /dev/random (qui est lent) à /dev/urandom qui lui n'utilise pas l'entropie du système pour fonctionner mais un générateur de nombre aléatoire.
python mon_scenario.py
.
----------------------------------------------------------------------
Ran 1 test in 4.051s
OK
Magnifique non ? Tout à fait mais ça ne vous dit pas ce que vous allez en faire dans votre nagios.
Bon, si vous insistez ... Il faut récupérer le script check_selenium.pl et lancer ensuite la sonde de la manière suivante :
/emplacement/scripts/check_selenium.pl --script \
/emplacement/de/mon/scenario.py \
--label "Le test de ma super application"
De là, vous devriez obtenir la sortie suivante :
Selenium test OK (Le test de ma super application)|time=3.180s test_count=1
Elle est pas belle la vie ?
Bref, j'ai donc commencé à vouloir faire ça en cucumber mais je me suis rapidement frotté à des problèmes mon cher concombre masqué refusant catégoriquement mes noms de formulaires fantaisiste (il faut dire qu'on trouve des dollars ('$') dedans ...).
Bien triste, j'ai commencé à chercher quelque chose d'autre qui pourrait répondre à mon besoin et je suis tombé sur selenium (http://seleniumhq.org/) et son IDE (qui est une simple extension à installer dans firefox).
J'ai commencé à faire joujou avec l'IDE et - malgré un rendu HTML catastrophique - j'ai réussi à faire un scénario de test avec Firefox.
En trifouillant un peu, j'ai vu qu'il existait un serveur selenium (un process java) et qu'il pouvait tourner dans un serveur X virtuel. Devant tant de beauté, j'ai donc commencé à mettre ça en place :D.
Pré-requis python
Comme par la suite je vais générer des scripts au format python, nous allons devoir installer la librairie python permettant de communiquer avec selenium. Ici, rien de bien compliqué, un coup de apt-get pour installer le nécessaire :apt-get install python-pip python-dev build-essential
Maintenant que nous avons pip, nous pouvons procéder à l'installation de la librairie selenium :
pip install -U selenium
Passons maintenant à la suite (et y'a du monde !)
X11 Virtual frame buffer (miam !)
Ce cher Xvfb ! Toujours un petit moment émouvant quand je le croise ! Pour le lancer, il faut simplement utiliser la ligne de commande suivante :DISPLAY=:1 Xvfb :1 -screen 0 1024x768x24
Bien penser à le rendre utilisable depuis n'importe où avec la commande xhost :
DISPLAY=:1 xhost +
ATTENTION : L'utilisation de xhost + va rendre le serveur X visible depuis l'extérieur !!! Il est conseillé de mettre en place un parefeu pour bloquer les accès externes.
L'installation se fait avec un apt-get install xvfb (et x11-server-utils pour disposer de l'utilitaire xhost)
Installation de Firefox
Par la suite, nous utiliserons firefox pour faire nos tests. Donc rien de bien fameux si ce n'est un apt-get install firefox (à remplacer par iceweasel si vous êtes sur Debian).Mise en place de Selenium
On arrive enfin au coeur du sujet. Selenium est un serveur qui s'appuie sur un jar java pour se lancer. Donc de manière logique, il va vous falloir un java fonctionnel. Je vous passe les détails, vous faîtes comme vous voulez.Récupérer ensuite la dernière version de selenium serveur sous la forme d'un JAR. Vous pouvez ensuite le lancer avec la ligne de commande suivante :
export DISPLAY=:1
java -Djava.security.egd=file:/dev/./urandom \
-jar /path/to/jar/selenium-server-standalone-2.25.0.jar \
-browserSessionReuse
A noter la présence de l'option -browserSessionReuse qui permet d'éviter de relancer le navigateur à chaque lancement de scénario et l'option biscornu java.security.egd qui permet de passer du device aléatoire /dev/random (qui est lent) à /dev/urandom qui lui n'utilise pas l'entropie du système pour fonctionner mais un générateur de nombre aléatoire.
Test de notre premier scénario
À l'aide de l'IDE selenium, nous avons enregistré notre scénario. Nous allons maintenant exporter ce dernier au format Python 2 / unittest / Remote Control. Voici ce à quoi ça devrait ressembler :from selenium import selenium import unittest, time, re class sites(unittest.TestCase): def setUp(self): self.verificationErrors = [] self.selenium = selenium("localhost", 4444, "*chrome", "http://monsite/") self.selenium.start() def test_sites(self): sel = self.selenium sel.open("/ma_page") sel.type("id=un_champ", "une_valeur") sel.type("id=un_autre_champ", "une_autre_valeur") sel.click("id=id_d_un_lien") sel.wait_for_page_to_load("30000") def tearDown(self): self.selenium.stop() self.assertEqual([], self.verificationErrors) if __name__ == "__main__": unittest.main()Lançons maintenant ce beau script depuis la machine faisant tourner selenium :
python mon_scenario.py
.
----------------------------------------------------------------------
Ran 1 test in 4.051s
OK
Magnifique non ? Tout à fait mais ça ne vous dit pas ce que vous allez en faire dans votre nagios.
(Des)intégrations dans nagios/Shinken
Comment ça, vous voulez le script qui analyse la sortie de tout ça et l'insert directement dans nagios ? Je vous trouve un peu exigeant quand même !Bon, si vous insistez ... Il faut récupérer le script check_selenium.pl et lancer ensuite la sonde de la manière suivante :
/emplacement/scripts/check_selenium.pl --script \
/emplacement/de/mon/scenario.py \
--label "Le test de ma super application"
De là, vous devriez obtenir la sortie suivante :
Selenium test OK (Le test de ma super application)|time=3.180s test_count=1
Elle est pas belle la vie ?
mardi 2 octobre 2012
Suivi des interfaces d'un switch CISCO sous Nagios/Shinken
Depuis quelques jours, je travaille sur la mise en place d'un Shinken chez un client. A cette occasion, on m'a demandé de faire un suivi des switchs de la boîte et notamment le débit de chaque port.
Comme je suis quelqu'un de relativement paresseux (je n'avais pas trop envie de me déclarer les 48 ports des 200 switchs à la main). J'ai donc rapidement pensé à un script qui me permettrait de déclarer automatiquement ces surveillances. Et comme je suis un mec super sympas qui adore raconter sa vie, je vais vous en faire profiter bande de veinards !
Pour se faire, nous allons utiliser les MIBs SNMP des switchs CISCO qui ont la bonne idée de proposer tout un tas de chose vachement intéressante (oui, enfin ... pour un administrateur d'outils de surveillance). Nous allons voir notamment l'OID 1.3.6.1.2.1.2.2.1.2 qui va nous renvoyer la liste des interfaces du switch :
$ snmpwalk -c ecalyptus -v 2c 10.1.1.1 1.3.6.1.2.1.2.2.1.2
iso.3.6.1.2.1.2.2.1.2.1 = STRING: "FastEthernet1"
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "TenGigabitEthernet1/1"
iso.3.6.1.2.1.2.2.1.2.3 = STRING: "TenGigabitEthernet1/2"
iso.3.6.1.2.1.2.2.1.2.4 = STRING: "TenGigabitEthernet1/3"
iso.3.6.1.2.1.2.2.1.2.5 = STRING: "TenGigabitEthernet1/4"
iso.3.6.1.2.1.2.2.1.2.6 = STRING: "GigabitEthernet3/1"
iso.3.6.1.2.1.2.2.1.2.7 = STRING: "GigabitEthernet3/2"
iso.3.6.1.2.1.2.2.1.2.8 = STRING: "GigabitEthernet3/3"
iso.3.6.1.2.1.2.2.1.2.9 = STRING: "GigabitEthernet3/4"
iso.3.6.1.2.1.2.2.1.2.10 = STRING: "GigabitEthernet3/5"
iso.3.6.1.2.1.2.2.1.2.11 = STRING: "GigabitEthernet3/6"
iso.3.6.1.2.1.2.2.1.2.12 = STRING: "GigabitEthernet3/7"
iso.3.6.1.2.1.2.2.1.2.13 = STRING: "GigabitEthernet3/8"
iso.3.6.1.2.1.2.2.1.2.14 = STRING: "GigabitEthernet3/9"
iso.3.6.1.2.1.2.2.1.2.15 = STRING: "GigabitEthernet3/10"
[...]
Nous allons nous servir de cette sortie pour générer notre surveillance. Pour cela, nous allons utiliser le script perl suivant :
Ci-dessous un exemple de surveillance sur un switch CISCO (du type WS-C2960-24PC-L) :
define hostgroup{
hostgroup_name WS-C2960-24PC-L
alias Switchs Cisco WS-C2960-24PC-L
}
Comme je suis quelqu'un de relativement paresseux (je n'avais pas trop envie de me déclarer les 48 ports des 200 switchs à la main). J'ai donc rapidement pensé à un script qui me permettrait de déclarer automatiquement ces surveillances. Et comme je suis un mec super sympas qui adore raconter sa vie, je vais vous en faire profiter bande de veinards !
Pour se faire, nous allons utiliser les MIBs SNMP des switchs CISCO qui ont la bonne idée de proposer tout un tas de chose vachement intéressante (oui, enfin ... pour un administrateur d'outils de surveillance). Nous allons voir notamment l'OID 1.3.6.1.2.1.2.2.1.2 qui va nous renvoyer la liste des interfaces du switch :
$ snmpwalk -c ecalyptus -v 2c 10.1.1.1 1.3.6.1.2.1.2.2.1.2
iso.3.6.1.2.1.2.2.1.2.1 = STRING: "FastEthernet1"
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "TenGigabitEthernet1/1"
iso.3.6.1.2.1.2.2.1.2.3 = STRING: "TenGigabitEthernet1/2"
iso.3.6.1.2.1.2.2.1.2.4 = STRING: "TenGigabitEthernet1/3"
iso.3.6.1.2.1.2.2.1.2.5 = STRING: "TenGigabitEthernet1/4"
iso.3.6.1.2.1.2.2.1.2.6 = STRING: "GigabitEthernet3/1"
iso.3.6.1.2.1.2.2.1.2.7 = STRING: "GigabitEthernet3/2"
iso.3.6.1.2.1.2.2.1.2.8 = STRING: "GigabitEthernet3/3"
iso.3.6.1.2.1.2.2.1.2.9 = STRING: "GigabitEthernet3/4"
iso.3.6.1.2.1.2.2.1.2.10 = STRING: "GigabitEthernet3/5"
iso.3.6.1.2.1.2.2.1.2.11 = STRING: "GigabitEthernet3/6"
iso.3.6.1.2.1.2.2.1.2.12 = STRING: "GigabitEthernet3/7"
iso.3.6.1.2.1.2.2.1.2.13 = STRING: "GigabitEthernet3/8"
iso.3.6.1.2.1.2.2.1.2.14 = STRING: "GigabitEthernet3/9"
iso.3.6.1.2.1.2.2.1.2.15 = STRING: "GigabitEthernet3/10"
[...]
Nous allons nous servir de cette sortie pour générer notre surveillance. Pour cela, nous allons utiliser le script perl suivant :
#!/usr/bin/perl use strict; open(MODEL, "modele.txt"); mkdir("modeles") if(!-d("modeles")); while(Ce script attend en entrée un fichier de paramètre (modele.txt) et nous donne en sortie des fichiers de configuration au format nagios dans le sous-répertoire modeles. Il nous reste maintenant à prendre ces fichiers et les intégrer dans la configuration de notre nagios/Shinken.) { chomp(); my($modele, $ip) = split(/;/); my @interfaces = `snmpwalk -c ecalyptus -v 2c $ip 1.3.6.1.2.1.2.2.1.2`; open(MODEL_CFG, ">modeles/switch-$modele.cfg"); foreach(@interfaces) { if(/iso.3.6.1.2.1.2.2.1.2.(\d+) = STRING: "(.*Ethernet.*)"/) { my ($id, $interface) = ($1, $2); print MODEL_CFG "define service { hostgroup_name $modele use generic-service service_description $interface check_command check_port_usage!$id!6000!8000 } \n"; } } close(MODEL_CFG); } close(MODEL);
Ci-dessous un exemple de surveillance sur un switch CISCO (du type WS-C2960-24PC-L) :
define service { hostgroup_name WS-C2960-24PC-L use generic-service service_description FastEthernet0/1 check_command check_port_usage!10001!6000!8000 } [...] define service { hostgroup_name WS-C2960-24PC-L use generic-service service_description GigabitEthernet0/2 check_command check_port_usage!10102!6000!8000 }Il reste ensuite à déclarer un hostgroup ad-hoc avec un template de serveur comme suit :
define hostgroup{
hostgroup_name WS-C2960-24PC-L
alias Switchs Cisco WS-C2960-24PC-L
}
define host {
name switch-WS-C2960-24PC-L
use generic-switch
alias Ensemble des switchs Cisco WS-C2960-24PC-L
hostgroups Switch,WS-C2960-24PC-L
icon_image vendors/cisco.png
register 0
}
Et nous pouvons déclarer maintenant des switchs utilisant le template switch-WS-C2960-24PC-L. Ces derniers viendront directement avec la surveillance automatique de tous leurs ports.
mercredi 6 octobre 2010
Import des données de ndoutils dans pnp4nagios
Il y a de ça 5 ou 6 mois, j'ai procédé à un refresh à notre infrastructure de suivi nagios. A l'époque nous utilisions un nagios couplé avec NDOUtils pour faire notre suivi de tendance des machines. J'avais par ailleurs créé un plugin permettant de grapher tout ceci en me basant sur la bibliothéque JPGraph.
Malheureusement, entre les problèmes sur la base de données, le fait que je sois sur Solaris (chouette encore un truc à compiler), les problèmes liés au broker nagios (pourquoi ce foutu machin ne veut pas se reconnecter à la base !!!), les problèmes de performance de la base (j'avais mis en place un système de rotation de la table nagios_servicechecks pour m'affranchir des problèmes de dégradation des performances avec le temps), la taille de tout ceci (200 Mo de place par jour pour 600 services !) et le plugin de graph à maintenir, j'ai fini par péter un cable !
Bref, à l'occasion d'un plan de refresh de ma machine, je suis tombé sur pnp4nagios et là, j'ai sérieusement réfléchi à me débarrasser de NDOUtils. En revanche, un point m'embêter : perdre mon historique de 100 jours de l'ancienne base MySQL. J'ai donc à ce moment pensé à utiliser les possibilités d'insertion en mode bulk de pnp4nagios afin de reconstituer mon historique.
Au démarrage, j'ai procédé par une extraction via un ensemble de scripts shells. J'ai ensuite procédé à un refactoring de ce script afin de le réécrire en perl que j'ai ensuite proposé à l'équipe de pnp4nagios. Ils m'ont simplement proposé de le déposer sur leur wiki à l'emplacement suivant.
Le script en question s'appelle ndo2pnp.pl et vous trouverez ci-dessous l'aide en ligne disponible sur l'outil :
Globalement, pour procéder à votre export/import, il faut suivre les étapes suivantes :
Quoi ? C'est tout ! Euh, juste une petite précision : l'import a duré 4 jours sur ma machine de production :). Un conseil : essayez de faire des extracts machine par machine (avec l'option --machines MAMACHINEAEXTRAIRE ou --services MESSERVICESAEXTRAIRE que j'ai oublié de documenté d'ailleurs ... Pas beau !). Les imports seront du coup moins long à faire (et éventuellement en parallèle) et peuvent vous donner une idée du résultat final sans avoir à vous coltiner l'intégralité de l'import de vos données.
Le résultat de tout ceci se trouve ci-dessous :

Toute la partie de décembre à février et le résultat de l'import (plus les quelques jours parasites d'octobre et novembre, date à laquelle nous avions eu des soucis avec la base MySQL). Vous remarquerez qu'entre temps, la base s'est alimentée avec de nouvelles valeurs.
Malheureusement, entre les problèmes sur la base de données, le fait que je sois sur Solaris (chouette encore un truc à compiler), les problèmes liés au broker nagios (pourquoi ce foutu machin ne veut pas se reconnecter à la base !!!), les problèmes de performance de la base (j'avais mis en place un système de rotation de la table nagios_servicechecks pour m'affranchir des problèmes de dégradation des performances avec le temps), la taille de tout ceci (200 Mo de place par jour pour 600 services !) et le plugin de graph à maintenir, j'ai fini par péter un cable !
Bref, à l'occasion d'un plan de refresh de ma machine, je suis tombé sur pnp4nagios et là, j'ai sérieusement réfléchi à me débarrasser de NDOUtils. En revanche, un point m'embêter : perdre mon historique de 100 jours de l'ancienne base MySQL. J'ai donc à ce moment pensé à utiliser les possibilités d'insertion en mode bulk de pnp4nagios afin de reconstituer mon historique.
Au démarrage, j'ai procédé par une extraction via un ensemble de scripts shells. J'ai ensuite procédé à un refactoring de ce script afin de le réécrire en perl que j'ai ensuite proposé à l'équipe de pnp4nagios. Ils m'ont simplement proposé de le déposer sur leur wiki à l'emplacement suivant.
Le script en question s'appelle ndo2pnp.pl et vous trouverez ci-dessous l'aide en ligne disponible sur l'outil :
$ ./ndo2pnp.pl --help
Usage :
-h --help Display this message.
--version Display version then exit.
-v --verbose Verbose run.
-u --user ndouser Log on to database with ndouser (default root).
-p --pass passwd Use passwd to logon (default gbu2kfe).
-t --type dbtype Change database type (default mysql).
--host dbhost Use dbhost (default localhost).
--dbname db Use db for ndo database name (default ndoutils).
--list-machine Display machine definition in ndo database.
--list-service Show services defined.
--export-as-pnp Export ndo content as a bulk file used by process_perfdata.pl.
>
Globalement, pour procéder à votre export/import, il faut suivre les étapes suivantes :
- Extraction du contenu de la base : ./ndo2pnp.pl --user mysql_user -p mysql_pass --export-as-pnp > /tmp/perfdata.bulk
- Import de l'extraction :/usr/share/pnp4nagios/libexec/process_perfdata.pl -b /tmp/perfdata.bulk --timeout 0
Quoi ? C'est tout ! Euh, juste une petite précision : l'import a duré 4 jours sur ma machine de production :). Un conseil : essayez de faire des extracts machine par machine (avec l'option --machines MAMACHINEAEXTRAIRE ou --services MESSERVICESAEXTRAIRE que j'ai oublié de documenté d'ailleurs ... Pas beau !). Les imports seront du coup moins long à faire (et éventuellement en parallèle) et peuvent vous donner une idée du résultat final sans avoir à vous coltiner l'intégralité de l'import de vos données.
Le résultat de tout ceci se trouve ci-dessous :

Toute la partie de décembre à février et le résultat de l'import (plus les quelques jours parasites d'octobre et novembre, date à laquelle nous avions eu des soucis avec la base MySQL). Vous remarquerez qu'entre temps, la base s'est alimentée avec de nouvelles valeurs.
jeudi 24 juin 2010
Problème de performance avec pnp4nagios sous Solaris
Depuis quelques temps déjà, je devais mettre en place pnp4nagios combiné à un nagios 3.2 sur une nouvelle machine. Auparavant, je passais par une machine un peu vieillotte (un sunfire V210 avec 2 Go de mémoire) que je devais remplacer par une plus récente (à base de M5000 Sun). L'ancienne plateforme passait par un nagios combiné avec ndoutils (un backend de stockage des données de performance sous MySQL). Cette plateforme était très contraignante pour plusieurs raisons :
Rien de bien choquant mais le problème est que sous Solaris la version de RRD venant de sunfreeware s'installe dans /usr/local. Problème, ce dernier est livré avec un binding perl prévu pour la version 5.8.8. Malheureusement, la version installée par défaut (ie dans le répertoire /usr/bin) est une version 5.8.4 et n'est pas en mesure d'utiliser la bibliothéque native perl de RRD.
- Plugin de génération de graphique maison (c'est votre serviteur qui avait écrit ça)
- Scripts de gestion du contenu de la table nagios_servicechecks : je découpais cette table en journée pour pouvoir supporté le volume de données (environ 200 Mo/jour et 17 Go d'historique)
- Lenteur de la solution : nagios et le module de base de données (ndo2db) n'était pas très consommateur mais en revanche, la base MySQL était très consommatrice de ressource disque et CPU.
Bref, pour toutes ces raisons et après un rapide tour des solutions existantes, nous avions décidé de partir sur l'excellent plugin pnp4nagios pour l'historisation. Avec ce plugin, plus de serveur MySQL, moins d'IO, plus de script de maintenance. Bref, que du bonheur.
C'est donc assez confiant qu'il y a quelques jours que nous avons procédé à la mise en production. Mais comme toujours, j'ai eu une mauvaise surprise lors de la migration. Lors de la fin de la bascule de tous nos anciens services sur la nouvelle (environ 900 services), j'ai commencé à voir des messages d'erreurs m'indiquant un time out lors du lancement du script process_perfdata.pl au bout de 5 secondes. En y regardant de plus près, j'ai constaté que le timeout était fixé par la directive perfdata_timeout=5 et en urgence, j'ai donc fixé le timeout à 30 s.
Une fois ce contournement mis en place, j'ai pu regarder en détail le problème. J'ai notamment constaté que la machine passait énormément de temps à faire ses mises à jour. En rajoutant quelques traces, je me suis rendu compte que le script process_perfdata.pl n'utilisait pas la bibliothéque native perl RRD mais le binaire rrd ! Suite à quelques tests que j'avais pu faire il y a quelques temps sur les deux modes de fonctionnement, j'ai essayé de voir si le problème ne pouvait pas venir de là.
Après un coup d'oeil à la configuration de nagios et je suis tombé sur cette partie :
define command {
command_name process-service-perfdata-file
command_line /bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl --bulk=/var/nagios/service-perfdata
}
define command {
command_name process-host-perfdata-file
command_line /bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA --bulk=/var/nagios/host-perfdata
}
Bref, j'ai donc changé la version de perl par celle se trouvant dans /usr/local/bin :
define command {Un coup d'arrêt relance et après quelques temps, j'ai obtenu une nette diminution au niveau des temps de traitement de perfdata :
command_name process-service-perfdata-file
command_line /usr/local/bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl --bulk=/var/nagios/service-perfdata
}
define command {
command_name process-host-perfdata-file
command_line /usr/local/bin/perl /usr/share/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA --bulk=/var/nagios/host-perfdata
}
Zoom sur la partie basse :
C'est ici qu'on constate tout l'intérêt de l'utilisation de la bibliothéque native RRD : on est passé à des temps de traitement d'environ 30s à des temps de traitement de l'ordre de la seconde.
lundi 10 mai 2010
Test du module RRD perl
Je suis en ce moment en train de finir mes scripts de migration de la base MySQL ndoutils vers des bases RRD gérées par pnp4nagios.
Globalement, le script est terminé et je suis juste en train de faire quelques tests. A cette occasion, j'ai voulu connaître le différentiel de performance entre RRD via le binaire et via la bibliothèque Perl.
Pour se faire, j'ai donc écrit le script suivant :
En gros, le script génère une sinusoïde que j'affiche ensuite sous gwenview (prenez votre lecteur d'image préféré).
Un rapide test nous donne le résultat suivant :
* via l'utilisation de la bibliothèque :
* via l'utilisation des binaires :
Donc 1 seconde contre environ 3 minutes dans le second cas. On va donc passer par la bibliothèque !
Globalement, le script est terminé et je suis juste en train de faire quelques tests. A cette occasion, j'ai voulu connaître le différentiel de performance entre RRD via le binaire et via la bibliothèque Perl.
Pour se faire, j'ai donc écrit le script suivant :
#!/usr/bin/perl
use RRDs;
$use_system = 1;
$current = time();
$step = 30;
$range = 3600 * 24 * 7;
$start = $current - $range;
print "Début : ".scalar(localtime())."\n";
if($use_system) {
system("rrdtool create test.rrd --start $start --step $step DS:valeur_test:GAUGE:600:U:U RRA:AVERAGE:0.5:1:".($range / $step));
} else {
RRDs::create("test.rrd", "--start", $start, "--step", $step, "DS:valeur_test:GAUGE:600:U:U", "RRA:AVERAGE:0.5:1:".($range / $step));
}
$j = 0.;
$| = 1;
$i = 0;
for($t = $start; $t < $current; $t += $step) {
$value = int(200.5 + cos($j) * 100.);
if($use_system) {
system("rrdtool update test.rrd $t:$value");
} else {
RRDs::update("test.rrd", "$t:$value");
}
$j += 0.001;
$i++;
}
print "Insertion de $i valeurs\n";
if($use_system) {
system("rrdtool graph speed.png --start $start --end $current DEF:def=test.rrd:valeur_test:AVERAGE LINE1:def#000000 -w 1000 -h 400");
} else {
RRDs::graph("speed.png", "--start", $start, "--end", $current,
"DEF:def=test.rrd:valeur_test:AVERAGE", "LINE1:def#000000", "-w", 1000, "-h", 400);
}
print "Fin : ".scalar(localtime())."\n";
system("gwenview speed.png");
En gros, le script génère une sinusoïde que j'affiche ensuite sous gwenview (prenez votre lecteur d'image préféré).
Un rapide test nous donne le résultat suivant :
* via l'utilisation de la bibliothèque :
drayan@robinet:~/nagios/RRD$ ./generate_rrd.pl
Début : Mon May 10 22:45:56 2010
Insertion de 20160 valeurs
Fin : Mon May 10 22:45:57 2010
* via l'utilisation des binaires :
Début : Mon May 10 22:46:08 2010
ERROR: test.rrd: illegal attempt to update using time 1272919568 when last update time is 1272919568 (minimum one second step)
Insertion de 20160 valeurs
1081x449
Fin : Mon May 10 22:48:57 2010
Donc 1 seconde contre environ 3 minutes dans le second cas. On va donc passer par la bibliothèque !
Inscription à :
Articles (Atom)