Monitorer les IOPS via Nagios

Catégorie : Monitoring Écrit par Milosz Szot

Niveau : intermédiaire

Nagios n'a pas de moniteur pour mesurer les IOPS, par défaut, comme la plupart des logiciels de monitoring d'ailleurs.
Nous allons donc modifier le moniteur "Check DiskIO via SNMP" écrit par Herbert Stadler, qui correspond à peu près à nos besoins.

C'est le plus cohérent de tous les plugins que j'ai trouvé :
je suis franchement tombé sur des horreurs lorsque je cherchais un plugin correct :
- ceux qui se basaient sur NRPE, alors que le SNMP permet par définition d'interroger les compteurs, qui existent quelque soit leur système d'exploitation (portabilité, facilité d'utilisation)
- ceux qui vérifiaient la bande passante au lieu des IOPS : c'est une information totalement sans valeur et qui peut facilement induire en erreur, puisque le débit va s'écrouler si le périphérique est saturé, alors que les IOPS explosent
- ceux qui comptaient les IOPS totaux, sans séparer les lectures et les écritures, alors que la distinction est de plus haute importance : lectures et écritures n'ont pas le même poids, surtout sur une grappe RAID, et doivent pouvoir être mesurées séparément lorsqu'on analyse les performances de certains clusters applicatifs, notamment les bases de données, la réplication, etc

Sur celui-là, il n'est juste pas possible de changer le type d'IOPS pour les warnings et les criticals via un paramètre, puisque les alertes sont configurées sur le compteur UCD-DISKIO-MIB::diskIONWritten "en dur" dans le script, via la variable $checkval.
Il y a 4 types d'indicateurs de performance possibles, les IOPS Read, les IOPS Write, et éventuellement la bande passante read et write, en MO/s (peu pertinents de mon point de vue, à part pour du steaming vidéo par exemple).

En l'état, pour pouvoir se servir de tous les indicateurs, il faudrait maintenir 4 copies du script, avec 4 commandes différentes configurées sur Nagios ...
Je préfère prendre le problème à la source, et adapter son comportement pour le rendre plus souple, une bonne fois pour toutes, afin de me simplifier le travail en aval.
Un seul script, une seule commande Nagios.

Nous allons donc devoir légèrement le comportement du script, c'est l'affaire de quelques minutes.

Vous pouvez télécharger le plugin d'origine sur : http://exchange.nagios.org/directory/Plugins/Network-Protocols/SNMP/Check-DiskIO-via-SNMP/details

Vous trouverez le script entier, modifié par mes soins sur mon site, il est relativement propre, et je crois avoir mis en conformité l'intégralité du script, afin de ne pas se retrouver avec un programme "semi-fonctionnel", à demi-cassé.
http://www.scalabilite.org/images/milonz/scripts/check_diskio_ucd.txt

Modification manuelle du script

Une fois la dernière version d'origine téléchargée, attribuer les droits d'exécution au script (755), et le placer dans le répertoire /usr/lib/nagios/plugins.
Un script Nagios est indépendant, et il est préférable de l'exécuter via la ligne de commande pour le tester, pour voir s'il s'exécute correctement, qu'il n'a pas de dépendances non satisfaites, etc.

Le prototype de la commande d'origine est le suivant :
Usage: check_diskio_ucd [-h] [-L] [-t timeout] [-v] [-V] [-C community] [-p port] [-s 1|2|3] -H hostname -d diskdevice -w <warning> -c <critical>
SNMP version 3 specific: [-u username] [-o authpass] [-r authprot] [-O privpass] [-R privprot]

Nous allons passer par sntmp v2, la communauté public, l'hôte 192.168.0.69, et interroger le device dm-0, la grappe RAID5.
/usr/lib/nagios/plugins/check_diskio_ucd -C public -s 2 -H 192.168.0.69 -d dm-0 -w 50 -c 100

Ajout d'un "type" d'IOPS pour les warnings du script

Il sera défini par le paramètre "-T" (à ne pas confondre avec "-t", pour la valeur timeout), qui deviendra un paramètre obligatoire à l'exécution du script.
La valeur du paramètre sera transférée dans la variable $opt_type.

C'est parti ...

Définition de la variable $opt_type, ligne 53 :

my ($mycheckval,$opt_type,$opt_type_op,$opt_type_metric);

Effacer la section du programme qui traite de la variable, de la ligne 178 à la ligne 192, et ajouter la section suivante :

my $checkval = $IONWrittenMBsec;

if ($opt_type eq "readio") {
 $opt_type_op = "Read";
 $opt_type_metric = "IOPS";
 $checkval = $IOReadssec;
};
if ($opt_type eq "writeio") {
 $opt_type_op = "Write";
 $opt_type_metric = "IOPS";
 $checkval = $IOWritessec;
};
if ($opt_type eq "bytesread") {
 $opt_type_op = "Read";
 $opt_type_metric = "MB/s";
 $checkval = $IONReadMBsec;
};
if ($opt_type eq "byteswritten") {
 $opt_type_op = "Write";
 $opt_type_metric = "MB/s";
 $checkval = $IONWrittenMBsec;
};

  if ( $checkval < $opt_warn ) {
    $msg = sprintf("DISKIO OK - No Problems found (%s %d %s)",$opt_type_op,$checkval,$opt_type_metric);
    $state = $ERRORS{'OK'};
  }elsif ( $checkval < $opt_crit ) {
    $msg = sprintf("DISKIO WARN - %s %d %s",$opt_type_op,$checkval,$opt_type_metric);
    $state = $ERRORS{'WARNING'};
  }else{
    $msg = sprintf("DISKIO CRIT - %s %d %s",$opt_type_op,$checkval,$opt_type_metric);
    $state = $ERRORS{'CRITICAL'};
  }
  last;
}

Prise en compte du paramètre -T dans la variable $opt_type, dans la section GetOptions, ligne 345 :

"T=s" => \$opt_type,
"iotype=s" => \$opt_type,

La variable $opt_type est rendue obligatoire, ligne 395 :

  unless (defined $opt_type) {
    print "\nERROR: parameter -T <iotype> not defined\n\n";
    print_usage();
    exit ($ERRORS{'UNKNOWN'});
  }

Si le type n'est pas readio, writeio, bytesread, ou byteswritten, aussi terminer l'exécution du programme, ligne 433 :

  if (($opt_type ne "readio") && ($opt_type ne "writeio") && ($opt_type ne "bytesread") && ($opt_type ne "byteswritten")) {
    printf ("\nERROR: IO Type %s unknown\n",$opt_type);
    print_usage();
    exit $ERRORS{'UNKNOWN'};
}

Ajout du paramètre dans les règles d'usage, en remplaçant la ligne 440 :

print "Usage: $PROGNAME [-h] [-L] [-t timeout] [-v] [-V] [-C community] [-p port] [-s 1|2|3] -H hostname -d diskdevice -T IOtype -w <warning> -c <critical>\n\n";

Ajout du paramètre dans l'aide, avant les options snmp, ligne 456 :

printf("-T (--iotype) IO Type [readio|writeio|bytesread|byteswritten]\n");

Intégration dans Nagios

Voyons comment intégrer le script pour SNMP v2 :

Nous avons besoin d'une commande qui prenne en compte l'hôte, la communauté,  le périphérique visé, le type d'IOPS, ainsi que les seuils d'alertes warning et critical, comme d'habitude.
Les alertes concernent le type d'IOPS vérifié, et non pas tous les types d'IOPS : si vous vérifiez les readio, les alertes ne seront pas activées pour les writeio, donc.
Ca correspond surtout à la façon dont j'organise mes sondes, je sépare les readio des writeio, pour chacun des périphériques : en cas d'alerte, je n'ai pas besoin de me demander si ce sont les lectures ou les écritures qui posent problème, puisque ce sont deux sondes différentes qui gèrent ces valeurs.
Avec les templates et les groupes que j'ai crée, le supplément de travail est réellement minimal !

Editer le fichier /etc/nagios3/conf.d/mycommands.cfg, et ajouter la section suivante :

define command {
        command_name check_diskio_ucd
        command_line $USER1$/check_diskio_ucd -s 2 -H $HOSTADDRESS$ -C $ARG1$ -d $ARG2$ -T $ARG3$ -w $ARG4$ -c $ARG5$
}

Je décide d'appliquer systématiquement la sonde sur mon groupe debian-servers, et de vérifier le disque sda.
Je n'ajoute que très rarement des disques supplémentaires, hormis certaines grappes RAID.
Dans ce cas-là, j'ajouterai la sonde au cas par cas, dans la configuration de la machine.
Elles sont pour la plupart virtualisées et stockées sur une grappe RAID distante, je leur fixe des limites assez génériques, qui seront ajustées si besoin est : 50 IOPS pour la lecture, 30 IOPS pour l'écriture.

Editer le fichier /etc/nagios3/conf.d/myservices.cfg, et ajouter les deux sections suivantes :

define service{
        use                             generic-service
        hostgroup_name                  debian-servers
        service_description             Disk IO Reads sda
        check_command                   check_diskio_ucd!public!sda!readio!50!100
        }


define service{
        use                             generic-service
        hostgroup_name                  debian-servers
        service_description             Disk IO Writes sda
        check_command                   check_diskio_ucd!public!sda!writeio!30!60
        }

Redémarrer Nagios :

/etc/init.d/nagios3 restart

Conclusion

Vous avez maintenant un script qui vous permet de monitorer et de mesurer les performances des disques, séparément, pour les opérations de lecture et d'écriture.
Ces informations sont, selon mon opinion personnelle, cruciales pour identifier un bottleneck (goulot d'étranglement) sur votre infrastructure, et dimensionner correctement.

Prenez par exemple un cluster de bases de données MySQL :

Si les IOPS en lecture saturent, il vous suffit d'ajouter un nouveau slave.
L'applicatif est configuré pour faire les requêtes en lecture sur les différents slaves, qui se partagent ces traitements-là (dimensionnement horizontal, "scaling-out").

Si les IOPS en écriture saturent, c'est nettement plus compliqué, puisqu'elles sont répliquées sur chaque nœud du cluster.
Il faut alors changer les disques de tous les membres du cluster pour améliorer les performances (dimensionnement vertical, "scaling-up").
Ou encore mieux, "sharder" la base de données (la base est "éclatée" sur plusieurs clusters différents, ce qui permet de confiner les problématiques des écritures liées à la réplication, aux tables dont chaque cluster a la gestion).

Partager l'article

Submit to FacebookSubmit to Google PlusSubmit to Twitter