Table of Contents
Monitoring avec InfluxDB
Parmi les nombreuses solutions de monitoring il existe de nombreux exemples sur une stack qui utilisent:
- des collecteurs permettant de collecter des données systèmes (CPU, mémoire, disque, I/O, …): collectd, telegraf
- une base de données (une TSDB1)) pour stocker les métriques et événements: influxdb
- une plate-forme graphique pour la mise en forme des données métriques et alerter: graphite, grafana.
Cet article présente comment les installer et les configurer, et bien entendu les lier ensemble pour obtenir un tableau de bord clair et précis de monitoring.
Lorsque SELinux est activé il faut autoriser les scripts et modules HTTPD à se connecter au réseau (HTTPD Service httpd_can_network_connect) :
setsebool -P httpd_can_network_connect 1
Il faut également accorder au processus HTTPD l'accès aux fichiers ainsi qu'aux fichiers statiques du site avec la commande:
chcon -v -R --type=httpd_sys_content_t /chemin/fichiers/statiques/du/site/
InfluxDB
InfluxDB est une base de données open source écrit en Go spécifiquement pour gérer des séries de données chronologiques. Ses points forts sont la haute disponibilité et la haute performance. C’est InfluxDB qui va sauvegarder les données des colleceurs pour ensuite être utilisées par Grafana.
Installation de InfluxDB
Ajouter le repo YUM d’InfluxDB:
cat > /etc/yum.repos.d/influxdb.repo<<'EOF' [influxdb] name = InfluxDB Repository - RHEL \$releasever baseurl = https://repos.influxdata.com/rhel/$releasever/$basearch/stable enabled = 1 gpgcheck = 0 gpgkey = https://repos.influxdata.com/influxdb.key EOF
Installer le package :
dnf makecache dnf install influxdb -y
Démarrer le service :
systemctl start influxd systemctl enable influxd
Ouvrir le port 8086 dans le pare-feu:
firewall-cmd --add-port=8086/tcp --permanent firewall-cmd --reload
Configuration de InfluxDB
Créer une base de données pour pouvoir y pousser les données remontées par les collecteurs:
influx -execute "CREATE DATABASE influx_db" influx -execute "CREATE DATABASE collectd_db"
Créer l’utilisateur influx_user:
influx -execute “CREATE USER influx_user WITH PASSWORD 'influx-password'” influx -execute “GRANT ALL ON influx_db TO influx_user influx -execute “GRANT ALL ON collectd_db TO influx_user
Il est possible de créer une retention policy pour déterminer la durée de conservation des données :
influx -execute 'CREATE RETENTION POLICY one_year ON influx_db DURATION 365d REPLICATION 3'
Collectd
Collectd est un service Linux qui permet de collecter, transférer et sauvegarder des données de performance concernant un ordinateur et son équipement réseau.
Installation de collectd
Son installation est simple :
dnf install collectd -y
Il est nécessaire d’activer le plugin « network » puisqu’il permettra la communication entre collectd et influxdb. Dans le fichier /etc/collectd/collectd.conf décommenter la ligne LoadPlugin network et insérer les lignes suivantes pour indiquer que InfluxDB est sur la même machine et écoute sur le port 25826 :
<Plugin network> Server "127.0.0.1" "25826" </Plugin>
De la même manière on peut modifier le fichier /etc/collectd/collectd.conf pour activer ou désactiver les plugins souhaités . Pour cela il suffit de commenter ou décommenter les lignes « LoadPlugin xxxxx » (par exemple nginx, cpu, df, disk, memory, mysql, memcached).
Il faut ensuite démarrer collectd pour prendre en compte ces modifications :
systemctl start collectd systemctl enable collectd
Activer le module collectd dans /etc/influxdb/influxdb.conf:
[[collectd]] enabled = true bind-address = "127.0.0.1:25826" # db files, or specifying a single db file. typesdb = "/usr/share/collectd" # security-level = "none"
Redémarrer le service influxd:
systemctl restart influxd
On peut tester la remontée avec la commande suivante:
curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=collectd_db" --data-urlencode "q=SELECT value FROM disk_read"
Ouvrir le port 25826 dans le pare-feu:
firewall-cmd --add-port=25826/tcp --permanent firewall-cmd --reload
Telegraf
Telegraf est un agent de récupération de métriques. Cet agent sait récupérer des métriques exposées au format Prometheus et propose 2 modes de récupération des métriques, via :
- push: la métrique est poussée dans Telegraf par le composant qui l’expose
- pull: Telegraf récupère la métrique en interrogeant le composant qui l’expose (le mode le plus utilisé)
Les métriques sont insérées au fil de l’eau dans InfluxDB.
Installation de Telegraf
Ajouter le repo YUM officiel de Telegraf:
cat > /etc/yum.repos.d/influxdb.repo<<'EOF' [influxdb] name = InfluxDB Repository - RHEL \$releasever baseurl = https://repos.influxdata.com/rhel/$releasever/$basearch/stable enabled = 1 gpgcheck = 0 gpgkey = https://repos.influxdata.com/influxdb.key EOF
Installer le package :
dnf makecache dnf install telegraf net-snmp net-snmp-libs net-snmp-utils -y
Configurer le backend, pour utiliser le plugin output InfluxDB dans /etc/telegraf/telegraf.conf:
[[outputs.influxdb]] urls = ["http://localhost:8086"] database = "influx_db" username = "influx_user" password = "influx_password"
Pour finir, redémarrer le service pour prendre en compte la configuration :
systemctl start telegraf systemctl enable telegraf
Configuration de Telegraf
Telegraf fonctionne sous forme de plugin à activer pour récupérer les métriques. L’écosystème de plugins est riche : il y a des plugins pour monitorer nginx, cassandra, haproxy, postgresql. Dans l’ensemble, les plugins sont simples à configurer.
Par exemple on va configurer un plugin pour dire à Telegraf de collecter les données SNMP sur un commutateur:
cat > /etc/telegraf/telegraf.d/sf033-a5500-013sns2.conf<<'EOF'
[[inputs.snmp]]
agents = [ "xx.xxx.xxx.xx" ]
version = 2
community = "lanread"
interval = "20s"
timeout = "10s"
retries = 3
[[inputs.snmp.field]]
name = "hostname"
oid = "RFC1213-MIB::sysName.0"
is_tag = true
[[inputs.snmp.field]]
name = "uptime"
oid = "DISMAN-EXPRESSION-MIB::sysUpTimeInstance"
[[inputs.snmp.field]]
name = "hh3cEntityExtCpuUsage"
oid = ".1.3.6.1.4.1.25506.2.6.1.1.1.1.6.212"
[[inputs.snmp.field]]
name = "hh3cEntityExtMemUsage"
oid = ".1.3.6.1.4.1.25506.2.6.1.1.1.1.8.212"
[[inputs.snmp.field]]
name = "hh3cEntityExtTemperature"
oid = ".1.3.6.1.4.1.25506.2.6.1.1.1.1.12.212"
# IF-MIB::ifTable contains counters on input and output traffic as well as errors and discards.
[[inputs.snmp.table]]
name = "switch"
inherit_tags = [ "hostname" ]
oid = "IF-MIB::ifTable"
# Interface tag - used to identify interface in metrics database
[[inputs.snmp.table.field]]
name = "ifDescr"
oid = "IF-MIB::ifDescr"
is_tag = true
# IF-MIB::ifXTable contains newer High Capacity (HC) counters that do not overflow as fast for a few of the ifTable counters
[[inputs.snmp.table]]
name = "switch"
inherit_tags = [ "hostname" ]
oid = "IF-MIB::ifXTable"
# Interface tag - used to identify interface in metrics database
[[inputs.snmp.table.field]]
name = "ifDescr"
oid = "IF-MIB::ifDescr"
is_tag = true
# EtherLike-MIB::dot3StatsTable contains detailed ethernet-level information about what kind of errors have been logged on an interface (such as FCS error, frame too long, etc)
[[inputs.snmp.table]]Fmib
name = "switch"
inherit_tags = [ "hostname" ]
oid = "EtherLike-MIB::dot3StatsTable"
# Interface tag - used to identify interface in metrics database
[[inputs.snmp.table.field]]
name = "ifDescr"
oid = "IF-MIB::ifDescr"
is_tag = true
[[inputs.snmp.table]]
oid = "IF-MIB::ifTable"
name = "switch"
inherit_tags = ["hostname"]
index_as_tag = true
EOF
Pour déterminer l'OID de la charge du processeur, de l'utilisation de la mémoire et de la température, dans le cas d'un stack composé de plusieurs commutateurs il faut récupérer les indexes identifiés par Board dans la table des description , en utilisant la commande:
snmpwalk -v2c -clanread xx.xxx.xxx.xx SNMPv2-SMI::mib-2.47.1.1.1.1.7 | grep Board
SNMPv2-SMI::mib-2.47.1.1.1.1.7.212 = STRING: "Board"
SNMPv2-SMI::mib-2.47.1.1.1.1.7.232 = STRING: "Board"
Dans l'exemple étudié les OID sont donc:
- hh3cEntityExtCpuUsage: .1.3.6.1.4.1.25506.2.6.1.1.1.1.6.212 et .1.3.6.1.4.1.25506.2.6.1.1.1.1.6.232
- hh3cEntityExtMemUsage: .1.3.6.1.4.1.25506.2.6.1.1.1.1.8.212 et .1.3.6.1.4.1.25506.2.6.1.1.1.1.8.232
- hh3cEntityExtTemperature: .1.3.6.1.4.1.25506.2.6.1.1.1.1.12.212 et .1.3.6.1.4.1.25506.2.6.1.1.1.1.12.232
À la suite de l'exécution de la première commande, une liste d'OID sera affichée, ceux dans lesquels une valeur supérieure à 0 signifie une charge CPU. Si les commutateurs sont empilés, l'OID avec une valeur supérieure à zéro sera supérieur à un. La deuxième équipe se penche sur la description, la nôtre sera “Board”.
Implanter la MIB DISMAN-EXPRESSION-MIB dans le répertoire /usr/share/snmp/mibs/:
wget https://raw.githubusercontent.com/hardaker/net-snmp/master/mibs/DISMAN-EXPRESSION-MIB.txt -P /usr/share/snmp/mibs/
Utiliser la commande suivante pour tester la configuration:
telegraf --test --config /etc/telegraf/telegraf.d/sf033-a5500-013sns2.conf
L'agent doit retourner des données du genre:
> interface,agent_host=xx.xxx.xxx.xx,dot3StatsIndex=17,host=localhost.localdomain,hostname=Sf033_A5500_013SNS2,ifDescr=GigabitEthernet1/0/17 dot3StatsAlignmentErrors=0i,dot3StatsCarrierSenseErrors=0i,dot3StatsDeferredTransmissions=0i,dot3StatsDuplexStatus=3i,dot3StatsEtherChipSet=".0.0",dot3StatsExcessiveCollisions=0i,dot3StatsFCSErrors=0i,dot3StatsFrameTooLongs=0i,dot3StatsInternalMacReceiveErrors=0i,dot3StatsInternalMacTransmitErrors=0i,dot3StatsLateCollisions=0i,dot3StatsMultipleCollisionFrames=0i,dot3StatsRateControlAbility=2i,dot3StatsRateControlStatus=3i,dot3StatsSQETestErrors=0i,dot3StatsSingleCollisionFrames=0i,dot3StatsSymbolErrors=0i 1676468198000000000
Graphite
Graphite est un logiciel de surveillance capable de restituer en quasi temps réel l’état de systèmes IT sous forme de graphiques. Son domaine d’activité est double : le stockage de données chronologiques de performances techniques issues des serveurs d'une part, la visualisation graphique (sous forme de courbes temporelles) des indicateurs de performance que traduisent ces données d'autre part. Pour fonctionner, le logiciel se base sur trois composantes principales :
- Carbon cache: le daemon réseau qui se charge de récupérer les métriques
- Carbon Whisper: la base de données qui stocke les métriques
- Graphite Web: l’application web qui gère le rendu graphique des métriques.
Installation de Graphite
Installer les prérequis pour construire les paquets:
dnf groupinstall "Development Tools" dnf install python39 dnf install libffi-devel python3-devel python3.6 -m pip install --upgrade pip
Installer whisper, carbon et graphite-web avec pip:
pip3 install --upgrade --force-reinstall --no-binary=:all: https://github.com/graphite-project/whisper/tarball/master pip3 install --force-reinstall --no-cache-dir --no-binary=:all: https://github.com/graphite-project/carbon/tarball/mastern -v "urllib3==1.24" -v "idna==2.7" pip3 install --upgrade --force-reinstall --no-binary=:all: https://github.com/graphite-project/graphite-web/tarball/master
Mettre en place les fichiers de configuration
pushd /opt/graphite/conf cp storage-schemas.conf.example storage-schemas.conf cp carbon.conf.example carbon.conf
Créer les fichiers de service:
cat > /etc/systemd/system/graphite-web.socket<<'EOF' [Unit] Description=graphite-web socket [Socket] ListenStream=/run/graphite-api.sock ListenStream=127.0.0.1:8080 [Install] WantedBy=sockets.target EOF
cat > /etc/systemd/system/graphite-web.service<<'EOF' [Unit] Description=graphite-web service Requires=graphite-web.socket [Service] Environment=PYTHONPATH=/opt/graphite/webapp ExecStart=gunicorn wsgi --pythonpath=/opt/graphite/webapp/graphite --bind 127.0.0.1:8080 Restart=on-failure User=root Group=root ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target EOF
Il faut modifier la valeur SECRET_KEY par défaut dans le fichier /etc/graphite/local_settings.py utilisé par graphite-web :
SECRET_KEY = 'MY_SECRET' # entrez votre propre clé secrète
Sinon, on aura une erreur lors du démarrage du service de l'application graphite-web
Mettre à jour la configuration de Nginx:
upstream graphite {
server 127.0.0.1:8080 fail_timeout=0;
}
server {
listen 80;
server_name sonde;
root /opt/graphite/webapp;
access_log /var/log/nginx/graphite.access.log;
error_log /var/log/nginx/graphite.error.log;
location = /favicon.ico {
return 204;
}
# serve static content from the "content" directory
location /static {
alias /opt/graphite/webapp/content;
expires max;
On peut ensuite démarrer graphite-web pour prendre en compte ces modifications :
systemctl start graphite-web systemctl enable graphite-web
Grafana
Grafana est un outil supervision, permettant de s’intégrer à une TSDB, ici InfluxDB. Grafana expose dans des dashboards les métriques brutes ou agrégées provenant d’InfluxDB et permet de définir de manière honteusement simple des seuils d’alertes et les actions associées. Il est simple à utiliser, permet l’actualisation en temps réel ainsi que le déplacement dans le temps pour visualiser ses informations par dates (hier, aujourd’hui, les 6 dernières heures, etc).
Installation de Grafana
Ajouter le repo YUM officiel de Grafana:
cat > /etc/yum.repos.d/grafana.repo<<'EOF' [grafana] name=grafana baseurl=https://packages.grafana.com/oss/rpm repo_gpgcheck=1 enabled=1 gpgcheck=1 gpgkey=https://packages.grafana.com/gpg.key sslverify=1 sslcacert=/etc/pki/tls/certs/ca-bundle.crt EOF
Installer le package :
dnf makecache dnf install grafana -y
Démarrer le service :
systemctl daemon-reload systemctl start grafana-server systemctl enable grafana-server
Ouvrir le port 3000 dans le pare feu:
firewall-cmd --add-port=3000/tcp --permanent firewall-cmd --reload
Configuration de Grafana
La première étape dans Grafana est d’ajouter la source de donnée (InfluxDB). Aller dans “Datasource” puis “Add Datasource” et ajouter la base Influxdb.
- Database: influxdb * Username: influxuser
- Password: influx-password
Ensuite pour créer les dashboards, on peut récupérer des dashboards de la communauté Grafana ou créer des dashboards.
Par exemple pour mettre en place un tableau de bord simple montrant le débit des interfaces:
Choisir le plugin d'affichage dans option panel, par exemple Gauge pour afficher les statistiques sous forme de jauges.
Pour installer des plugins packagés, une fois que l'archive contenant les actifs du plug-in est téléchargé, on peut l'installer en extrayant l'archive dans le répertoire de plug-in:
unzip mon-plugin-0.2.0.zip -d YOUR_PLUGIN_DIR/mon-plugin
Le chemin d'accès au répertoire du plugin est défini dans le fichier de configuration /etc/grafana/grafana.ini:
# Directory where grafana will automatically scan and look for plugins
;plugins = /var/lib/grafana/plugins
Il est possible d'installer des plugins avec Grafana CLI (Toutes les commandes répertoriées s'appliquent aux référentiels et répertoires par défaut de Grafana, on peut remplacer les valeurs par défaut avec les options globales):
- Lister les plugins disponibles: grafana-cli plugins list-remote
- Lister les plugins installés: grafana-cli plugins ls
- Installer la dernière version d'un plugin: grafana-cli plugins install <plugin-id>
- Installer une version spécifique d'un plugin: grafana-cli plugins install <plugin-id> <version>
- Mettre à jour un plugin: grafana-cli plugins update <plugin-id>
- Mettre à jour tous les plugins: grafana-cli plugins update-all
- Supprimer un plugin: grafana-cli plugins remove <plugin-id>
Définir la requête (onglet Query) comme suit:
| A | (InfluxDB) | |||||
|---|---|---|---|---|---|---|
| FROM | autogen | interface | WHERE | hostname | = | Sf033_A5500_013SNS2 |
| SELECT | field(ifHCOutOctets) | mean() | derivative(10s) | math(/100) | alias(output) |
|
| GROUP BY | time($__interval) | tag(ifDescr) | fill(null) | |||
| Time Zone | (optional) | ORDER BY TIME | ascending | |||
| Limit | (optional) | SLIMIT | (optional) | |||
| FORMAT AS | Time series | ALIAS | $tag_ifDescr $col | |||
Les points importants à noter sont :
- Utilisation des champs ifHCInOctets/ifHCOutOctets comptent la même chose que les compteurs ifInOctets/ifOutOctets mais ils sont de type counter64 (compteur sur 64 bits) alors que les premiers sont de type counter32 (compteur sur 32 bits). Passer les compteurs en 64 bits est devenu nécessaire à cause des interfaces haut débit (10Gbps et plus) car à ce débit avec un compteur sur 32 bits on a vite fait de faire “faire un tour” au compteur d'octets et ça devient donc difficile de mesurer le débit de manière fiable. Le ifInOctets/ifOutOctets est gardé pour des raisons de compatibilité avec les applications qui ne géreraient pas les variables de type counter64. Lorsqu'on utilise ces compteurs il faut utiliser un algorithme de transformation dans le bloc SELECT (ici derivative(10s))
- Utilisation de derivative(10s). Les données sous-jacentes sont stockées sous la forme d'un compteur qui s'incrémente tous les 8 bits reçus. Ce n'est pas particulièrement utile en soi. En utilisant derivative(), combiné avec math(8), on peut calculer les bits par seconde.
- le nom d'hôte de commutateur est Sf033_A5500_013SNS2
- l'alias (output) affecté au champs permet de référencé celui-ci avec la variable $col dans le paramètre ALIAS
- Regroupement par heure et par balise (ifDescr) - cela divise les données en lignes distinctes par interface.
- Le paramètre ALIAS contrôle les étiquettes attribuées à chaque série. Dans ce cas, il apparaît comme quelque chose comme TenGigabitEthernet 34/0/1 Output.
