lid's Wiki

title: Supervision: Initiation
description: Bases de la supervision: découverte de SNMP, et de Zabbix
published: true
date: 2024-02-07T20:45:33.434Z
tags:
editor: markdown
dateCreated: 2024-02-07T20:41:24.937Z

Définitions et concepts

Introduction

La supervision d'une infrastructure a pour but de garantir la disponibilité et les niveaux de service de cette infrastructure. Pour cela, elle doit pouvoir surveiller l'infrastructure en collectant des /métriques/ pertinentes, tant matérielles qu'applicatives, et aussi être en mesure d'informer et d'alerter en cas de situation anormale, et ce, afin de garantir la remontée de l'alerte et un temps d'intervention (ou pire, d'indisponibilité du service) minimal.

Les alertes de supervision sont basées sur des mesures effectuées à intervalle réguliers qui seront effectuées par un ou plusieurs outil(s) de /métrologie/ et qui seront comparées avec des seuils prédéfinis.

De même, certaines solutions de supervision peuvent intégrer des outils automatisés de résolution d'incidents mineurs (par exemple, relancer un service automatiquement. On peut faire une analogie avec le fonctionnement d'orchestrateurs comme Docker Swarm ou Kubernetes qui relançeront automatiquement un container s'étant mis "en carafe"), ce qu'on nomme /Supervision 2.0/ ou /hypervision/.

On peut distinguer - hors supervision industrielle - trois grands types de supervision:

Avantages de la Supervision

La supervision possède de nombreux avantages et est indispensable à tout système d'information sérieux:

En effet, un système efficace de supervision va permettre:

Par là, on va pouvoir:

Métrologie

Un outil de métrologie a pour fonction de mesurer les ressources du système d'information. Il est en général intégré à la solution de supervision.

Lorsque l'on met en place nos outils de métrologie, il est nécessaire de définir quelles métriques sont pertinentes ainsi que les méthodes de mesure permettant de collecter ces métriques.

On utilise deux types de mesures:

Métrique

Une métrique, c'est une caractéristique mesurable de l'infrastructure, définie de façon rigoureuse et précise. Elle permet de déterminer si une situation est normale ou anormale, et d'effectuer des comparaisons:

Exemples de logiciels de supervision

Il existe de nombreux logiciels de supervision, libres et propriétaires, certains monolithiques, d'autres modulaires, d'autres n'étant que des "briques" que l'on peut ajouter les uns aux autres pour former notre système de supervision (exemple: collecteur de données (collectd, telegraf, statsd, cadvisor)-> agrégateur de données (Carbon, InfluxDB) -> affichage (Grafana)).

Parmi les plus connus:

nagios.png

nagios2.png

zabbix.png

screenz1.png

graf1.png

graf2.png

On peut aussi collecter des informations autres que purement "informatiques", afin de voir l'évolution d'une plateforme. Bon évidemment, c'est le moment où mon "check" du temps de réponse est out (il faut donc que je le mette à jour 😃)

SNMP: Simple Network Management Protocol

Concepts et Définitions

Définition

SNMP, Simple Network Management Protocol, soit "protocole simple de gestion du réseau" (je me demande souvent si le "simple" n'est pas ironique ici:)) est un protocole de communication, en UDP, qui utilise, pour les clients, le port 161, et pour le(s) serveur(s) de management, le port 162. Il permet de superviser et diagnostiquer à distance différents équipements, du routeur au serveur en passant par les commutateurs.

SNMP est basé sur trois éléments principaux:

Typiquement, on utilisera SNMP pour administrer les équipements (on peut exécuter des scripts à distance via SNMP) et pour surveiller le comportement du matériel.

Versions du protocole SNMP

Il existe trois versions du protocole SNMP (on utilisera de préférence la v3 pour des raisons évidentes, mais il reste la possibilité de devoir superviser des matériels plus anciens utilisant des versions antérieures du protocole):

SNMPv3 permet 3 modes de communication:

MIB

mib.jpeg

SNMP utilise ce qu'on appelle des MIBs (Management Information Base, qui constituent une base de données rassemblant les objets de gestion et supervision (OID, on y revient plus bas) des nœuds de notre réseau de communication. Les objets en question sont définis selon un ensemble de la syntaxe Abstrace Syntax Notation One, ASN.1, appelé Structure de Gestion de l'Information, dans sa version 2 (RFC 2578).

Cette base de données est hiérarchique (structure en forme d'arbre) et chaque entrée (Managed Object) de cette base de données est associée à un Object IDentifier, OID.

Un Managed Object peut être de deux types:

Ce qui nous amène à la définition de ce qu'est un Object IDentifier. Attention, ça picote.

OID

Un OID, identificateur d'objet, est tout d'abord un standard de l'ITU (International Telecommunications Union) et de l'ISO/IEC pour nommer tout objet, concept ou "truc" (si si) avec un "nom" persistant qui ne soit pas ambigu. Ces OID sont organisés de façons hiérarchiques et identifiés par une suite de numéros uniques.

Un OID commence toujours par soit:

En règle générale, on utilisera rarement des objets commençant par 0 et 2. (je n'en ai jamais rencontré).

Par exemple, l'OID de tout matériel Cisco (le "top-level" de Cisco dans l'arbre des OIDs) commence par:

1.3.6.1.4.1.9 - atchoum! Qu'est ce que ça veut dire?

le site http://www.oid-info.com (eh oui, http sans S… shrug) permet de
parcourir l'arbre complet des OIDs.

Mise en place de SNMP

Pour cela, nous allons avoir besoin de deux VMs - Debian Trixie SVP 😃. La première sera notre VM superviseur (aka NMS), et la seconde constituera notre premier nœud.

Installation sur le NMS et sur le node

Sur notre VM "superviseur" (NMS), nous allons installer snmp ainsi que snmp-mibs-downloader, qui contient des informations propriétaires (sigh) permettant l'accès à la plupart de l'arbre des OIDs:

Note: il est fort possible que vous deviez activer les dépôts non-free sur Debian. Si vous ne savez pas comment faire... demandez moi 😃

NMS $ sudo apt update && sudo apt install snmp snmp-mibs-downloader

Sur notre VM "node1", nous allons juste installer snmpd:

node1 $ sudo apt update && sudo apt install snmpd

Configuration du NMS

La configuration est ici très simple. On va simplement éditer le fichier de configuration de snmp pour qu'il prenne en compte nos MIBs propriétaires (sigh):

NMS $ sudo vim /etc/snmp/snmp.conf
# commenter la ligne "mibs :":
# mibs :

Et... c'est tout! Je vous rassure, ça va être un peu plus touffu pour la configuration du node.

Configuration de snmpd sur notre node /node1/

node1 $ sudo vim /etc/snmp/snmpd.conf

La première chose à faire va être de configurer l'adresse (et donc l'interface réseau) sur laquelle /snmpd/ écoute. En effet, par défaut (et par sécurité) il écoute uniquement sur localhost (127.0.0.1), sur le port 161.

Petite note sur la sécurité et SNMP

Dans le cas d'une machine (par exemple un serveur dédié (OVH, Online, ou serveurs dans une colo/datacenter)) possédant plusieurs interfaces réseau (virtuelles (VPN) ou physiques (eth0, eth1, enp0s1, eno1, etc) il est plus sûr de ne pas exposer snmpd sur l'interface WAN (ie connectée à Internet directement) mais d'utiliser un réseau privé isolé (RPNG Online, vRack OVH) pour la communication entre le manager et les nodes.

Si la topologie physique du réseau ne le permet pas, on peut aussi utiliser un VPN (man openvpn(8)) pour ajouter une couche de sécurité (et d'authentification) supplémentaire.

Comme on se trouve sur un réseau privé dont on a (normalement) le contrôle, on va donc renseigner l'adresse IP de l'interface réseau de notre VM /node1/ (ici, je prends comme exemple une adresse 172.30.0.2/24 pour notre interface réseau principale):

# on commente d'abord la ligne:
agentAddress	udp:127.0.0.1:161
# Puis:
agentAddress	udp:172.30.0.2:161
# Si on a une adresse IPv6, par exemple 2001:abcd::2/64, notre ligne deviendra (notez les crochets):
agentAddress	udp:172.30.0.2:161,udp6:[2001:abcd::2]:161
# Si on veut ecouter sur toutes les interfaces reseau, en udp et en udp6:
agentAddress	udp:161,udp6:[::1]:161

Tant que nous y sommes, nous allons créer un utilisateur configurator que nous utiliserons uniquement pour la configuration - nous l'effacerons ensuite, lorsque nous aurons créé notre utilisateur supervisor (note: vous pouvez bien sûr leur donner les noms que vous voulez) sur le nœud ET sur le NMS.

Toujours dans /etc/snmp/snmpd.conf:

# on ajoute les lignes suivantes en fin de fichier:
createUser test SHA super_mot_de_passe AES
#rwuser, utilisateur read/write (il peut snmpset), rouser pour un readonly
rwuser configurator priv
rwuser test priv
rwuser supervisor priv
# on quitte notre editeur de texte et on relance le service snmpd:
$ sudo systemctl restart snmpd

Notre config est prête, on va pouvoir se connecter à notre daemon SNMP depuis notre VM de supervision! Mais avant, un petit récapitulatif de la syntaxe générale des commandes SNMP!

Structure type des commandes SNMP

La plupart des outils SNMP vont utiliser les mêmes options de bases, qui sont:

Notre première commande SNMP 😃

Dès lors, la structure de base d'une commande SNMP envoyée depuis notre superviseur vers notre agent SNMP sur notre nœud node1 aura pour forme:

$ snmpcommande -u configurator -l authPriv -a SHA -x AES -A \
  super_mot_de_passe -X super_mot_de_passe 172.30.0.2 OID

On peut même le tester tout de suite et vérifier que notre configuration est correcte dans la foulée:

$ snmpwalk -u configurator -l authPriv -a SHA -x AES -A \
  super_mot_de_passe -X super_mot_de_passe 172.30.0.2 | less
# qui va nous renvoyer la liste des OIDs disponibles, ici sur une VM chez moi:
SNMPv2-MIB::sysDescr.0 = STRING: Linux daoloth 4.9.0-3-amd64 #1 SMP \
# Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (29638) 0:04:56.38
SNMPv2-MIB::sysContact.0 = STRING: Me <me@example.org>
SNMPv2-MIB::sysName.0 = STRING: daoloth
SNMPv2-MIB::sysLocation.0 = STRING: Sitting on the Dock of the Bay
SNMPv2-MIB::sysServices.0 = INTEGER: 72
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORID.1 = OID: SNMP-MPD-MIB::snmpMPDCompliance
SNMPv2-MIB::sysORID.2 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORID.3 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
SNMPv2-MIB::sysORID.4 = OID: SNMPv2-MIB::snmpMIB
SNMPv2-MIB::sysORID.5 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup
# ... etc, etc, etc
HOST-RESOURCES-MIB::hrSWInstalledDate.871 = STRING: 0-1-1,0:0:0.0
HOST-RESOURCES-MIB::hrSWInstalledDate.872 = STRING: 0-1-1,0

Comme vous voyez, il y en a… un énorme paquet!

Par exemple, si on veut uniquement le nom ou l'uptime de la machine node1:

$ snmpget -v 3 -u configurator -a SHA -A super_mot_de_passe -x AES -X \
  super_mot_de_passe -l authPriv 172.30.0.2 SNMPv2-MIB::sysDescr.0
# note, on peut aussi utiliser uniquement sysDescr.0
# qui nous renverra:
SNMPv2-MIB::sysDescr.0 = STRING: Linux daoloth 4.9.0-3-amd64 #1 SMP \
 Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64
# Pour l'uptime:
$ snmpget -v 3 -u configurator -a SHA -A super_mot_de_passe -x AES -X \
  super_mot_de_passe -l authPriv 172.30.0.2
HOST-RESOURCES-MIB::hrSystemUptime.0
#qui nous renverra (dans le cas de cette VM chez moi - qu'il faut que
#je reboote d'ailleurs)
HOST-RESOURCES-MIB::hrSystemUptime.0 = Timeticks: (1944097103) 225 days, 0:16:11.03
etc.

Ça peut sembler très verbeux, mais ça peut être extrêmement puissant - sachant qu'en prime SNMP est très léger.

On peut aussi interroger notre agent SNMP en utilisant les OID numériques, par exemple on peut remplacer SNMPv2-MIB::sysDescr.0 par 1.3.6.1.2.1.1.1.0

Création et suppression d'utilisateurs SNMPv3

Pour la gestion des utilisateurs en SNMP, nous allons utiliser l'outil snmpusm dont la syntaxe est similaire aux autres outils snmp, et qui utilisera comme template celui d'un utilisateur existant:

$ snmpusm -v... hote_distant create utilisateur utilisateur_existant

Et donc, dans notre cas:

$ snmpusm -v 3 -u configurator -a SHA -A super_mot_de_passe -x AES -X \
super_mot_de_passe -l authPriv 172.30.0.2 create supervisor \
configurator

Maintenant, nous allons changer le mot de passe de l'utilisateur supervisor. En effet, il a le même mot de passe que notre utilisateur configurator, ce qui n'est pas très "propre":

$ snmpusm -v 3 -u supervisor -a SHA -A super_mot_de_passe -x AES -X \
super_mot_de_passe -l authPriv 172.30.0.2 passwd super_mot_de_passe \
mot_de_passe_encore_mieux

Note: un mot de passe SNMPv3 doit faire 8 caractères minimum.

Bon, on va aussi en profiter pour se simplifier la vie. En effet, taper à chaque fois ses identifiants, le protocole utilisé par défaut, etc… c'est pénible, non? On va donc soit modifier notre fichier /etc/snmp/snmp.conf (si on veut que nos paramètres d'identification soient accessibles à tous les utilisateurs de notre manager), soit créer un fichier ~/.snmp/snmp.conf pour que seul notre utilisateur dispose de ces informations - vous avez bien créé un utilisateur? 😃

# on cree notre repertoire
$ mkdir .snmp
$ vim .snmp/snmp.conf
# on va pouvoir ajouter nos informations d'authentification
defSecurityName supervisor
defSecurityLevel authPriv
defAuthType SHA
defPrivType AES
defAuthPassphrase mot_de_passe_encore_mieux
defPrivPassphrase mot_de_passe_encore_mieux
# on sauvegarde et on quitte
Esc:wq ;) (ou Ctrl-C:wq - pratique si Esc n'est pas pris en compte)

Maintenant, on peut simplement faire:

$ snmpget 172.30.0.2 sysUpTime.0

au lieu de se "coltiner" toute les options de chiffrement et d'authentification à la main 😃

Maintenant, on va supprimer notre utilisateur configurator:

Sur notre node1, nous allons commenter les lignes correspondantes à cet utilisateur dans /etc/snmp/snmpd.conf:

# on edite notre fichier avec notre editeur prefere (ViM bien entendu)
#createUser configurator etc
#rwuser configurator priv

Sur notre NMS on supprime l'utilisateur en question:

$ snmpusm 172.30.0.2 delete configurator

Commandes SNMP utiles

Nous avons déjà vu la commande snmpwalk ainsi que snmpusm et snmpget.

Comme nous l'avons vu, par défaut, snmpwalk nous renvoie tout l'arbre… pas très pratique quand on ne cherche que les OIDs "sous-section" d'une OID plus générique. Par exemple, l'OID system:

$ snmpwalk 172.30.0.2 system

Une autre commande très sympathique, c'est snmptranslate qui va nous permettre de:

Exemples:

$ snmptranslate 1.3.6.1.2.1.1.1.0
SNMPv2-MIB::sysDescr.0
# avec le flag -On pour l'operation inverse - lisez la manpage:
$ snmptranslate -On SNMPv2-MIB::sysDescr.0
.1.3.6.1.2.1.1.1.0
# ah oui, le "." au debut, c'est la racine des OID :)
# et le meilleur pour la fin, ici avec l'OID numerique correspondant a l'uptime:
~$ snmptranslate -Td .1.3.6.1.2.1.25.1.1.0                      
HOST-RESOURCES-MIB::hrSystemUptime.0
hrSystemUptime OBJECT-TYPE
-- FROM       HOST-RESOURCES-MIB
SYNTAX        TimeTicks
MAX-ACCESS    read-only
STATUS        current
DESCRIPTION   "The amount of time since this host was last
initialized.  Note that this is different from
sysUpTime in the SNMPv2-MIB [RFC1907] because
sysUpTime is the uptime of the network management
portion of the system."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) host(25) \
hrSystem(1) hrSystemUptime(1) 0 }

On a plusieurs "flags" utilisables avec l'opérateur -O:

Maintenant, on va aussi voir comment on peut obtenir un formatage de la sortie plus lisible que celui de snmpwalk avec la commande snmptable, par exemple ici sur l'OID tcpConn. Testez:

$ snmpwalk 172.30.0.2 tcpConn
# bon courage :)

C'est certes détaillé mais pas réellement lisible humainement parlant. Par contre, avec /snmptable/, on va pouvoir présenter ces données tabulaires sous forme de… tableau (oui oui…)

# par exemple, sur une de mes VMs perso:
$ snmptable 192.168.42.215 tcpConn
SNMP table: TCP-MIB::tcpConnTable

tcpConnState tcpConnLocalAddress tcpConnLocalPort tcpConnRemAddress tcpConnRemPort
listen             0.0.0.0               13           0.0.0.0              0     
listen             0.0.0.0               22           0.0.0.0              0     
listen             0.0.0.0               37           0.0.0.0              0     
listen             0.0.0.0               80           0.0.0.0              0     
listen             0.0.0.0              111           0.0.0.0              0     
listen             0.0.0.0             2049           0.0.0.0              0     
listen             0.0.0.0            37011           0.0.0.0              0     
listen             0.0.0.0            38595           0.0.0.0              0     
listen             0.0.0.0            45737           0.0.0.0              0     
listen             0.0.0.0            55333           0.0.0.0              0     
listen           127.0.0.1               25           0.0.0.0              0     
listen           127.0.0.1             4005           0.0.0.0              0     
established           127.0.0.1             4005         127.0.0.1          38228
established           127.0.0.1            38228         127.0.0.1           4005
established      192.168.42.215               22     192.168.42.10          48706

Qui est ensuite facilement transformable en tableau, csv ou, ici,
org-mode:

tcpConnState tcpConnLocAddr tcpConnLocPort tcpConnRemAddr
listen 0.0.0.0 13 0.0.0.0
listen 0.0.0.0 22 0.0.0.0
listen 0.0.0.0 37 0.0.0.0
listen 0.0.0.0 80 0.0.0.0
listen 0.0.0.0 111 0.0.0.0
listen 0.0.0.0 2049 0.0.0.0
listen 0.0.0.0 37011 0.0.0.0
listen 0.0.0.0 38595 0.0.0.0
listen 0.0.0.0 45737 0.0.0.0
listen 0.0.0.0 55333 0.0.0.0
listen 127.0.0.1 25 0.0.0.0
listen 127.0.0.1 4005 0.0.0.0
established 127.0.0.1 4005 127.0.0.1
established 127.0.0.1 38228 127.0.0.1
established 192.168.42.215 22 192.168.42.10

C'est tout de suite plus lisible, non? 😃

On a vu que snmpwalk nous permet de parcourir tout l'arbre, ou juste un /subset/ (branche) de cet arbre. On peut aussi utiliser la commande snmpgetnext pour passer d'OID en OID, par exemple:

$ snmpbulkget 172.30.0.2 hrSystem
HOST-RESOURCES-MIB::hrSystemUptime.0 = Timeticks: (1949936967) 225 days, 16:29:29.67
# etc etc etc

et par exemple avec snmpbulkwalk:

$ snmpbulkwalk 192.168.42.215 vacmAccess
SNMP-VIEW-BASED-ACM-MIB::vacmAccessContextMatch."grpcomm1"."".0.noAuthNoPriv = INTEGER: prefix(2)
SNMP-VIEW-BASED-ACM-MIB::vacmAccessContextMatch."grpcomm2"."".0.noAuthNoPriv = INTEGER: prefix(2)
SNMP-VIEW-BASED-ACM-MIB::vacmAccessContextMatch."grpsupervisor"."".3.authPriv = INTEGER: prefix(2)
SNMP-VIEW-BASED-ACM-MIB::vacmAccessContextMatch."grpauthOnlyUser"."".3.authNoPriv = INTEGER: prefix(2)
#... etc etc etc 

En fait, au lieu d'envoyer un paquet par ligne, les commandes bulk vont envoyer plusieurs lignes par paquet.

Bon, toutes ces commandes, c'est certes sympa, mais c'est quand même mieux d'avoir une solution de supervision qui va nous générer de beaux graphes et tableaux à partir des données que nous pouvons extraire via SNMP, non?

Traps SNMP, INFORM SNMPv3

Les Traps (et INFORM pour SNMPv3) snmp permettent aux agents d'envoyer directement au NMS SNMP des informations pertinentes (up/down d'une interface réseau par exemple).

Elles sont documentées dans la RFC 1157 pour SNMPv1 (mais qui utilise encore SNMPv1?), 1907 pour SNMPv2 et 3413 à 3415 pour SNMPv3. Le NMS doit disposer des MIBs contenant les OIDs correspondant aux Traps SNMP envoyées par les agents (i.e. si l'agent est utilisé sur du matériel Cisco, Juniper ou autre, le NMS doit disposer des MIBs correspondantes pour pouvoir comprendre la signification de la trap ou du message INFORM envoyés).

Comme nos agents envoient directement les informations au NMS sans répondre à une requête de ce dernier, elles ont plusieurs avantages:

Une des différences majeures entre une Trap SNMP et un INFORM SNMP (introduit dans SNMPv2) est que l'agent, dans le premier cas, ne sait pas si le NMS a bien reçu le message (il n'y a pas de ACK transmis par le NMS).

De même, il y a plusieurs différences dans l'implémentation des Traps (et INFORM) entre SNMPv1/2 et SNMPv3. En effet, SNMPv3 impose que le message soit rejeté si:

Cela signifie que contrairement à SNMPv1/2, où le message sera pris en compte tant qu'il appartient à la même communauté, SNMPv3 impose d'avoir un couple utilisateur/engineID pour chaque agent de votre infrastructure. C'est à dire que si vous avez 100 agents SNMP, il vous faudra… 100 directives createUser dans votre configuration de snmptrapd (conseil: sortez les scripts 😉).

Configuration de snmptrapd sur un NMS UNIX/UNIX-like

La première chose à faire est d'installer - via le gestionnaire de paquets de la distribution utilisée - le paquet correspondant à snmptrapd, ici pour Debian et dérivés:

$ sudo apt install snmptrapd

On va ensuite configurer snmptrapd, on coupe d'abord le service (et on le lancera "à la main" ensuite pour envoyer notre premier message INFORM et vérifier qu'il est bien arrivé):

$ sudo systemctl stop snmptrapd
$ sudo vim /etc/snmp/snmptrapd.conf
# on ajoute en fin de fichier:
createUser supervisor SHA supermotdepasse AES supermotdepasse
# on autorise l'utilisateur a envoyer des infos de log
# on peut l'autoriser a envoyer d'autres choses (execute (envoyer les
# details de l'inform ou trap a un programme ou script), net (envoyer
# les notifs a un autre NMS))
authUser log supervisor
# ou par ex: authUser log,execute supervisor

Pour le moment, on ne va pas relancer snmptrapd via systemctl start snmptrapd mais on va le lancer "à la mano":

$ sudo snmptrapd -f -C -c /etc/snmp/snmptrapd.conf -Le

Maintenant, si on se place sur notre node1, et qu'on envoie un INFORM avec nos informations d'authentification:

$ sudo snmpinform -v 3 -a SHA -A supermotdepasse -x AES -X \
supermotdepasse -l authPriv -u supervisor 172.30.0.1 1 \
SNMPv2-MIB::coldStart

On devrait obtenir, dans le /log/ de notre snmptrapd sur notre NMS:

2018-03-13 15:21:45 daoloth.lidless.lan [UDP: \
[192.168.42.215]:39420->[192.168.42.213]:162]: \
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1) 0:00:00.01 \
SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-MIB::coldStart

"Indiquant" que notre machine node1 vient de redémarrer "brutalement".

Maintenant, la question, c'est "comment automatiser l'envoi de messages INFORM (ou de TRAPs)" depuis notre machine /node1/, ce qui nous amène au chapitre suivant 😃

Configuration des agents SNMPv3 sur matériel Cisco

Il faut tout d'abord créer notre utilisateur SNMP (et le groupe auquel il appartient) sur notre routeur (ou commutateur):

Router- enable
Router- conf t
Router(config)- snmp-server user supervisor group nom_de_groupe v3 \
auth SHA mot_de_passe priv AES passphrase [access {accesslist}]

Tester ensuite depuis notre NMS que nous:

De même, on peut tester la configuration SNMP de notre matériel via
différentes commandes show

Router- ena
Router- show snmp user utilisateur
Router- show snmp group

Auto-Discovery via SNMP

Il est possible de découvrir quasi-automatiquement - et avec un peu de scripting - l'ensemble d'un réseau de machines "discutant" en SNMP (i.e dans la même communauté pour SNMPv1, v2c, et disposant des mêmes informations d'identification pour SNMPv3). Il suffit, en partant d'une machine dont nous pouvons interroger l'état des interfaces réseau via /snmpget/ par exemple, de chercher les OIDs correspondant à ses interfaces réseau, qui vont nous indiquer… avec quelles machines elle est interconnectée. De là, on peut ensuite, depuis notre NMS,
interroger successivement les machines découvertes selon le même
principe pour pouvoir "mapper" tout le réseau rapidement.

On sort un peu du programme de ce cours, mais je vous laisse explorer la piste 😃

Zabbix

Installation sur notre VM de supervision

Alors, pour ce TP, nous allons nous simplifier la vie et utiliser Docker pour installer Zabbix.

Tout d'abord, on installe sur notre VM les paquets suivants:

sudo apt install docker.io docker-compose
# on ajoute notre utilisateur au groupe docker
sudo usermod -aG docker votre-utilisateur
# déloggez-vous/déconnectez-vous de SSH/etc
# et reconnectez vous pour prendre en compte
# votre nouveau groupe

ensuite, nous allons créer un fichier docker-compose.yml

version: '3'

services:
  zabbixdb:
    image: postgres:13-alpine
    environment:
      - POSTGRES_DB=zabbix
      - POSTGRES_USER=zabbix
      - POSTGRES_PASSWORD=epsiepsi
    volumes:
    - zabbixpg-data:/var/lib/postgresql/data
  zabbixserver:
    image: zabbix/zabbix-server-pgsql:alpine-latest
    environment:
      - DB_SERVER_HOST=zabbixdb
      - POSTGRES_USER=zabbix
      - POSTGRES_PASSWORD=epsiepsi
    links:
      - zabbixdb
    depends_on:
      - zabbixdb
    ports:
      - 10050:10050
      - 10051:10051/udp
  zabbixweb:
    image: zabbix/zabbix-web-nginx-pgsql:alpine-latest
    environment:
      - DB_SERVER_HOST=zabbixdb
      - POSTGRES_USER=zabbix
      - POSTGRES_PASSWORD=epsiepsi
      - PHP_TZ=Europe/Paris
      - ZBX_SERVER_HOST=zabbixserver
    links:
      - zabbixdb
      - zabbixserver
    depends_on:
      - zabbixdb
      - zabbixserver
    ports:
      - 9080:8080
      
volumes:
  zabbixpg-data:
    driver: local

Configuration utilisateurs

On se connecte à notre Zabbix: http://IP_VM_Zabbix

Les login et mot de passe de base sont: Admin/zabbix, à changer
rapidement bien sûr 😉

Note: évidemment, en production, on utiliserait un IDP (LDAP/AD/OIDC/etc) pour identifier nos utilisateurs, les groupes auxquels ils appartiennent et les permissions à leur accorder

Ajout de notre node à monitorer

Ça tombe bien, on a nos VMs qui n'attendent que ça 😃

Direction le menu Configuration/Hosts, puis on clique sur Create Host. Dans notre cas, on choisit le groupe Linux Server.

On renseigne un nom d'hôte "parlant" pour notre machine /node1/, puis on renseigne le champ Agent Interfaces. Remarquez qu'on a aussi notre copain SNMP dans la liste des interfaces disponibles…

Quelles métriques pertinentes pour notre node?

Pour le moment, si notre hôte est bien configuré, il ne nous remonte aucune information. Il faut en effet configurer les Items que notre NMS va suivre et stocker en base de données concernant cet hôte.

Dans la terminologie Zabbix, un item correspond à une métrique récupérée sur un hôte précis.

Ici, on se place donc sur l'hôte que nous venons de créer, et on clique sur le lien items, puis sur Create item.

ici, on va par exemple créer un item nous permettant de récupérer la valeur du Load CPU à un instant t: system.cpu.load

On procède de la même façon pour collecter d'autres métriques que l'on jugera pertinentes (ex: bande passante, I/Os disque, RAM, etc).

Par contre, dans le cas oú on aurait une centaine d'hôtes similaires à monitorer, ça risque de devenir rapidement barbant de les faire un par un (et juste un peu contre-productif). On va voir qu'on peut en fait facilement générer des modèles d'hôtes via les templates. Mais d'abord, comment déclencher une alerte au cas oú un paramètre de nos hôtes dépasse un seuil établi?

Triggers

Il s'agit des limites acceptables en deça desquelles aucune alerte n'est envoyée/affichée dans le dashboard. Là encore c'est "self-explanatory": menu Configuration/Hosts, on sélectionne notre hôte, puis enfin on clique sur triggers et enfin sur Create trigger.

la syntaxe d'un trigger est de la forme:

{Hostname:type.sous-type.valeur.calcul(intervalle de temps)}>valeur
# ou =, ou <, etc

Par exemple, sur une machine 12 coeurs, 24 threads dont le nom est
Front1:

{Front1:system.cpu.load.avg(120)}>24

Signifie: alerter d'un problème si le load moyen de Front1 est supérieur à 24 pendant deux minutes.

Templates

Pour créer un /template/ on va se placer dans le menu Configuration/Templates (original, non?)

On peut définir des templates contenant plusieurs items, triggers, etc pour des hôtes possédant des rôles similaires. De même on peut lier un hôte a plusieurs templates.

Par exemple, imaginons qu'on ait un hôte:

On pourra par exemple lui appliquer un template "Linux Générique" nous permettant de collecter les données de base de l'OS: CPU, RAM, I/Os, espace disque.

Puis un template "BDD SQL", nous remontant les valeurs types d'une BDD: Nombre de QPS, buffers, deadlocks, etc.

Bien évidemment, ces templates pourront aussi posséder des triggers spécifiques, par exemple:

Services

Un service est un ensemble d'hôtes participant à l'exécution d'une tâche plus complexe.

Par exemple, on peut imaginer qu'un service Web va se composer:

L'ensemble de ces machines et des logiciels qu'ils exécutent formant ce qu'on appelle un service du point de vue Business. il est donc important de déterminer l'impact du mauvais fonctionnement d'une de ces machines ou d'un de ces logiciels. Par exemple, sur un gros cluster Riak composé d'une trentaine de machines, le fait qu'une ou deux machines soient DOWN n'est pas impactant pour le Service et donc pour le business. Pas besoin de réveiller un adminsys pour ça en pleine nuit 😃.

À l'inverse, si la BDD Master est tombée, et que donc, par exemple dans le cas d'un site de e-commerce, les utilisateurs ne peuvent plus enregistrer leurs actions (achats, etc) l'impact business n'est plus le même - et là on réveillera le sysadmin 😉

Autres solutions de supervision

WMI: Windows Monitoring Instrumentation

WMI est un peu le SNMP "sauce Windows" (on peut aussi utiliser SNMP sous Windows). Il dérive du standard WBEM (Web-Based Enterprise Management) et CIM (Common Information Model) du DMTF (Distributed Management Task Force). Il permet d'obtenir de nombreuses informations sur l'état de Windows ainsi que d'exécuter des scripts (powershell, etc) en fonction de l'état du système.

Collectd/statsd, Prometheus, InfluxDB, Grafana, etc

Il existe de nombreux systèmes de collecte (au moins autant que de logiciels de supervision) permettant de collecter des informations de supervision depuis des machines sous UNIX ou GNU/Linux. Certaines sont dites /agentless/ dans le sens où - typiquement - c'est le système de supervision qui va se connecter (par exemple en SSH) aux machines supervisées pour collecter les données en exécutant des commandes spécifiques (c'est le cas de MicroFocus (ex HP) SiteScope). D'autres requièrent l'installation d'un agent spécifique (exemple libre: collectd, exemple propriétaire: NewRelic) sur chaque machine supervisée.

Ces agents permettent de collecter des données à la fois système (load, entrées/sorties, etc) et applicatives (par exemple le nombre de requêtes exécutées par un serveur Web ou un reverse-proxy) voire plus détaillées (temps de réponse de PHP-FPM ou WSGI par exemple, mais aussi temps d'exécution d'une fonction précise de l'applicatif (statsd), très pertinent pour pouvoir /remonter/ des informations aux développeurs de l'applicatif afin de pouvoir améliorer le code et donc la qualité de service.

l'agrégateur de données consiste en général en une base de données (InfluxDB par exemple, mais on peut aussi utiliser PostGreSQL, MariaDB ou même SQL Server pour les masochistes, voire MongoDB si vous n'avez pas peur qu'il oublie des données - véridique 😄) qui va stocker les données collectées dans différentes tables, et y appliquer des règles de rétention (par exemple, conserver les données stockées sur un mois, puis ensuite passer à une métrique par heure, puis par jour, etc en fonction de l'éloignement temporel de cette métrique).

Enfin, on va afficher ces données via un logiciel de supervision (Shinken, Nagios, etc), voire avec un logiciel qui ne fait qu'afficher ces données (Grafana) qui va interroger l'agrégateur à chaque requête de l'utilisateur pour générer les graphiques représentant l'évolution des métriques collectées dans le temps.

De même, il existe aussi des outils de monitoring (et d'alerte) de logs (les plus connus étant basés sur la /stack/ ELK (ElasticSearch, Logstash, Kibana), par exemple OSSEC, Whazu (assez excellent), qui vérifient aussi la conformité PCI-DSS de l'infrastructure au fil du temps et peuvent pointer de potentielles failles dans votre infrastructure.