Prenez soin de vos machines avec LibreNMS

Spécialité(s)


Résumé

Dans un article précédent [PROXMOX], je vous ai conté ma vie d’éleveur de machines virtuelles. À cette occasion, j’avais évoqué la nécessité de bien prendre soin de nos machines, et pour ce faire nous avons à notre disposition un très bon outil : LibreNMS. Voyons donc, sans plus attendre, comment en tirer parti !


Body

1. Pourquoi utiliser un tel outil en 2022 ?

Comme son nom l’indique, LibreNMS est un système de monitoring réseau. Les lettres NMS signifiant Network Monitoring System.

Mais pourquoi utiliser un système de monitoring « vieillot » alors qu’il existe des solutions bien plus récentes et plus jolies ? La réponse est simple : je pense qu’il peut être intéressant d’avoir plusieurs systèmes de monitoring à la fois, chacun répondant à un besoin spécifique.

Tout d’abord, c’est un peu comme multiplier les sources pour vérifier une information, cela évite les erreurs !

Ensuite et surtout, je trouve que certains systèmes sont plus adaptés que d’autres à certaines tâches. Je m’explique.

Avec des outils comme Telegraf / Node Exporter, Prometheus / InfluxDB et Grafana, vous aurez de magnifiques graphes avec des données en quasi temps réel. C’est beau et très pratique pour analyser une situation récente. Par contre, côté configuration, c’est un peu laborieux. Déjà, il faut installer un paquet de logiciels côté serveur, et aussi un logiciel côté client. Côté serveur, il faudra aussi se lancer dans la création de « dashboard » sur Grafana. Beaucoup d’étapes (automatisables) avant d’avoir accès à vos données !

D’un autre côté, il y a LibreNMS (ou plus généralement, les outils de monitoring basés sur SNMP). Côté serveur, il suffit d’installer un seul outil : LibreNMS, et côté client, il faut activer et configurer le service snmpd. Les graphes sont statiques et bien moins jolis qu’avec Grafana. Par contre, par défaut, la plupart des métriques sont déjà « monitorées » (pour la suite de l’article, je vais utiliser le verbe surveiller), toutes ces valeurs sont déjà visibles via l’interface web et classées par catégories. En quelques secondes, tout fonctionne.

Une fois les deux solutions configurées, je trouve qu’il est plus agréable d’utiliser une pile de logiciels type TIG (Telegraf, InfluxDB, Grafana) pour effectuer des recherches précises en cas de problème sur un serveur, pour un « debug » en temps réel ou une analyse plus poussée dans les jours qui suivent.

Par contre, je préfère avoir un outil comme LibreNMS pour conserver un historique sur le long terme sans prise de tête. Et bizarrement, peut-être, je préfère aussi LibreNMS pour gérer les alertes !

2. Installation, côté serveur

Je vais être honnête avec vous, cela fait bien longtemps que j’ai installé un programme à la main. J’utilise Docker, et une fois le rôle Docker déployé sur mes serveurs, j’installe les programmes avec un simple fichier : docker-compose.yml.

Nous allons procéder ainsi pour LibreNMS dont voici le docker-compose.yml [COMPOSE] :

version: "3.5"
 
services:
  db:
    image: mariadb:10.5
    container_name: librenms_db
    command:
      - "mysqld"
      - "--innodb-file-per-table=1"
      - "--lower-case-table-names=0"
      - "--character-set-server=utf8mb4"
      - "--collation-server=utf8mb4_unicode_ci"
    volumes:
      - "./db:/var/lib/mysql"
    environment:
      - "TZ=${TZ}"
      - "MYSQL_ALLOW_EMPTY_PASSWORD=yes"
      - "MYSQL_DATABASE=${MYSQL_DATABASE}"
      - "MYSQL_USER=${MYSQL_USER}"
      - "MYSQL_PASSWORD=${MYSQL_PASSWORD}"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-db
 
  memcached:
    image: memcached:alpine
    container_name: librenms_memcached
    environment:
      - "TZ=${TZ}"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-memcached
 
  redis:
    image: redis:5.0-alpine
    container_name: librenms_redis
    environment:
      - "TZ=${TZ}"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-redis
 
  msmtpd:
    image: crazymax/msmtpd:latest
    container_name: librenms_msmtpd
ssss    env_file:
      - "./msmtpd.env"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-msmtpd
  
  librenms:
    image: librenms/librenms:latest
    container_name: librenms
    hostname: librenms
    cap_add:
      - NET_ADMIN
      - NET_RAW
    ports:
      - target: 8000
        published: 8000
        protocol: tcp
    depends_on:
      - db
      - memcached
      - msmtpd
    volumes:
      - "./data:/data"
    env_file:
      - "./librenms.env"
    environment:
      - "TZ=${TZ}"
      - "PUID=${PUID}"
      - "PGID=${PGID}"
      - "DB_HOST=db"
      - "DB_NAME=${MYSQL_DATABASE}"
      - "DB_USER=${MYSQL_USER}"
      - "DB_PASSWORD=${MYSQL_PASSWORD}"
      - "DB_TIMEOUT=60"
      - "REDIS_HOST=redis"
      - "REDIS_PORT=6379"
      - "REDIS_DB=0"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms
 
  dispatcher:
    image: librenms/librenms:latest
    container_name: librenms_dispatcher
    hostname: librenms-dispatcher
    cap_add:
      - NET_ADMIN
      - NET_RAW
    depends_on:
      - librenms
      - redis
    volumes:
      - "./data:/data"
    env_file:
      - "./librenms.env"
    environment:
      - "TZ=${TZ}"
      - "PUID=${PUID}"
      - "PGID=${PGID}"
      - "DB_HOST=db"
      - "DB_NAME=${MYSQL_DATABASE}"
      - "DB_USER=${MYSQL_USER}"
      - "DB_PASSWORD=${MYSQL_PASSWORD}"
      - "DB_TIMEOUT=60"
      - "DISPATCHER_NODE_ID=dispatcher1"
      - "REDIS_HOST=redis"
      - "REDIS_PORT=6379"
      - "REDIS_DB=0"
      - "SIDECAR_DISPATCHER=1"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-dispatcher
 
  syslogng:
    image: librenms/librenms:latest
    container_name: librenms_syslogng
    hostname: librenms-syslogng
    cap_add:
      - NET_ADMIN
      - NET_RAW
    depends_on:
      - librenms
    ports:
      - target: 514
        published: 514
        protocol: tcp
      - target: 514
        published: 514
        protocol: udp
    volumes:
      - "./data:/data"
    env_file:
      - "./librenms.env"
    environment:
      - "TZ=${TZ}"
      - "PUID=${PUID}"
      - "PGID=${PGID}"
      - "DB_HOST=db"
      - "DB_NAME=${MYSQL_DATABASE}"
      - "DB_USER=${MYSQL_USER}"
      - "DB_PASSWORD=${MYSQL_PASSWORD}"
      - "DB_TIMEOUT=60"
      - "REDIS_HOST=redis"
      - "REDIS_PORT=6379"
      - "REDIS_DB=0"
      - "SIDECAR_SYSLOGNG=1"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-syslogng
 
 
  snmptrapd:
    image: librenms/librenms:latest
    container_name: librenms_snmptrapd
    hostname: librenms-snmptrapd
    cap_add:
      - NET_ADMIN
      - NET_RAW
    depends_on:
      - librenms
    ports:
      - target: 162
        published: 162
        protocol: tcp
      - target: 162
        published: 162
        protocol: udp
    volumes:
      - "./data:/data"
    env_file:
      - "./librenms.env"
    environment:
      - "TZ=${TZ}"
      - "PUID=${PUID}"
      - "PGID=${PGID}"
      - "DB_HOST=db"
      - "DB_NAME=${MYSQL_DATABASE}"
      - "DB_USER=${MYSQL_USER}"
      - "DB_PASSWORD=${MYSQL_PASSWORD}"
      - "DB_TIMEOUT=60"
      - "SIDECAR_SNMPTRAPD=1"
    restart: unless-stopped
    networks:
      default:
        aliases:
          - librenms-snmptrapd
 
networks:
  default:
    external:
      name: br0

Ainsi que le fichier .env :

TZ=Europe/Paris
PUID=1000
PGID=1000
 
MYSQL_DATABASE=librenms
MYSQL_USER=librenms
MYSQL_PASSWORD=VotreSuperPa$$w0rd

Et le fichier msmtpd.env (pour envoyer des mails) :

SMTP_HOST=XXXX
SMTP_PORT=587
SMTP_TLS=on
SMTP_STARTTLS=on
SMTP_TLS_CHECKCERT=on
SMTP_AUTH=on
SMTP_USER=XXXXX
SMTP_PASSWORD=XXXXX
SMTP_FROM=XXXXX

Rien de fou ici, il s’agit juste des fichiers officiels. J’ai simplement rajouté un pont réseau br0 à la configuration Docker. Cela me permet d’avoir un reverse proxy NGINX devant chacune de mes applications et ainsi d’exposer le minimum de ports.

3. Installation, côté client

3.1 Ajout automatique d’un serveur avec Ansible

Comme je l’évoquais plus haut, l’installation côté client se fait en installant et configurant le service snmpd, et pour ce faire, j’ai encore un script Ansible qui permet de déployer tout cela sans se fouler. Le voici [GIT] :

---
- name: Install snmpd for deb systems
  apt:
    name: "{{ packages }}"
  vars:
    packages:
    - snmp
    - snmpd
    - rsyslog
    state: present
  when: ansible_distribution == "Ubuntu" or ansible_distribution == "Debian"
 
- name: Install snmpd for rpm systems
  yum:
    name: "{{ packages }}"
  vars:
    packages:
    - net-snmp
    - net-snmp-utils
    - rsyslog
    state: present
  when: ansible_distribution == "CentOS" or ansible_distribution == "Fedora"
 
- name: Stop service snmpd, if running
  service:
    name: snmpd
    state: stopped     
 
- template:
    src: snmpd.j2
    dest: /etc/snmp/snmpd.conf
    owner: root
    group: root
    mode: 0600
 
- name: Add snmp user
  lineinfile:
    path: /var/lib/snmp/snmpd.conf
    regexp: '^# '
    insertafter: '^# '
    line: "createUser {{ snmp_user }} SHA {{ snmp_auth }} AES {{ snmp_priv }}"
    state: present
  when: ansible_distribution == "Ubuntu" or ansible_distribution == "Debian"
 
- name: Add snmp user
  lineinfile:
    path: /var/lib/net-snmp/snmpd.conf
    regexp: '^# '
    insertafter: '^# '
    line: "createUser {{ snmp_user }} SHA {{ snmp_auth }} AES {{ snmp_priv }}"
    state: present
  when: ansible_distribution == "CentOS"
 
- name: Start service snmpd, if running
  service:
    name: snmpd
    state: started
 
- template:
    src: remote_rsyslog.conf.j2
    dest: /etc/rsyslog.d/remote.conf
    owner: root
    group: root
    mode: 0644
 
- name: Stop service rsyslog, if running
  service:
    name: rsyslog
    state: restarted
 
- name: Register host with LibreNMS
  uri:
    url: "{{ librenms_api_url }}"
    validate_certs: no
    method: POST
    body:
      hostname: "{{ inventory_hostname }}"
      #hostname: "{{ ansible_hostname }}"
      #description: "{{ ansible_hostname }}"
      version: v3
      authlevel: authPriv
      authname: "{{ snmp_user }}"
      authpass: "{{ snmp_auth }}"
      authalgo: SHA
      cryptopass: "{{ snmp_priv }}"
      cryptoalgo: AES
    body_format: json
    headers:
      Content-Type: "application/json"
      X-Auth-Token: "{{ librenms_token }}"

Ce rôle Ansible va tout d’abord installer les paquets nécessaires, que ce soit sur une distribution type Debian ou CentOS.

Ensuite, il arrête le service snmpd.

Il configure snmpd pour le faire fonctionner avec la version 3 du protocole, en utilisant les bonnes variables référencées dans un fichier global (group_vars/all), ainsi que les identifiants dans le fichier sécurisé vault d’Ansible.

Suite à cela, le service snmpd est relancé.

Le rôle s’occupe également de modifier la configuration de rsyslog afin d’envoyer ses logs vers le serveur de LibreNMS.

Pour valider cette modification, le service adéquat est redémarré.

Enfin, une requête HTTPS est envoyée vers l’API de LibreNMS afin d’enregistrer automatiquement ce nouvel hôte à surveiller.

Pour que cette dernière étape fonctionne, il faut au préalable avoir généré un jeton d’authentification via l’interface web de LibreNMS en cliquant sur l’icône de la molette (en haut à droite), puis API > API Settings.

Si tout a fonctionné, votre nouvelle machine devrait apparaître dans LibreNMS au bout de quelques secondes !

3.2 Ajout manuel d’un équipement

Si vous ne voulez pas utiliser Ansible, ou dans le cas d’équipements pour lesquels nous n’avez pas accès à l’OS, comme un switch, il faudra le faire à la main.

Cela se passe dans Devices > Add Device (Figure 1).

librenms add device-s

Figure 1

Il suffit de remplir les informations demandées, en adéquation avec la configuration de votre switch.

Après avoir installé au moins un équipement, il est possible de scanner des sous-réseaux complets afin de faire de l’ajout en masse. Cela peut donc être très pratique pour ajouter d’un seul coup tous vos équipements réseaux [AUTODISCO].

Pour ce faire, plusieurs possibilités : soit vos équipements utilisent snmp v2c, dans ce cas, il faudra simplement ajouter la variable : LIBRENMS_SNMP_COMMUNITY=VotreCommunauté dans votre fichier docker-compose.yml.

Si vous utilisez la version 3, alors c’est un peu plus compliqué, apparemment, il n’y a pas de variable pour cela…

Il faudra donc modifier le fichier de config.php au sein du conteneur librenms avec la commande suivante :

docker exec -it librenms /bin/bash

Une fois placé dans le conteneur, il faut ajouter les lignes suivantes au fichier /opt/librenms/config.php :

// v3
$config['snmp']['v3'][0]['authlevel'] = 'authPriv';
$config['snmp']['v3'][0]['authname'] = 'my_username';
$config['snmp']['v3'][0]['authpass'] = 'my_password';
$config['snmp']['v3'][0]['authalgo'] = 'SHA';
$config['snmp']['v3'][0]['cryptopass'] = 'my_crypto';
$config['snmp']['v3'][0]['cryptoalgo'] = 'AES';

Remplacez les valeurs ci-dessus par les vôtres, sauvegardez, puis quittez le conteneur (par exemple avec CTRL+D).

Vous pouvez aussi modifier ces valeurs via la Web UI en allant dans Icône de la molette > Global Settings > Poller > SNMP.

Maintenant, que vous ayez suivi la méthode pour la v2c ou la v3 (voire les deux), il est temps de lancer un scan avec la commande suivante :

docker-compose exec librenms lnms scan 192.168.1.0/24 -v

Encore une fois, adaptez la commande ci-dessus avec les bonnes valeurs. Vous pouvez également ajouter plusieurs sous-réseaux les uns à la suite des autres.

Le -v, quant à lui, correspond au mode verbose. Je vous conseille de l’activer afin de voir ce qu’il se passe.

4. Mise en place des alertes

Vos machines sont désormais sous surveillance. C’est bien beau, mais sans alertes, ça ne sert pas à grand-chose ! Voyons donc comment les configurer.

4.1 Importer les règles

Rendez-vous dans Alerts > Alert Rules, puis cliquez sur Create rule from collection. À partir de là, un menu apparaît avec des règles prédéfinies. Choisissez celles qui vous intéressent puis ajoutez-les à votre liste de règles (qui doit être vide pour le moment).

Par exemple, voici, en Figure 2, ce à quoi ressemble une alerte pour le stockage.

librenms regle stockage-s

Figure 2

Si l’espace disque utilisé est supérieur ou égal à 90 %, alors une alerte critique est envoyée après 1 minute. J’ai mis le Max alerts à 1 afin de ne pas être spammé. Mais vous pouvez bien entendu changer ce chiffre, et dans ce cas, faites attention au paramètre Interval.

Chaque règle peut être activée ou désactivée, modifiée pour la rendre plus ou moins spécifique, etc. La gestion des règles est assez flexible et permet de faire à peu près n’importe quoi, facilement et graphiquement !

4.2 Configurer l’acheminement des alertes

Ensuite, pour que vos alertes puissent être acheminées vers vous, il faut configurer un « transport », dans Alerts > Alert transports et Create alert transport.

Comme pour les règles d’alertes, LibreNMS vous prend par la main et vous permet de configurer le transport de votre choix via un menu déroulant listant de très nombreuses méthodes comme les mails, Telegram, Discord, SMS, syslog, etc.

Configurez donc la méthode qui vous convient le mieux !

Une fois que cela est fait, vos alertes devraient être fonctionnelles.

J’aime bien tester le bon fonctionnement de la chose en créant un faux fichier pour remplir un « disque ».

Pour ce faire, je me connecte sur une de mes machines, je vérifie la place restante avec df -h, puis, en admettant qu’il reste 26G, je vais créer un fichier de 25G avec la commande : fallocate -l 25G plop.img.

Si je reçois une alerte, alors c’est tout bon ! N’oubliez pas de supprimer le fichier plop.img et vous devriez recevoir une seconde alerte pour vous indiquer que tout est de retour à la normale.

4.3 Modifier les modèles d’alertes

Un aspect intéressant de LibreNMS est la personnalisation des alertes via des modèles (soit des  « templates » en anglais) que vous pouvez modifier et/ou créer facilement. C’est cet aspect qui m’a fait revenir sur LibreNMS récemment. En effet, j’utilisais Grafana jusque-là, mais ils ont changé leur système d’« alerting » (pour se rapprocher de ce que fait Prometheus), et je trouve que c’est une horreur pour avoir de beaux modèles !

Pour jouer avec les modèles, il faut donc se rendre dans Alerts > Alert templates.

Par exemple, vous pouvez avoir une alerte disque qui ressemble à la Figure 3.

librenms alerte stockage-s

Figure 3

Notez le Alert title et le Reccovery title qui permettent de facilement différencier les nouvelles alertes des alertes résolues. Pour que cela fonctionne, il faudra que votre modèle comprenne la valeur {{ $alert->title }}.

Côté « code », voici à quoi cela ressemble :

<b>{{ $alert->title }}</b>
<b>Rule</b> : {{ $alert->name }}
<b>Device Name</b> : {{ $alert->hostname }}
<b>Severity</b> : {{ $alert->severity }}
@if ($alert->state == 0)
<b>Time elapsed</b> : {{ $alert->elapsed }} @endif
<b>Timestamp</b> : {{ $alert->timestamp }}
 
<b>Server</b> : {{ $alert->sysName }}
@foreach ($alert->faults as $key => $value)
<b>Mount Point</b> : {{ $value['storage_descr'] }}
<b>Percent Utilized</b> : {{ $value['storage_perc'] }}
@endforeach

Malheureusement, j’ai rencontré des problèmes en essayant de formater les messages en Markdown, c’est pourquoi j’utilise désormais du HTML.

Chaque type d’alerte peut être modifié. C’est assez fastidieux, mais une fois le temps pris pour le faire, cela permet d’avoir des alertes claires avec juste ce qu’il faut d’information afin de savoir d’un rapide coup d’œil s’il faut s’en occuper immédiatement ou si cela peut attendre.

5. Fonctionnalités additionnelles

5.1 Les services

Les Services permettent, par exemple, de surveiller l’état d’un site web en envoyant une requête HTTP/HTTPS et en analysant le code HTTP.

Ils permettent aussi de vérifier qu’un serveur de temps NTP est bien synchronisé, de vérifier s’il y a des mises à jour à installer, de vérifier la file d’attente des e-mails à envoyer, etc.

Voyons tout de suite comment ajouter un service via, Services > Add Service (Figure 4).

librenms add service-s

Figure 4

Les parties importantes sont Check Type, ici http. Ensuite le Device, cela correspond à la machine qui va exécuter cette vérification (cela peut donc être une machine autre sur le serveur LibreNMS). Remote Host quant à lui correspond à l’URL du site web que vous voulez surveiller, et enfin les Parameters, dans notre cas les bons paramètres pour surveiller la date d’expiration d’un certificat « HTTPS ».

5.2 Les apps

Les Apps permettent de surveiller à peu près tout et n’importe quoi en plus de ce qui est déjà surveillé par défaut. Elles se basent sur la fonctionnalité snmp extend qui permet de lancer une commande sur une machine et d’en récupérer le retour.

Pour ce qui suit, nous allons prendre l’exemple d’un onduleur branché en USB et déjà configuré via nut (cela fonctionne aussi avec apcups) [ONDU].

Je ne tiens pas à copier/coller dans cet article les scripts déjà fournis par l’équipe de LibreNMS, ni à paraphraser leur guide qui est très bien fait. Je voudrais juste vous donner les grandes lignes du processus.

Il s’agit donc de copier un script qui, dans notre cas, va exécuter la commande upsc pour récupérer des informations sur notre onduleur comme la charge de la batterie, le voltage, la durée restante de batterie, etc.

Ensuite, ce script sera exécuté à intervalles réguliers via le service snmpd. Il faudra bien évidemment que votre script soit exécutable, et qu’il puisse être exécuté avec les droits de l’utilisateur snmp (Debian-snmp sur une distribution Debian). Cela veut dire que dans certains cas, il faudra modifier le fichier /etc/sudoers (avec la commande visudo, pour éviter les catastrophes) en conséquence.

Une fois en place, cela nous donne de « jolis » petits graphiques (Figure 5).

librenms nut graphs-s

Figure 5

Conclusion

Comme nous avons pu le voir, LibreNMS n’a pas grand-chose à envier aux solutions de monitoring plus récentes. Le plus gros « reproche » que nous pourrions lui faire est que ses graphiques ne sont pas très jolis (en 2022).

À part cela, c’est une solution très complète qui permet de monitorer rapidement un parc complet de machines : aussi bien des serveurs que des switchs ou autres appareils pour lesquels nous n’avons pas accès à l’OS. En passant un peu plus de temps sur la configuration, il est assez simple d’obtenir une configuration qui répondra parfaitement à vos besoins avec les bonnes alertes envoyées aux bonnes personnes, et formatées comme vous le souhaitez !

Il reste aussi énormément de fonctionnalités que nous n’avons pas abordées dans cet article, comme la possibilité d’utiliser un agent (check_mk), des intégrations avec différents logiciels (comme oxidized qui sauvegarde les configurations de vos switchs), et j’en passe !

Références

[PROXMOX] D. Gourmel, « Proxmox : vis ma vie d’éleveur de machines de virtuelles », Linux Pratique n°134, novembre - décembre 2022 : https://connect.ed-diamond.com/linux-pratique/lp-134/proxmox-vis-ma-vie-d-eleveur-de-machines-virtuelles

[COMPOSE] Fichier docker-compose.yml officiel de LibreNMS :
https://github.com/librenms/docker/tree/master/examples/compose

[GIT] Fichiers de config Ansible : https://github.com/Nesousx/ansible

[ONDU] LibreNMS Apps : nut : https://docs.librenms.org/Extensions/Applications/#ups-nut

[AUTODISCO] Ajouter automatiquement vos équipements :
https://docs.librenms.org/Extensions/Auto-Discovery/#getting-started



Article rédigé par

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous