Grafana et prometheus

De Justine's wiki
Aller à la navigation Aller à la recherche

Sources, liens

https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config

Présentation

Grafana est un logiciel libre sous licence GNU Affero General Public License Version 32 (anciennement sous licence Apache 2.0 avant avril 2021) qui permet la visualisation de données. Il permet de réaliser des tableaux de bord et des graphiques depuis plusieurs sources dont des bases de données temporelles comme Graphite (en), InfluxDB et OpenTSDB3. 

(Merci Wikipedia)

Prometheus est un logiciel libre de surveillance informatique et générateur d'alertes. Il enregistre des métriques en temps réel dans une base de données de séries temporelles (avec une capacité d'acquisition élevée) en se basant sur le contenu de point d'entrée exposé à l'aide du protocole HTTP. Ces métriques peuvent ensuite être interrogé à l'aide d'un langage de requête simple (PromQL) et peuvent également servir à générer des alertes. Le projet est écrit en Go et est disponible sous licence Apache 2. 

(Merci encore Wikipedia) NB : j'appellerais Prometheus "Prom" pour éviter des longueurs.

J'utilise Grafana et Prometheus dans le but de faire des graphiques et de la métrologie. L'installation se fera sous Docker. Le principe est le suivant :

  • Sur mes machines cibles sont installés un ou plusieurs exporters prometheus, soit des agents. Chaque exporter répond à un port précis, et retourne diverses informations. On a un exporter généraliste (node-exporter), mais on en a aussi pour haproxy, varnish, apache, etc...
  • Prometheus interroge les exporters en http. Par exemple, pour prometheus-node-exporter, il interroge http://ma-machine:9100/metrics
  • Prometheus stocke le résultat dans sa base de données.
  • Grafana interroge Prometheus pour obtenir des données à afficher dans ses dashboards.

Le tout donne ce genre de choses, dont les screenshots rendent toujours bien :

Présentation du fichier docker-compose du projet

Je package le tout dans un fichier Docker-compose <source lang="yaml"> version: '3.3' networks:

   graf:
       external: false
       ipam:
           config:
               - subnet: 172.27.0.0/24

services:

   grafana:
       restart: always
       ports:
           - '3001:3000'
       image: grafana/grafana
       volumes:
         - grafana-data:/var/lib/grafana
         - grafana-conf:/etc/grafana
       networks:
           graf:
               ipv4_address: 172.27.0.10
   prometheus:
       restart: always
       ports:
           - '9090:9090'
       command:
           - "--storage.tsdb.retention.time=1y"
           - "--config.file=/etc/prometheus/prometheus.yml"
       volumes:
           - './prometheus-conf/:/etc/prometheus/'
       image: prom/prometheus
       networks:
           graf:
               ipv4_address: 172.27.0.20
   blackbox-exporter:
       restart: always
       ports:
           - '9115:9115'
       container_name: blackbox_exporter
       dns:
         - 9.9.9.9
         - 8.8.8.8
         - 1.1.1.1
       volumes:
           - ./blackbox:/etc/blackbox_exporter
       image: 'prom/blackbox-exporter:master'
       networks:
           graf:
               ipv4_address: 172.27.0.30

volumes:

 grafana-data:
 grafana-conf:

</source>

Ici, plusieurs choses.

Network

Le network me sert à avoir des configs portables. En effet, les IPs ne changent pas, ce qui permettra par exemple de toujours savoir où trouver prometheus. Sinon, à chaque redémarrage, les IPs vont changer. Le réseau est simple.

Grafana

Grafana n'as pas besoin de grand-chose.

  • restart always : on ne veut pas que notre conteneur s'arrête.
  • ports: Par défaut, Grafana utilise le port 3000. Chez moi il est déjà pris, alors je le mets sur le 3001. C'est sur ce port le 3001 ici) que j'irais chercher mon interface web.
  • image : grafana
  • volumes : le volume grafana-data ira stocker la conf grafana (donc les dashboards créés, principalement). Le volume grafana-conf stockera la configuration de Grafana. Je n'utilise pas des volumes en mode bind, mais des volumes docker (qui sont définis tout en bas du fichier) pour des problèmes de droit.
  • network : son ip

Prometheus

  • le port est ouvert; cela n'est dans l'absolu pas nécessaire, puisque Grafana est dans le même réseau Docker.
  • Les commandes : ces arguments sont ajoutés au lancement de la commande de lancement de Prometheus dans le conteneur. La première fait en sorte que Prom garde ses données pendant 1 an (au lieu de 15 jours normalement); la seconde lui précise le chemin de son fichier de config.
  • Le volume bindé ici nous permettra de modifier à la volée le fichier de config de Prom, prometheus.yml

blackbox_exporter

Il s'agit d'un exporter "autonome"; il va tourner dans son propre conteneur. Son rôle est d'interroger une liste de serveurs web que nous allons configurer afin de renvoyer les temps de connexion, statut SSL, etc.

Mon wiki va bien
  • Les ports n'ont, dans l'absolu, pas besoin d'être ouvert puisque tout est dans le même réseau Docker.
  • dns : il s'agit ici de changer les serveurs DNS que va utiliser mon conteneur. J'utilise ici des résolveurs DNS publics courants afin d'éviter des problèmes avec la conf DNS de mon domaine.
  • Le volume correspond à son dossier de configuration.

Configuration de Prometheus

La documentation de Prom se trouve ici Toute la configuration de Prometheus se fait par un seul fichier, prometheus.yml. Je vais devoir déposer celui-ci dans mon volume prometheus-conf. Pour en récupérer une version standard, je peux lancer à part un conteneur Prom pour aller récupérer /etc/prometheus/prometheus.yml dans le conteneur.

Ma configuration est très proche de la config de base : <source lang="yaml">

  1. my global config

global:

 scrape_interval: 5s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
 evaluation_interval: 5s # Evaluate rules every 15 seconds. The default is every 1 minute.
 # scrape_timeout is set to the global default (10s).
  1. Alertmanager configuration

alerting:

 alertmanagers:
   - static_configs:
       - targets:
         # - alertmanager:9093
  1. Load rules once and periodically evaluate them according to the global 'evaluation_interval'.

rule_files:

 # - "first_rules.yml"
 # - "second_rules.yml"
  1. A scrape configuration containing exactly one endpoint to scrape:
  2. Here it's Prometheus itself.

scrape_configs:

 # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
 - job_name: "prometheus"
   # metrics_path defaults to '/metrics'
   # scheme defaults to 'http'.
   static_configs:
     - targets: ["localhost:9090"]
 - job_name: "node"
   static_configs:
     - targets: ["supervision.squi.fr:9100", "lamp.squi.fr:9100", "gate.squi.fr:9100", "dns1.squi.fr:9100", "exploit.squi.fr:9100", "82.65.78.250:9100"]
 - job_name: "haproxy"
   static_configs:
     - targets: ["gate.squi.fr:8404"]
 - job_name: "bind"
   static_configs:
     - targets: ["dns1.squi.fr:9119", "exploit.squi.fr:9119"]
 - job_name: "blackbox"
   metrics_path: /probe
   scrape_interval: 30s
   scrape_timeout: 20s
   params:
       module: [http_2xx]
   static_configs:
     - targets:
       - https://bookstack.squi.fr/
       - https://chezjustine.space/
       - https://wiki.squi.fr/
       - https://gitea.squi.fr/
       - https://rss.squi.fr
       - https://stats.squi.fr
       - https://supervision.squi.fr
   relabel_configs:
     - source_labels: [__address__]
       target_label: __param_target
     - source_labels: [__param_target]
       target_label: instance
     - target_label: __address__
       replacement: 172.27.0.30:9115

</source>

Nous allons voir les sections importantes (soit, celles que j'ai modifiées).

Scrape interval, evaluation_interval

<source lang="yaml"> global:

 scrape_interval: 5s 
 evaluation_interval: 5s 
 # scrape_timeout is set to the global default (10s).

</source> C'est le délai par défaut auquel Prometheus va aller interroger ses exporters (scrape_interval) et évaluer ce qu'il récupère (evaluation_interval). Par défaut 15 secondes, j'ai descendu la configuration à 5.

scrape_configs, utiliser des exporters

C'est ici que nous allons dire à Prometheus qui il doit aller interroger, et sur quels ports. Pour chaque type d'exporter, je vais définir un "job" différent. Ainsi, tout est bien rangé. Prometheus se fiche en réalité un peu des données qu'il reçoit; il va interroger une machine, récupérer des données, et les ranger dans sa base.

Le schéma général d'un job est ici: <source lang="yaml">

 - job_name: "un nom que je choisis"
   static_configs: #Ici, je vais donner des hotes et éventuellement des labels (cf la doc)
     - targets: ["unemachine:port", "etc:etc"] #mes hotes

</source>

En général, un exporter a un nom comme prometheus-*-exporter.

Les repos Debian en ont un certain nombre : <source> root@machin:/opt/grafana# sudo apt install prometheus- prometheus-alertmanager prometheus-node-exporter prometheus-apache-exporter prometheus-node-exporter-collectors prometheus-bind-exporter prometheus-pgbouncer-exporter prometheus-bird-exporter prometheus-postfix-exporter prometheus-blackbox-exporter prometheus-postgres-exporter prometheus-elasticsearch-exporter prometheus-process-exporter prometheus-exporter-exporter prometheus-pushgateway prometheus-hacluster-exporter prometheus-redis-exporter prometheus-haproxy-exporter prometheus-smokeping-prober prometheus-homeplug-exporter prometheus-snmp-exporter prometheus-ipmi-exporter prometheus-sql-exporter prometheus-libvirt-exporter prometheus-squid-exporter prometheus-mailexporter prometheus-tplink-plug-exporter prometheus-mongodb-exporter prometheus-trafficserver-exporter prometheus-mqtt-exporter prometheus-varnish-exporter prometheus-mysqld-exporter prometheus-xmpp-alerts prometheus-nginx-exporter </source>

Une fois installé, il a un service SystemD à son nom que l'on peut gérer.

job prometheus

<source lang="yaml">

 - job_name: "prometheus"
   # metrics_path defaults to '/metrics'
   # scheme defaults to 'http'.
   static_configs:
     - targets: ["localhost:9090"]

</source> Ce job est présent par défaut. Prometheus se monitore lui-même.

Utiliser node_exporter

<source lang="yaml">

 - job_name: "node"
   static_configs:
     - targets: ["machine1:9100", "machine2:9100", "machine3:9100"]

</source>

Ici, il s'agit du job qui va interroger node_exporter. Celui-ci a pour rôle de remonter des informations sur le système au sens large : CPU, RAM, disques, etc... Il est très poussé et suffit à bien des choses.

Le job configuré ci-dessus va donc interroger mes machines sur le port 9100.

Sur chacune de mes machines, j'ai juste à installer le paque prometheus-node-exporter présent dans les repos Debian. Ensuite, il faut simplement s'assurer que Prometheus a accès au port 9100 des machines.

Utiliser haproxy_exporter

<source lang="yaml">

 - job_name: "haproxy"
   static_configs:
     - targets: ["haproxy.squi.fr:8404"]

</source>

Cet exporter pour haproxy permet de renvoyer pas mal d'informations intéressantes : codes de réponses http de mon HAProxy, état des backends, etc. Il peut être installé sur le serveur haproxy avec

apt install prometheus-haproxy-exporter

Le port 8404, qui est en réalité celui du frontend stats de HAProxy, doit répondre. Une fois le package installé, il y'a un peu de conf à faire au niveau d'HAProxy. En effet, le frontend stats doit ressembler à ça: <source> frontend stats bind *:8404 option http-use-htx http-request use-service prometheus-exporter if { path /metrics } stats enable stats uri /stats stats refresh 10s </source>

On voit ici que le frontend de statistiques d'HAProxy est configuré pour utiliser l'exporter si on interroge l'URI /metrics.

Vérifier avec haproxy -c -V -f /etc/haproxy/haproxy.cfg , puis reload d'HAProxy.

Utiliser bind_exporter

Cet exporter pour bind envoie lui aussi nombre d'informations utiles sur Bind9 : requête, réponses, uptime, etc.

<source>

 - job_name: "bind"
   static_configs:
     - targets: ["dns1:9119", "dns2:9119"]

</source>

Celui-ci s'installe avec apt install prometheus-bind-exporter, sur le/les serveurs dns, et répond sur le port 9119. Une fois celui-ci installé, il faut faire un peu de conf sur le serveur Bind9. Ajouter ce bloc tout en bas de /etc/bind/named.conf.options, en dehors du bloc "options" : <source> statistics-channels {

   inet 127.0.0.1 port 8053 allow { 127.0.0.1; };

}; </source>

Puis reload de bind9.

Utiliser blackbox_exporter

Cet exporter est donc ici sous la forme d'un conteneur qui va aller interroger des sites web et renvoyer des données.

<source lang="yaml">

- job_name: "blackbox"
   metrics_path: /probe
   scrape_interval: 30s
   scrape_timeout: 20s
   params:
       module: [http_2xx]
   static_configs:
     - targets:
       - https://google.com/
       - https://facebook.com/
   relabel_configs:
     - source_labels: [__address__]
       target_label: __param_target
     - source_labels: [__param_target]
       target_label: instance
     - target_label: __address__
       replacement: 172.27.0.30:9115

</source>

Ici, la section targets définit quels sont les sites qui seront interrogés. Un peu plus bas, la section replacement définit où se trouve l'exporter blackbox : il n'est en effet pas sur le même conteneur que Prometheus, il faut donc bien le lui préciser.

Sa configuration se trouve dans le dossier de volume "blackbox", sous le nom config.yml. J'ai repris la conf par défaut:

<source lang="yaml"> modules:

 http_2xx:
   prober: http
 http_post_2xx:
   prober: http
   http:
     method: POST
 tcp_connect:
   prober: tcp
 pop3s_banner:
   prober: tcp
   tcp:
     query_response:
     - expect: "^+OK"
     tls: true
     tls_config:
       insecure_skip_verify: false
 grpc:
   prober: grpc
   grpc:
     tls: true
     preferred_ip_protocol: "ip4"
 grpc_plain:
   prober: grpc
   grpc:
     tls: false
     service: "service1"
 ssh_banner:
   prober: tcp
   tcp:
     query_response:
     - expect: "^SSH-2.0-"
     - send: "SSH-2.0-blackbox-ssh-check"
 irc_banner:
   prober: tcp
   tcp:
     query_response:
     - send: "NICK prober"
     - send: "USER prober prober prober :prober"
     - expect: "PING :([^ ]+)"
       send: "PONG ${1}"
     - expect: "^:[^ ]+ 001"
 icmp:
   prober: icmp

</source>

Le reste de la conf est assez explicite.

Lancer les conteneurs

C'en est fini des configurations dans des fichiers. Je peux lancer mes conteneurs:

docker-compose up -d

Configurer Grafana

Une fois mes conteneurs montés, je vais pouvoir configurer Grafana via sa console Web. Je me connecte donc avec les identifiants par défaut: admin : admin Dans la foulée, on me propose de changer, ce que je fait.

Ajouter Prometheus comme source de données

Pour se faire, je clique sur l'icône de roue dentée, section "Data Sources", puis "add data source".

Je clique ensuite sur Prometheus > Select

Je rentre ensuite l'adresse de prometheus, donc avec son IP qui a été définie dans docker-compose.

Puis tout en bas de la page, "Save and test". Grafana doit confirmer que c'est bon.

Ajouter des dashboards

On peut créer des dashboards soi-même, mais c'est compliqué. Heureusement, un tas de dashboards fait par la communauté se trouvent sur https://grafana.com/grafana/dashboards/. On peut chercher des dashboards à intégrer ici.

De mon côté, je fais un dashboard par type d'exporter. Je ne montrerais la procédure que pour le dashboard node-exporter, mais le principe est valable pour les autres.

  • Cliquer sur un dashboard qui nous plaît, puis à droite, en dessous de "get this dashboard", copier l'ID.

Ensuite, on va l'importer sur Grafana.

Cliquer sur le + dans la barre de gauche, section "import" :

Rentrer l'ID du dashboard, puis cliquer sur Load.

Dans la fenêtre qui s'ouvre, donner un nom, et choisir notre serveur Prometheus comme source de données, puis Import.

Et voilà. Le dashboard est dispo dans la section home.