Affichage des articles dont le libellé est nagios. Afficher tous les articles
Affichage des articles dont le libellé est nagios. Afficher tous les articles

mercredi 24 juillet 2013

Packager NSClient++ sous Windows (64 bits) à l'aide de puppet

Bon, pas la peine d'en rajouter sur le titre, j'ai honte. Mais bon voilà, j'avais commencé à vouloir packager NSClient++ avec l'OS alternatif propriétaire (avec ce plugin), et je me suis rendu compte que le package NSClient++ était réinstallé tout le temps. J'ai donc voulu savoir pourquoi.

En effet, en lançant l'application du catalogue sur mon noeud, j'avais systématiquement ce message :

Notice: /Stage[main]/Nscp/Package[nscp]/ensure: created
Notice: /Stage[main]/Nscp/File[C:\Program Files\NSClient++\nsclient.ini]/content:

Info: /Stage[main]/Nscp/File[C:\Program Files\NSClient++\nsclient.ini]: Filebucketed C:/Program Files/NSClient++/nsclient.ini to main with sum e3daba1
4bc76433649a9c4af706042ac
Notice: /Stage[main]/Nscp/File[C:\Program Files\NSClient++\nsclient.ini]/content: content changed '{md5}e3daba14bc76433649a9c4af706042ac' to '{md5}38b
2bb3dbe8530f33d983ccfd8394628'
Info: /Stage[main]/Nscp/File[C:\Program Files\NSClient++\nsclient.ini]: Scheduling refresh of Service[nscp]
Notice: /Stage[main]/Nscp/Service[nscp]: Triggered 'refresh' from 1 events
Notice: Finished catalog run in 11.64 seconds

En gros, mon package nscp était constamment réinstallé et ce dernier venait également mettre à jour le fichier nsclient.ini. Je me suis donc dit que le package n'avait pas le bon nom et qu'il fallait que je trouve le bon. Après avoir essayé NSClient++, NSClientpp, j'en ai eu marre de chercher et je me suis posé la question de savoir comment avoir le nom de ce fameux package. C'est là que j'ai découvert l'existence de la commande puppet resource package. Ci-dessous un extrait de la sortie de cette commande :

[...]
package { 'NSClient++ (x64)':
  ensure => 'installed',
}
package { 'Puppet Enterprise':
  ensure => 'installed',
}
[...]

J'avais enfin le nom de mon package ('NSClient++ (x64)') et du coup, NSClient arrêtait de s'installer systématiquement et donc, le fichier nsclient.ini n'était plus à mettre à jour. En gros, mon agent n'avait plus rien à faire. Bonne nouvelle donc !


mercredi 31 octobre 2012

Thruk une alternative à l'interface Web de Nagios

Il était une fois un moteur nagios ...

Si comme moi vous avez été amené a mettre en oeuvre plusieurs nagios, vous avez sûrement dû vous frotter a son interface Web a base de cgi et de fichier plat exporter toutes les 10 secondes.

Ne crachons pas dans la soupe, cette interface reste très bien pour une petite installation.

Malheureusement, avec l'évolution des besoins en supervision, il devient de plus en plus difficile de se contenter de cette interface. En vrac, on va donner les éléments suivants :
  • Interface vieillissante qui (en dehors des nouveaux CSS des dernières version de nagios) n'a plus évolué depuis de nombreuses années ;
  • Nécessité d'héberger les CGI sur la même machine que le moteur nagios ;
  • Overhead d'écriture du fichier status.dat ;
  • Désynchronisation de l'interface avec le moteur nagios (pour lancer un test immédiat - même dans le cas d'un test très court - l'interface vous rend la main tout de suite et vous devez attendre le lancement du test + le temps de rafraîchissement du fichier status.dat) ;
  • Explosion des temps de réponse dans le cas d'une grosse installation ;
  • Dans le cas où vous auriez plusieurs nœuds nagios, vous devez vous connecter sur la bonne interface pour consulter votre serveur.

Origine de Thruk

Thruk est donc un projet qui a démarré sur ce constat afin d'offrir une alternative sans pour autant dérouté complètement les utilisateurs en reprenant - dans les grandes lignes - l'aspect de l'ancienne interface. En réalité, cette interface apporte des améliorations très intéressantes par rapport à l'ancienne interface avec notamment les points suivants :
  • Possibilité de déporter l'interface de consultation sur un serveur distant ;
  • Possibilité de fédérer plusieurs noeuds nagios dans la même interface ;
  • Compatibilité avec n'importe quel moteur du moment que ce dernier supporte Livestatus (Shinken, Icinga, centreon engine, check_mk).

Quelques pré-requis de fonctionnement

L'installation de Livestatus se fait en rajoutant un broker à votre moteur nagios. Pour plus de détail, vous pouvez vous reporter à l'article suivant : setting up and using Livestatus. A noter que check_mk et Shinken viennent nativement avec ce support.

Autre point, dans le cas d'un accès déporter, il sera peut-être nécessaire de mettre en place un outil vous permettant d'exposer votre socket Unix sur le réseau. La documentation officiel fait appel à l'outil Unixcat (qui vient avec nagios). Pour ma part, j'ai préféré utiliser l'outil socat qui m'a donné des connexions plus stable et plus rapide. Ci-dessous un exemple de commande pour lancer socat :

socat TCP-LISTEN:1958,interface=lo,reuseaddr,keepalive,nodelay,fork,crnl \
      UNIX-CLIENT:/var/lib/nagios3/rw/live,keepalive

Installation de Thruk

Le gros défaut de Thruk est tout de même la ribambelle de plugin perl CPAN qu'il a comme dépendance. Heureusement, l'auteur du plugin propose un package tout prêt pour la plupart des plateformes disponibles (Debian, RedHat, Ubuntu, etc.). Pour se faire, il faut se rendre sur la page de téléchargement du projet, choisir le package qui vous convient et procéder à l'installation du package.

A noter que le produit a tout de même besoin de quelques dépendances au niveau système (plugin fastcgi pour apache notamment). Il faudra donc bien penser à installer ces dernières sous peine d'avoir des erreurs au moment de l'installation du package.

Une fois l'installation terminée, Thruk va créer un fichier htpasswd avec comme administrateur par défaut thrukadmin (mdp thrukadmin). Dans le cas où vous auriez déjà un fichier de mot de passe, bien penser à modifier le fichier /etc/apache2/conf.d/thruk.conf afin de pointer sur le bon. Bien penser également à modifier le fichier /etc/thruk/cgi.cfg dans ce cas là afin de définir les droits adéquates.

Enfin, il vous faudra  modifier le fichier /etc/thruk/thruk_local.conf afin de pointer sur votre noeud de supervision. Ci-dessous un exemple d'interfaçage avec un moteur Shinken :
######################################
# Backend Configuration, enter your backends here
<Component Thruk::Backend>
  <peer>
      name   = Shinken
      type   = livestatus
      <options>
          peer    = 127.0.0.1:50000
     </options>
  </peer>
</Component>
Un petit arrêt/relance du serveur apache et nous devrions être en mesure d'utiliser Thruk.

Tour du propriétaire

Connectez-vous sur l'interface Thruk (http://MONSERVEUR/thruk/). On devrait vous demander un mot de passe (thrukadmin/thrukadmin par défaut).

Au premier lancement, vous devriez avoir à attendre quelques secondes (ce comportement est normal puisque apache va devoir instancier les process fastcgi de Thruk à ce moment là). Ce délais d'attente passé, vous devriez arriver sur l'interface de Thruk. Par la suite, les process étant déjà là, vous n'aurez pas ce temps d'attente.

Comme indiqué un peu plus haut, l'interface est quasi la même que celle des CGIs si on exclue la map graphique (mais elle est avantageusement remplacé par une grille qui est plus fonctionnelle).

Du côté des améliorations, on peut noter les points suivants :
  • Champ de recherche plus efficace (utilisation d'ajax pour vous proposer des solutions lors de le champ de recherche avec proposition de choix de hostgroup, nom des services et bien sûr machine) ;
  • Lors du lancement d'un test, l'interface se bloque tant que le moteur nagios n'a pas récupéré le résultat du test (plus besoin de faire de rafraîchissement) ;
  • Intégration des graphiques de PNP ;
  • Présence de lien permettant des exports au format Excel (je sais, je suis pas forcément fan mais c'est quand même pratique).
Globalement, l'interface est plus jolie, plus réactive et vous avez également d'autres raffinements auxquels je ne pense pas forcément (générateur de rapport, gestion de la conf etc.).

Bref, comme dirait l'autre, l'essayer c'est l'adopter !

vendredi 26 octobre 2012

Plugin de suivi des PDUs

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é :


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.

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 :
#!/usr/bin/perl
use strict;

open(MODEL, "modele.txt");
mkdir("modeles") if(!-d("modeles"));
while() {
  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);
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.

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.

mardi 20 mars 2012

Quelques tests du mod_gearman avec nagios

J'ai dernièrement travaillé sur la mise en place d'une nouvelle infra nagios se basant sur une Redhat EL5.5 à la place de ma zone Solaris (youpi ! enfin du Linux sur notre infra !). A cette occasion, j'ai voulu voir ce que donné le mod gearman. Avant de le mettre en production, je l'ai activé sur mon poste (Debian/Kubuntu). J'en décris ici les principales étapes ainsi que les résultats de quelques tests.

Compilation

Ici, rien de très compliqué, il faut récupérer la dernière version (1.2.4 au moment de la rédaction de l'article mais la 1.2.6 est sortie entre temps) à l'adresse suivante : http://labs.consol.de/wp-content/uploads/2010/09/mod_gearman-1.2.4.tar.gz
Avant compilation, installons quelques pré-requis :
apt-get install gearman libgearman-dev
Vient ensuite le temps de la compilation :
# Décompression
tar xfv mod_gearman-1.2.4.tar.gz && cd mod_gearman-1.2.4
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
make
make install

Intégration de gearman dans nagios

De là, vous devriez obtenir un binaire /usr/lib/mod_gearman/mod_gearman.o que vous pouvez maintenant référencer de la manière suivante dans votre fichier /etc/nagios3/nagios.cfg :
broker_module=/usr/lib/mod_gearman/mod_gearman.o localhostgroups=local-server server=localhost:4730 key=Found@nor1g1nalK3y$ eventhandler=yes services=yes hosts=yes
Ici, il faut surtout noter les points suivants :
  • L'option localhostgroups donne le nom des groupes de machine sur lesquelles nous ne déléguerons pas les appels. Il est de bon goût d'y mettre les machines de votre infra nagios afin d'être sûr de détecter les problèmes sur vos services gearman ;
  • L'option server donne l'adresse d'écoute du démon gearman ;
  • L'option key permettant de gérer le chiffrement des communications entre les process gearman ;
  • Enfin les options eventhandler=yes services=yes hosts=yes permettant d'indiquer ce que nous pouvons faire faire à nos workers gearman.
Il  ne nous reste plus qu'à lancer les workers gearman et faire recharger la configuration à notre moteur nagios :
/etc/init.d/mod_gearman_worker start
Starting mod_gearman_worker...OK
/etc/init.d/nagios3 reload
 * Reloading nagios3 monitoring daemon configuration files nagios3

Lancement d'un petit bench

Maintenant que notre conf est prête, voyons l'impact de gearman sur le fonctionnement de notre moteur nagios. Tout d'abord, un test en désactivant gearman pour avoir une idée de la capacité native de notre moteur nagios.

A propos de la machine et du bench

Rien de particulier à signaler, il s'agit d'un processeur quadri-coeur (AMD Phenom(tm) II X4 965) avec 4 Go de mémoire.
Concernant la conf nagios du bench, elle consiste à créer des fichiers de configuration contenant les éléments suivants :
define host{
        use                     generic-host
        process_perf_data       0
        host_name               @HOST@
        alias                   @HOST@
        address                 127.0.0.1
        }

define service{
        use                             generic-service         ; Name of service template to use
        host_name                       @HOST@
        service_description             dummy1
        check_interval                  1
        check_command                   return-ok
}
[...]

Sans mod_gearman

Voici grosso modo les temps forts au niveau du changement de conf :
Heurenb machinesnb servicesinterval
20h4540056005min
20h5540056001min
21h2560084001min
21h40800112001min

Tout ceci a entraîné le comportement suivant au niveau de la machine de bench :
  • Latence du moteur nagios :
  •  Consommation CPU de la machine

La consommation avoisine en pointe les 92 % avec une moyenne - pour la fin du test - dans les 75%. La latence se situe dans les 500ms en fin de test.

Avec mod_gearman

Passons maintenant la même configuration avec gearman actif. Tout d'abord les évènements du bench :
Heurenb machinesnb servicesinterval
22h0040056001min
22h2060084001min
22h40800112001min
23h021000140001min
23h221200168001min

Et maintenant le comportement du serveur pendant cette même période :
  • Latence du moteur nagios :
  • Consommation CPU :

Non seulement la consommation CPU n'a jamais dépassé 37 % en pointe (on est plutôt à 25% de moyenne) mais en plus, on a pu faire 50 % de tests en plus sans impact particulier au niveau de la machine et en gardant une latence inférieur à 400ms.

Pour conclure ...

Comme on peut le voir, l'utilisation de gearman fait grandement baisser la consommation CPU de notre serveur. D'autant plus que gearman offre également la capacité de distribuer nos surveillances sur plusieurs machines différentes. Vous pouvez également déporter la génération des graphiques sur une autre machine (à l'aide du mode gearman de PNP4Nagios par exemple).

Si vous combinez tout ceci,  nous sommes face à un outil apportant une très grande souplesse à ce vieux moteur nagios. Non seulement vous réduisez votre consommation CPU mais tout en vous laissant la possibilité de distribuer très facilement vos éléments de surveillance/métrologie en fonction de vos besoins.

Pour aller plus loin, je vous conseille de faire un tour sur le site de gearman qui présente pas mal de possibilité d'architecture.

dimanche 26 février 2012

Gestion des mots de passe de l'interface web de shinken

Shinken est sortie il y a peu de temps en version 1.0rc1. J'ai voulu l'installer et utiliser la nouvelle interface web. Comme j'ai eu quelques difficultés et qu'il semblerait que d'autre ai eu le même problème que moi (merci à David pour ton aide !), je me permets de déposer quelques éléments sur le sujet.
Pour l'installation, il faut tout d'abord télécharger l'archive à l'adresse suivante :https://github.com/naparuba/shinken/tarball/1.0rc1
Vous obtiendrez alors l'archive naparuba-shinken-1.0rc1-0-g5a2075e.tar.gz. Une fois l'archive décompressé, vous pourrez lancer l'installation à l'aide de la commande suivante :
sudo python setup.py install --install-scripts=/usr/bin/
De là, lancez shinken avec la commande /etc/init.d/shinken start
Si vous jetez un oeil au process shinken de votre machine, vous devriez obtenir les choses suivantes :
root@robert:/home/drayan/dev/naparuba-shinken-5a2075e# ps -fu shinken
UID        PID  PPID  C STIME TTY          TIME CMD
shinken  15495 30036  0 00:15 ?        00:00:00 /usr/bin/python /usr/bin//shinken-reactionner -d -c /etc/shinken/reactionnerd.ini
shinken  30009     1  0 Feb25 ?        00:00:56 /usr/bin/python /usr/bin//shinken-scheduler -d -c /etc/shinken/schedulerd.ini
shinken  30019 30009  0 Feb25 ?        00:00:00 /usr/bin/python /usr/bin//shinken-scheduler -d -c /etc/shinken/schedulerd.ini
shinken  30021     1  0 Feb25 ?        00:00:51 /usr/bin/python /usr/bin//shinken-poller -d -c /etc/shinken/pollerd.ini
shinken  30031 30021  0 Feb25 ?        00:00:21 /usr/bin/python /usr/bin//shinken-poller -d -c /etc/shinken/pollerd.ini
shinken  30036     1  0 Feb25 ?        00:00:40 /usr/bin/python /usr/bin//shinken-reactionner -d -c /etc/shinken/reactionnerd.ini
shinken  30046 30036  0 Feb25 ?        00:00:07 /usr/bin/python /usr/bin//shinken-reactionner -d -c /etc/shinken/reactionnerd.ini
shinken  30051     1  0 Feb25 ?        00:00:54 /usr/bin/python /usr/bin//shinken-broker -d -c /etc/shinken/brokerd.ini
shinken  30061 30051  2 Feb25 ?        00:05:53 /usr/bin/python /usr/bin//shinken-broker -d -c /etc/shinken/brokerd.ini
shinken  30063     1  0 Feb25 ?        00:00:22 /usr/bin/python /usr/bin//shinken-receiver -d -c /etc/shinken/receiverd.ini
shinken  30073 30063  0 Feb25 ?        00:00:00 /usr/bin/python /usr/bin//shinken-receiver -d -c /etc/shinken/receiverd.ini
shinken  30079     1  0 Feb25 ?        00:01:11 /usr/bin/python /usr/bin//shinken-arbiter -d -c /etc/shinken/nagios.cfg -c /etc/shinken/shinken-specific.cfg
shinken  30080 30079  0 Feb25 ?        00:00:03 /usr/bin/python /usr/bin//shinken-arbiter -d -c /etc/shinken/nagios.cfg -c /etc/shinken/shinken-specific.cfg
shinken  30087 30079  0 Feb25 ?        00:00:00 /usr/bin/python /usr/bin//shinken-arbiter -d -c /etc/shinken/nagios.cfg -c /etc/shinken/shinken-specific.cfg
shinken  30109 30021  0 Feb25 ?        00:00:04 /usr/bin/python /usr/bin//shinken-poller -d -c /etc/shinken/pollerd.ini
shinken  30116 30021  0 Feb25 ?        00:00:04 /usr/bin/python /usr/bin//shinken-poller -d -c /etc/shinken/pollerd.ini
shinken  30124 30021  0 Feb25 ?        00:00:04 /usr/bin/python /usr/bin//shinken-poller -d -c /etc/shinken/pollerd.ini
shinken  30140 30051  1 Feb25 ?        00:03:26 /usr/bin/python /usr/bin//shinken-broker -d -c /etc/shinken/brokerd.ini
shinken  30149 30051  0 Feb25 ?        00:00:14 /usr/bin/python /usr/bin//shinken-broker -d -c /etc/shinken/brokerd.ini
shinken  30170 30021  0 Feb25 ?        00:00:04 /usr/bin/python /usr/bin//shinken-poller -d -c /etc/shinken/pollerd.ini
Vous pouvez maintenant vous rendre sur l'interface web de shinken sur l'url suivante : http://localhost:7767/
Un utilisateur vous sera demandé. Il s'agira par défaut de admin/admin.
A ce sujet, il faut savoir que le système d'authentification s'appuie sur la configuration contenu dans le fichier shinken-specific.cfg (dans le répertoire /etc/shinken) et notamment sur le passage suivant :

# The WebUI broker module
define module{
       module_name      WebUI
       module_type      webui
       
       host             0.0.0.0       ; mean all interfaces
       port             7767

[...]
       modules          Apache_passwd,ActiveDir_UI,Cfg_password
[...]
}
Comme indiqué, l'interface essaye d'authentifier l'utilisateur avec 3 modules différents. Le premier qui y arrive arrête le mécanisme.
Dans le cas présent, nous allons tout d'abord essayer de nous authentifier avec un fichier htpasswd apache (toujours dans shinken-specific.cfg) :
define module{
       module_name      Apache_passwd
       module_type      passwd_webui

       #  WARNING : put the full PATH for this value!
       passwd           /etc/shinken/htpasswd.users

}
Vient ensuite le module active directory :
# Check authentification for WebUI using a Active Directory
define module{
       module_name      ActiveDir_UI
       module_type      ad_webui

#   UNCOMMENT this line to really enable this module and allow it to
#   connect!
#        ldap_uri         ldaps://myserver
       username         user
       password         password
       basedn           DC=google,DC=com

}
Enfin, dans le cas de l'interface web de shinken (avec sa conf par défaut), ce dernier va s'appuyer sur ces fichiers de configuration. Dans le cas de l'utilisateur admin, il s'agit d'un contact (au sens nagios) définie dans les fichiers de configuration (par défaut, fichier contacts.cfg). Le mot de passe est par ailleurs définie de la manière suivante :
define contact{
        use                                     generic-contact
        contact_name                            admin
        email                                   shinken@localhost
        pager                                   0600000000   ; contact phone number
        password                                admin
        is_admin                                1
}
De là, vous pouvez changer le mot de passe et le faire prendre en compte par shinken. Il ne reste plus maintenant qu'à configurer vos services !

lundi 19 décembre 2011

Patch multi packet pour NRPE 2.13

Malgré le faible intérêt de la sortie de nrpe 2.13, je vais tout de même le déployer pour la simple et bonne raison que nous allons bientôt migrer notre infrastructure nagios de Solaris à Linux. C'est donc dans ce cadre que j'ai voulu changer de version et surtout réappliquer le patch que j'utilise depuis pas mal de temps permettant de gérer des sorties longues.

Problème, le patch de tonvoon (dont je parle ici) n'est plus utilisable en l'état. Comme de toute façon le code source a très peu été retouché (juste l'ajout d'une fonction dans le démon nrpe), nous allons voir comment faire pour récupérer ce patch et forcer son application.

Tout d'abord, il nous faut récupérer une copie de notre patch sur notre machine :

wget https://dev.icinga.org/attachments/download/113/nrpe_multiline.patch

Passons maintenant à la transformation de notre patch au format Windows (eurk !) :

unix2dos ./nrpe_multiline.patch

Il ne nous reste plus qu'à passer le patch en indiquant la ligne de commande patch --binary -l -p1. Si tout se passe bien, la sortie devrait ressembler à ce qui suit :

nous@roulette:~/nagios/nrpe-2.13$ patch --binary -l -p1 < ../nrpe_multiline.patc
h 
patching file include/common.h
patching file src/check_nrpe.c
patching file src/nrpe.c
Hunk #1 succeeded at 972 (offset -57 lines).
Hunk #2 succeeded at 1190 (offset -57 lines).
Hunk #3 succeeded at 1206 (offset -57 lines).
Hunk #4 succeeded at 1235 (offset -57 lines).

Lançons maintenant la configuration et la compilation. Tout devrait bien se passer.

Nous allons maintenant nous assurer qu'il n'y a pas eu de régression. Tout d'abord créons un fichier nrpe.cfg avec le contenu suivant :

log_facility=daemon
pid_file=./nrpe.pid
server_port=5666
server_address=127.0.0.1
nrpe_user=nagios
nrpe_group=nagios
allowed_hosts=127.0.0.1
dont_blame_nrpe=0
debug=0
command_timeout=60
connection_timeout=300

command[short_output]=echo coucou
command[long_output]=/bin/cat /etc/wgetrc

La première commande affiche un simple coucou et la seconde affiche le contenu du fichier /etc/wgetrc.

Mais trêve de bavardage et lançons séance tenante notre démon :

nous@roulette:~/nagios/nrpe-2.13$ ./src/nrpe -c ./nrpe.cfg -d
nous@roulette:~/nagios/nrpe-2.13$ ps -ef | grep nrpe
nous      9374     1  0 17:04 ?        00:00:00 ./src/nrpe -c ./nrpe.cfg -d
nous      9376  5769  0 17:04 pts/0    00:00:00 grep --color=auto nrpe

Tout semble parfait. Lançons un test de notre première commande :

./src/check_nrpe -H localhost -c short_output
coucou

Ça semble plutôt pas mal. Regardons maintenant la taille de la sortie de notre commande longue et comparons cela au fichier d'origine :

nous@roulette:~/nagios/nrpe-2.13$ ./src/check_nrpe -H localhost -c long_output | wc
    126     797    4496
nous@roulette:~/nagios/nrpe-2.13$ wc /etc/wgetrc
 126  797 4496 /etc/wgetrc

C'est parfait ! Notre NRPE en version 2.13 avec patch sortie longue est prêt à fonctionner !

samedi 26 novembre 2011

Sortie de NRPE 2.13

Il y'a peu de temps, la version 2.13 de NRPE est sortie. Autant dire que je suis assez déçu sur le contenu de cette nouvelle version puisque nous n'avons qu'un seul changement pour définir qui a le droit de se connecter sur l'agent NRPE dans le fichier nrpe.cfg (ainsi que la compilation sous Solaris 10). En gros, auparavant, vous étiez obliger de donner explicitement l'IP de votre serveur nagios pour pouvoir vous connecter. Dorénavant, vous pouvez préciser un réseau avec un masque. Ci-dessous un exemple de fichier nrpe.cfg faisant appel à ce mécanisme :
log_facility=daemon
pid_file=/var/run/nagios/nrpe.pid
server_port=6666
nrpe_user=nagios
nrpe_group=nagios
# allowed_hosts=127.0.0.1
allowed_hosts=192.168.0.0/24

dont_blame_nrpe=0
debug=0
command_timeout=60
connection_timeout=300
command[check_users]=/usr/lib/nagios/plugins/check_users -w 5 -c 10
command[check_load]=/usr/lib/nagios/plugins/check_load -w 15,10,5 -c 30,25,20
command[check_hda1]=/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /dev/hda1
command[check_zombie_procs]=/usr/lib/nagios/plugins/check_procs -w 5 -c 10 -s Z
command[check_total_procs]=/usr/lib/nagios/plugins/check_procs -w 150 -c 200 
NB: ce démon tourne sur le port 6666 pour des besoins de test. La commande check_nrpe ci-dessous utilisera l'option -p 6666 pour pouvoir s'y connecter.
On va essayer de se connecter sur notre agent NRPE. Ci-dessous l'adresse de mon poste :
drayan@robert:~/dev/nrpe-2.13$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 1c:6f:65:21:7b:c0  
          inet adr:192.168.0.17  Bcast:192.168.0.255  Masque:255.255.255.0
[...]
Lançons un test en tant que localhost (qui devrait nous jeter du fait qu'on se présente avec l'adresse IP 127.0.0.1) :
drayan@robert:~/dev/nrpe-2.13$ ./src/check_nrpe -H localhost -c check_load -p 6666
CHECK_NRPE: Error - Could not complete SSL handshake.
Parfait ! Lançons maintenant la même chose en utilisant notre adresse IP :
drayan@robert:~/dev/nrpe-2.13$ ./src/check_nrpe -H 192.168.0.17 -c check_load -p 6666
OK - Charge moyenne: 0.03, 0.06, 0.09|load1=0.030;15.000;30.000;0; load5=0.060;10.000;25.000;0; load15=0.090;5.000;20.000;0;
Voilà, c'est tout ... Je suis notamment assez déçu que le patch pour gérer les sorties longues (dont j'avais parlé ici il y'a quelque temps) ne fasse pas partie de cette release.

mercredi 9 novembre 2011

Optimisation de PNP4Nagios avec RRDcached

Suite à l'article sur l'utilisation du démon NPCD, j'ai voulu voir quel pourrait être l'impact de la mise en place du démon RRDCached sur le fonctionnement de PNP4Nagios. Pour se faire, il faut bien comprendre à quoi sert ce fameux démon.

Pour cela, il faut revenir sur le fonctionnement de PNP4Nagios à savoir de prendre un grand nombre de métrique et d'alimenter au fur et à mesure un grand nombre de petit fichier : les fichiers RRD. Au delà d'un certain nombre de service, nous pouvons nous retrouver avec une machine qui fait énormément d'IO et qui du coup n'a plus le temps de mettre à jour certaines métriques (mécanisme de timeout de PNP4Nagios). Nous voyons donc qu'au delà un certain seuil, PNP4Nagios peut retomber sur tous les travers classiques des infrastructures de surveillance : consommer de la puissance CPU et être lent (qui a soufflé le nom de NDO utils ?). Le démon RRDCached prend ici tout son sens. En effet, ce dernier va buffuriser les mises à jours RRD au lieu de les faire unitairement réduisant grandement les IO sur notre serveur nagios.

Pour mieux comprendre, prenons le cas d'un serveur nagios remontant en moyenne 10 métriques par services. Si vous êtes comme moi et que vous avez explosé vos fichiers RRD en n fichiers pour chaque services, vous aurez un fichier par métrique. Si nous scruptons toutes les 5 minutes nos différents services (toujours en moyenne), nous nous retrouvons à mettre à jour 10 fichiers pour chaque test de service nagios. Si on reporte ce chiffre sur 1 heure, nous aurons donc environ 120 écritures sur une heure. Si vous multipliez tout ceci par le nombre de service présent sur vos machines (on va dire 5000), vous vous retrouvez à faire environ 600000 écritures par heure. Si vous ajoutez à cela que votre serveur faire appel à des métriques qui sont plus régulière (toutes les 2 minutes voir toute les minutes), vous pouvez commencer à avoir des problèmes.

RRDCached, en s'intercallant entre les outils RRD et les écritures sur le disque, va regrouper ces dernières et ainsi mieux exploiter les capacités de la machine. Imaginons que ce dernier procéde à une buffurisation des écritures sur 1/2 heure, vous diviserez par 6 vos IOs pour des services scruptant toutes les 5 minutes. Ce chiffre pouvant monter à 30 pour des services remontant des métriques toutes les minutes.

Voyons maintenant comment mettre en oeuvre ce démon.

NB : Par la suite, il est évident que je considérerai que PNP4Nagios sera configuré en mode NPCD (cf mon article sur la configuration de PNP4Nagios en mode NPCD) et surtout qu'il utilisera le module RRDs de perl pour faire ses mise à jour (cf mon article sur le sujet).

Installons tout d'abord notre démon rrdcached (sous Debian ou ubuntu) :
sudo apt-get install rrdcached
Et regardons si ce dernier est bien lancé :
$ /etc/init.d/rrdcached status
rrdcached (1262) is running.
$ ps -fp 1262
UID        PID  PPID  C STIME TTY          TIME CMD
root      1262     1  0 18:46 ?        00:00:00 /usr/bin/rrdcached -l unix:/var/run/rrdcached.sock -j /var/lib/rrdcached/journal
Tout semble aller pour le mieux. Nous allons maintenant configurer le script process_perfdata.pl afin qu'il passe par ce démon pour la mise à jour des fichiers RRD. Pour se faire, nous allons modifier le fichier process_perfdata.cfg et notamment la ligne suivante :
RRD_DAEMON_OPTS = unix:/var/run/rrdcached.sock
Attendons un petit peu et allons consulter l'interface de PNP4Nagios. Cette dernière ne devrait plus nous remonter de statistique sur notre moteur PNP4Nagios. Ce comportement est tout à fait normal étant donné que l'interface PHP de PNP4Nagios n'a aucune connaissance de ce nouveau démon. Ce dernier continue donc de s'appuyer sur les fichiers RRD présent alors que ces derniers ne sont plus mis à jour en temps réel.

Modifions maintenant la configuration de PNP4Nagios (fichier config_local.php qu'il faudra créer s'il n'existe pas) afin de lui préciser le pipe nommé de notre démon de cache :

$conf['RRD_DAEMON_OPTS'] = 'unix:/var/run/rrdcached.sock';
Dorénavant, le graphique se met bien à jour en temps réel. En effet, en précisant au binaire RRDTool que nous avons un démon de cache, ce dernier va simplement dire au démon de vider ses buffers sur les fichiers RRDs que nous sommes en train de consulter afin qu'il nous fasse profiter des dernières valeurs que ce dernier avait emmagasiné.

Vous pourriez vous dire que le fait de vider le cache de notre démon avant de pouvoir consulter nos graphiques est une perte de temps. Effectivement, ce comportement sera peu avantageux pour les fichiers RRDs que nous voudrons consulter. En revanche, il sera avantageux pour les milliers d'autres qui pourront continuer à être buffurisé.

ATTENTION !!! Dorénavant, votre démon RRDcached est un élément vitale de votre infrastructure. Je vous recommande chaudement de le surveiller avec votre moteur nagios sous peine de ne plus avoir de mise à jour si ce dernier devait tomber.

Vous allez me dire que tout ça c'est très bien mais vous voudriez savoir si le jeu en vaut la chandelle. Comme généralement les graphiques parlent plus que les chiffres, voici les résultats des temps de réponse moyen de PNP4Nagios suite à la mise en place de ce merveilleux plugin (ici sur 1 mois) :


Comme vous pouvez le constater, du jour où le démon a été mis en place, j'ai vu une grosse diminution de l'effet yoyo et surtout une baisse assez importante du temps moyen pour les mise à jour de PNP4Nagios (passage de 9 secondes avec pointe à 70 secondes à une moyenne sans pique autour de 5 secondes). Autant vous dire que tout ceci est une très bonne nouvelle et que je vais pouvoir continuer mon travail de big brother !

mardi 20 septembre 2011

Template wlsagent pour PNP4Nagios

Il y a de ça peu de temps, j'ai présenté l'utilisation de wlsagent pour le suivi sous nagios d'instance WebLogic. J'avais également donné quelques exemples de graphique sous PNP4Nagios mais sans donner le template de présentation :



Le template est maintenant disponible à l'adresse suivante : http://docs.pnp4nagios.org/templates/check_wlsagent

Il faut copier-coller ce fichier dans le répertoire template de PNP4Nagios (en principe, quelque chose comme /usr/local/pnp4nagios/share/templates/) et se débrouiller pour que PNP4Nagios arrive à faire le lien entre le plugin de lancement et le template.

Personnellement, comme j'appelle tout au travers de NRPE, j'ai simplement créé un doublon de la commande check_nrpe en l'appelant check_wlsagent :
# 'check_wlsagent' command definition
define command{
  command_name check_wlsagent
  command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$
}
J'appelle ensuite mes surveillances à l'aide de commande de ce genre :
# Application WebLogic à surveiller
define service{
  use generic-service
  host_name remotehost
  service_description Application hyperimportante
check_command check_wlsagent!check_application_hyperimportante
}

mardi 13 septembre 2011

Optimisation du couple nagios/PNP4Nagios

Description de l'installation

J'utilise depuis maintenant plusieurs années un moteur nagios sur notre infra pour avoir un suivi de ce qu'il se passe sur nos serveurs.

Au début, nous avions axé notre déploiement sur la partie serveur d'application Java (à base de WebLogic). Nous avons très rapidement activé l'utilisation du moteur de base de données ndo2db. Par la suite nous avons intégré environ 60 serveurs sous cette surveillance pour un total d'environ 600 services. Les choses sont restés en l'état en raison de la machine que nous utilisions qui était particulièrement lente et pauvre en IO disque (pour les plus curieux, il s'agissait d'un Sunfire V210 avec un bi-processeur Ultrasparc III@1Ghz et 2 Go de mémoire).

Il y'a de ça un an et demi, nous avons échangé notre vieille machine poussive contre une machine Solaris flambant neuve (à base de M5000). De là, j'ai profité pour changer nos outils d'autant que je n'étais pas particulièrement content de ndo2db. C'est à cette occasion que j'ai mis en place la toute dernière version de PNP4Nagios en version 0.6 (que j'avais testé en version béta quelques temps auparavant).

De là, j'ai découvert le super système de template de PNP4nagios (cf cet article) et j'ai commencé à mettre ça en oeuvre sur tous nos éléments vitaux d'infrastructure (apache, oracle, MySQL etc.).

Le mode synchrone de PNP4Nagios étant particulièrement lent, j'ai très vite déployé PNP4Nagios en mode bulk lancé par nagios. Mais, le succès aidant, je suis rapidement passé de 60 à 100 machines puis 200. Comme un SI ne diminue jamais, dernièrement nous sommes arrivé à environ 300 machines pour environ 3000 services. Loin d'être énorme (en tunant la configuration de nagios, on parle de configuration montant à 30000 services et plus), les performances du moteur nagios avaient tout de même tendance à se dégrader comme on peut le voir sur le graphique ci-dessous des temps de latence maximum :


On voit ici des temps de latence maximum qui monté à plus de 60 secondes. Même si c'est loin d'être complètement bloquant, ça indique une réactivité beaucoup moins bonne qu'au début du fonctionnement de la plateforme.

C'est donc à ce moment là que j'ai commencé à regarder les optimisations qu'il était possible de faire et notamment l'utilisation de NPCD. J'ai également mis en place le démon de cache RRD. Pour ce dernier j'essaierai d'en parler dans un autre article.

Mise en place de NPCD

La mise en place de NPCD se fait en deux temps : mise en place du démon puis modification de la commande d'insertion des données de performance dans PNP4Nagios. Ci-dessous un schéma extrait du site de PNP4Nagios expliquant le fonctionnement du démon NPCD :

Pour le lancement du démon NPCD, rien d'extraordinaire, il suffit simplement de lancer la commande suivante :
/usr/local/pnp4nagios/bin/npcd
On peut ensuite vérifier sa présence sur le serveur :
ps -ef | grep npcd
Le démon se lance en s'appuyant sur le fichier /usr/local/pnp4nagios/etc/npcd.cfg. Ce dernier va contenir toutes les informations sur le comportement que devra adopter le démon. Vous pouvez notamment tuner les éléments suivants :
  • Le temps de pause entre deux checks dans le répertoire de spool ;
  • Le nombre max de process perfdata à lancer en parallèle ;
  • La verbosité de la log.
Une fois NPCD, nous allons maintenant pouvoir basculer l'insertion des données en utilisant un répertoire de spool. Pour se faire, nous allons changer les commandes process-service-perfdata-file et process-host-perfdata-file (en principe dans le fichier /usr/local/etc/nagios/template/commands.cfg). Ces dernières ressemblaient aux lignes suivantes :
define command {
       command_name    process-service-perfdata-file
       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/service-perfdata
}

define command {
       command_name    process-host-perfdata-file
       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/host-perfdata
}
Nous les avons remplacé par les lignes suivantes :
define command {
       command_name    process-service-perfdata-file
       command_line    /bin/mv /usr/local/pnp4nagios/var/service-perfdata /usr/local/pnp4nagios/var/spool/service-perfdata.$TIMET$
}

define command {
       command_name    process-host-perfdata-file
       command_line    /bin/mv /usr/local/pnp4nagios/var/host-perfdata /usr/local/pnp4nagios/var/spool/host-perfdata.$TIMET$
}
Il s'agit simplement de substituer l'appel direct à la commande process_perfdata.pl de PNP4Nagios par un déplacement de fichier dans un répertoire. Pas grand chose me direz-vous mais nous allons vite voir que ce petit changement aura des conséquences très intéressante au niveau de nagios.

Résultat de l'optimisation

Et il se trouve que cette modification a eu un énorme impact sur les performances. Pour preuve un état du temps de latence moyen maximum :

On peut voir que nous avons gagné en stabilité au niveau des temps de réponse max et surtout que ces derniers restent largement en dessous les 5 secondes (sauf exceptionnellement mais rien à voir avec le comportement précédent).

mercredi 9 mars 2011

Patch du jour : NRPE et les sorties longues

NRPE est vraiment un compagnon inséparable de nagios : lancer des plugins à distance sur un serveur et récupérer leurs résultats au travers d'une simple commande check_nrpe.

Pour l'illustrer, lançons un démon NRPE avec le fichier de configuration suivant :


log_facility=daemon
pid_file=./nrpe.pid
server_port=5666
server_address=127.0.0.1
nrpe_user=nagios
nrpe_group=nagios
allowed_hosts=127.0.0.1
dont_blame_nrpe=0
debug=0
command_timeout=60
connection_timeout=300

command[short_output]=/bin/cat /tmp/test
command[long_output]=/bin/cat /etc/screenrc


Nous y avons défini deux commandes (short_output et long_output) et nous l'avons fait écouter sur l'adresse localhost. Lançons maintenant notre process :


# ./nrpe -c ./nrpe.cfg -d
# ps -ef | grep nrpe
nagios 11411 1 0 22:39 ? 00:00:00 ./nrpe -c ./nrpe.cfg -d
root 11417 6370 0 22:39 pts/4 00:00:00 grep --color=auto nrpe


Essayons maintenant de récupérer le résultat d'une de nos commandes :


$ ./check_nrpe -H localhost -c short_output
Retour NRPE|Short_output=1


Tout semble fonctionner au mieux mais malheureusement dans le cas d'une sortie trop grande, tout ce qui dépasse 1024 ieme octet est ignoré :


$ ./check_nrpe -H localhost -c long_ouput | wc
34 160 1024


En creusant un peu, cette limitation vient de la définition d'une constante C dans le fichier include/common.h :

#define MAX_PACKETBUFFER_LENGTH 1024


Ici, la solution qui vient immédiatement à l'esprit est de simplement changer cette valeur et relancer la compilation. Une fois la recompilation terminée, nous obtenons un binaire check_nrpe et un binaire nrpe.

En lançant notre nrpe patché, nous avons effectivement le résultat attendu. Petit soucis, si vous avez déjà des agents NRPE et que vous voulez lancer votre commande check_nrpe sur un ancien serveur, vous obtiendrez une belle erreur vous indiquant un soucis de communication :


$ ./check_nrpe -H localhost -c short_output
CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages.


Si vous êtes comme moi avec environ 300 agents NRPE déjà existant, vous aurez quelques hésitations à les redéployer tous. Heureusement, tonvoon a écrit un patch assez astucieux à ce sujet il y a déjà quelques temps. Le principe est d'utiliser le champ packet_type pour indiquer un nouveau type RESPONSE_PACKET_WITH_MORE en plus des types RESPONSE_PACKET et QUERY_PACKET. Lorsque le plugin check_nrpe détecte ce type de paquet, au lieu de terminer la communication, le client récupère les packets suivants pour les concaténer jusqu'au maximum de 16ko. Et cerise sur le gateau : le plugin check_nrpe reste compatible avec les anciens clients NRPE !

Vous pouvez donc mettre votre plugin check_nrpe à jour et faire la mise à jour au fil de l'eau pour vos agents NRPE voir - si vous êtes vraiment un gros feignant - ne le faire que là où vous en avez besoin.

Pour appliquer le patch, récupérer une copie de NRPE en version 2.12, patcher là avec le fichier suivant puis lancer le classique configure ; make ; make install. Vous obtiendrez alors vos deux binaires à utiliser.

jeudi 23 décembre 2010

Installation de shinken et configuration de l'interface Thruk

J'utilise beaucoup nagios pour mon travail de tous les jours mais c'est un outil qui n'est pas parfait (loin de là! ). J'ai donc lu avec beaucoup d'intérêt le démarrage du projet shinken qui a comme gros avantage d'être beaucoup plus performant et d'être beaucoup plus modulable que son ainé.

Voulant m'en faire une idée pour de vrai, j'ai donc procédé à une installation from scratch. Comme la documentation ne parle pas du tout de l'ajout de l'interface, je laisse donc ici quelques mots à ce sujet.

Installation de shinken



Tout d'abord créer un utilisateur shinken. Très important, il faut un home qui soit valide (sinon, l'arbitrer ne démarre pas !).

Reste ensuite à procéder à l'installation. Ici, rien de plus simple, il faut simplement récupérer le package shinken-0.4.tar.gz puis de le décompresser. Se rendre dans le répertoire shinken-0.4 puis lancer la commande suivante :

sudo python setup.py install --install-scripts=/usr/bin


De là, shinken va créer pas mal de répertoire (notamment /var/lib/shinken et /etc/shinken). Par convenance, j'ai créé un fichier shinken.sh qui me lance tous les éléments dans le bon ordre :


patrice@Enclume:~/tmp/shinken-0.4$ cat /etc/init.d/shinken.sh
#!/bin/bash

cd /etc/init.d

for script in shinken-scheduler shinken-poller shinken-reactionner shinken-broker shinken-arbiter
do
./$script $1
done


De là, il suffit de faire un /etc/init.d/shinken.sh start et c'est parti ! Pour vérifier que tout va bien, il faut s'assurer que les process suivants sont bien présents :


patrice@Enclume:~/tmp/shinken-0.4$ ps -u shinken
PID TTY TIME CMD
4358 ? 00:00:09 shinken-schedul
4367 ? 00:00:10 shinken-poller
4372 ? 00:00:00 shinken-poller
4380 ? 00:00:09 shinken-reactio
4385 ? 00:00:00 shinken-reactio
4949 ? 00:00:13 shinken-broker
4989 ? 00:00:00 shinken-poller
4990 ? 00:00:00 shinken-poller
4993 ? 00:00:00 shinken-poller
4996 ? 00:00:18 shinken-broker
4997 ? 00:00:00 shinken-broker
5001 ? 00:00:00 shinken-reactio
5004 ? 00:00:00 shinken-poller
5018 ? 00:00:10 shinken-arbiter


Configuration de l'interface Thruk



Ici, il faut récupérer l'interface Thruk à l'emplacement suivant. On la décompresse puis nous nous rendons dedans afin d'y créer un fichier thruk_local.conf. En voici le contenu :


~/tmp/Thruk-0.74$ cat thruk_local.conf
######################################
# Backend Configuration, enter your backends here
<component Thruk::Backend>
<peer>
name = Shinken
type = livestatus
hidden = 0 # make this backend hidden by default
groups = admins # make this backend only visible to the admin group
<options>
peer = 127.0.0.1:50000
verbose = 0
</options>
</peer>
</component>


De là, il ne nous reste plus qu'à lancer le démon Thruk :


~/tmp/Thruk-0.74/script$ ./thruk_server.pl
You can connect to your server at http://enclume:3000


NB : Attention, il s'agit d'un test. Il est possible de lancer l'interface Thruk en utilisant un serveur apache mais ce n'est pas l'objet de cet article.

De là, il ne nous reste plus qu'à accéder à l'interface http://localhost:3000 au travers un navigateur :



Bon, il va maintenant falloir que je configure correctement ma map :D Mais bon, ça c'est une autre histoire ;).

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 :

$ ./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.

vendredi 25 juin 2010

Compilation NRPE sous AIX 5.3 avec support du SSL

J'ai eu dernièrement besoin de compiler un agent nagios NRPE pour AIX 5.3. Malheureusement pour moi, cet OS est livré sans librairie dynamique openssl (ie libssl.so). J'ai donc du compiler nrpe en static.

N'ayant pas trouver d'information intéressante sur le net (en dehors de désactiver le ssl), je me suis dit que ce genre d'information pourrait être utile à d'autre.

Tout d'abord, modifier le fichier configure de la manière suivante (sur une version 2.12 de nrpe) :


$ diff configure.orig configure
6673c6673
< if test -f "$dir/libssl.so"; then
---
> if test -f "$dir/libssl.a"; then
6687c6687
< LIBS="$LIBS -lssl -lcrypto";
---
> LIBS="$LIBS $ssllibdir/libssl.a $ssllibdir/libcrypto.a";


Le patch consiste à changer la nature du fichier recherché (libssl.a à la place de libssl.so) et remplacer les flags de compilation -lssl et -lcrypto par les fichiers des bibliothèques que l'on vient de trouver.

Il ne reste plus qu'à lancer configure avec les options suivantes :
./configure --with-ssl=/opt/freeware --with-ssl-lib=/opt/freeware/lib --prefix=/opt/nagios


Un coup de make ; make install et vous disposez maintenant des binaires nrpe et check_nrpe à la mode AIX et surtout avec le support du SSL.

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 :
  • 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
}
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.

Bref, j'ai donc changé la version de perl par celle se trouvant dans /usr/local/bin :
define command {
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
}
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 :

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.

mercredi 23 juin 2010

Supervision de WebLogic à l'aide de nagios

Afin de surveiller la consommation mémoire de nos instances WebLogic, j'ai commencé à écrire un plugin se basant sur le protocole SNMP.

Pour ceux qui ne le saurait pas, WebLogic est un serveur d'application Java propriétaire.

Ce besoin de surveillance vient du fait que les serveurs les hébergeants (des Sun V890 avec 40 Go de mémoire) sont sur le point d'arriver à saturation mémoire. Pour cette raison, nous avons donc essayé de savoir quelles instances consommées et à quelle hauteur.

Il faut dire que nous avons constaté que la mémoire allouée aux JVMs étaient le double de la mémoire physique ! Pour info, la machine héberge une centaine d'instance WebLogic en version 8.1 et Java 1.4. Comme vous vous en doutez, nous avons prévu de faire le ménage dans nos instances. Mais pour ça, il nous faudrait un petit état des lieux, d'où l'écriture d'un script.

Passons maintenant à l'écriture du script.

Premier point, il faut se débrouiller pour activer l'agent SNMP au niveau du domaine WebLogic. Nous pourrons ainsi interroger le serveur sans avoir à faire de couteuses interrogations à base de programme en java. Nous allons ensuite nous baser sur l'outil snmpwalk.

Pour mémoire, une page de référence de la MIB de ce serveur d'application est disponible à l'adresse suivante : http://download.oracle.com/docs/cd/E13222_01/wls/docs90/snmp/index.html

Commençons tout d'abord par interroger l'agent SNMP WebLogic en ligne de commande :
drayan@robinet:~$ snmpwalk -m ./BEA-WEBLOGIC-MIB.mib -c public -v 1 192.168.0.10:7061 .1.3.6.1.4.1.140.625.180
La branche .1.3.6.1.4.1.140.625.180 correspond aux informations sur les threads Java actifs. Nous pouvons également interroger la branche .1.3.6.1.4.1.140.625.340.1 pour récupérer la quantité de mémoire consommée (jvmRuntimeHeapSizeCurrent). A noter que pour connaître les instances présentes dans le domaine WebLogic, je fais appel à la branche 1.3.6.1.4.1.140.625.361.1.

Une fois enrobé tout ceci j'obtiens le script suivant :
#!/usr/bin/perl
use strict;
use File::Basename;
use Sys::Hostname;
use Getopt::Long;

my $verbose = 0;
my $show_help = 0;
my $show_version = 0;
my $snmp_address = 0;
my $instance = 0;
my $snmp_cmd = "snmpwalk -m ".dirname($0)."/../share/BEA-WEBLOGIC-MIB.mib";
my $show_only = ".*";

sub usage {
my ($msg) = @_;
$msg = "" if(!$msg);
my $name = basename($0);
print "Usage :
\$ $name [OPTION]

Get runtime information about WebLogic instance
-h --help display this help and exit.
--intance <SRVNAME>[,<>] name of the instances to check.
--only <REGEXP> show only instance corresponding to regexp.
--snmp <HOST[:PORT]> address (and port) of the snmp server.
-v --verbose verbose.

Examples:
\$ $name --port 10861 --instance srvback11,srvback12,srvback13,srvback14
".($msg ? "\n".$msg."\n" : "")
}

GetOptions(
"V" => \$show_version,
"version" => \$show_version,
"h" => \$show_help,
"help" => \$show_help,
"v" => \$verbose,
"verbose" => \$verbose,
"snmp=s" => \$snmp_address,
"instance=s" => \$instance,
"only=s" => \$show_only,
);

if($show_help) { usage(); exit(0); }
die("Please specify snmp address (--snmp host:port)") if(!$snmp_address);

if(!$instance) {
my(%instance_name, %instance_state) = ((), ());
my @tmp = ();
my ($i, $j) = (0, 0);
foreach(`$snmp_cmd -c public -v 1 $snmp_address 1.3.6.1.4.1.140.625.361.1 2> /dev/null`) {
if(/BEA-WEBLOGIC-MIB::serverLifeCycleRuntimeName.*STRING: "(\w+)"/) {
$instance_name{$i++} = $1;
} elsif(/BEA-WEBLOGIC-MIB::serverLifeCycleRuntimeState.*STRING: "(\w+)"/) {
my $label = $instance_name{$j++};
$instance_state{$label} = $1;
if($1 =~ /RUNNING/) {
print "$label is RUNNING\n" if($verbose);
push(@tmp, $label);
} else {
print "Ignoring $label\n" if($verbose);
}
}
}
$instance = join(",", @tmp);
}

my $perfdata = "";
foreach my $srv(sort(split(/,/, $instance))) {
next if(!($srv =~ /$show_only/));
my @result = `$snmp_cmd -c public\@$srv -v 1 $snmp_address .1.3.6.1.4.1.140.625.340.1 2> /dev/null`;
my($label, $current_max_heap, $free_heap);
foreach(@result) {
if(/BEA-WEBLOGIC-MIB::jvmRuntimeName.*STRING:\s+"(\w+)"/) { $label = $1; }
elsif(/BEA-WEBLOGIC-MIB::jvmRuntimeHeapFreeCurrent.*INTEGER:\s+(\d+)/) { $free_heap = $1; }
elsif(/BEA-WEBLOGIC-MIB::jvmRuntimeHeapSizeCurrent.*INTEGER:\s+(\d+)/) {
$current_max_heap = $1;
$current_max_heap = int($current_max_heap / 1048576 + .5);
$free_heap = int($free_heap / 1048576 + .5);
my $used = $current_max_heap - $free_heap;
$perfdata .= " $label=$used;$current_max_heap;$current_max_heap;0;$current_max_heap";
}
}
}

print "WebLogic memory OK|$perfdata\n";
On configure notre agent pour accepter un nouveau type de commande :
command[check_weblogic_memory]=/usr/lib/nagios/plugins/check_weblogic --snmp localhost:7061
On configure un nouveau service sous Nagios :
define service {
host_name machine-weblogic
use generic-service
service_description Suivi memoire WebLogic
check_command check_nrpe!check_weblogic_memory
}
Et hop ! Au bout de quelques jours, vous obtenez le résultat suivant (en combinaison avec pnp4nagios) :