Prometheus est un logiciel de supervision open-source créé par SoundCloud. En 2013, SoundCloud a décidé d'utiliser Prometheus pour ses infrastructures de Production et a publié la version 1.0 en Juillet 2016.

Prometheus, écrit en GO, s'impose depuis comme la solution de référence pour superviser une infrastructure de type Cloud, SaaS/Openstack, OKD, K8S.

Plusieurs autres solutions de supervision sont disponibles sur le marché :

  • Zabbix;
  • Nagios;
  • Centreon;
  • Sensu;
  • InfluxData.

Chaque solution offre ses avantages et ses inconvénients. Prometheus est fourni par défaut comme outil de supervision pour OKD et K8S.

Dans les éléments qui vont particulièrement nous intéresser, nous retiendrons les briques suivantes :

  • Prometheus server : c’est le moteur permettant de stocker les métriques collectées ;
  • Jobs exporters : il s’agit d’agents sur lesquels Prometheus viendra collecter les différentes métriques ;
  • Web UI : restitution des métriques à l’utilisateur ;
  • Alertmanager : gestionnaire d’envoi des alertes aux utilisateurs.

Prometheus collecte les données en provenance des clients nommés “Exporters” installés sur les instances distantes. Il interroge à intervalle régulier ces agents pour récupérer les données.

Le “back-end” de Prometheus intègre sa propre base de données de type “Time Series” similaire à OpenTSDB.

Par défaut, le stockage des métriques s'effectue sur les disques locaux du serveur ce qui rend la scalabilité et la durabilité du stockage complexes et ne le rend pas résilient à la panne puisque le stockage n'est pas distribué.

Pour un environnement de production, il sera donc nécessaire d'utiliser un système de fichier distribué et résilient comme du “glusterFS” ou un système de stockage distant. En fonction du type de stockage distant choisi, seule l'écriture ou lecture / écriture est possible.

La durée de rétention est de 15 jours lors de l'installation du serveur Prometheus. Il est possible d'augmenter la rétention en fonction de la taille de stockage disponible.

Il embarque un puissant langage de requêtage nommé PromQL qui permet :

  • Filtrage des indicateurs par labels (inclusion, exclusion, expressions rationnelles);
  • Génération de vecteurs (plusieurs valeurs d'un indicateur sur une fenêtre temporelle par exemple) sur lesquels il est possible d'appliquer des fonctions et opérateurs d'agrégation (min, max, moyenne glissante, somme …).

Le résultat de chaque requête peut être visualisé sous forme de graphe, tableau ou être mis à disposition de systèmes externes via l'API HTTP.

Chaque résultat est généré sous forme d'un des 4 types suivants :

  • String : Chaîne de caractères;
  • Numérique : Un nombre décimal;
  • Un vecteur instantané : un ensemble de séries temporelles contenant un seul échantillon pour chaque série, toutes partageant le même horodatage;
  • Un ensemble de vecteurs : un ensemble de séries temporelles contenant une plage de points pour chaque série.

Voici quelques exemples de requêtes :

http_requests_total
http_requests_total{job="apiserver", handler="/api/comments"}
http_requests_total{status!~"4.."}
sum(rate(http_requests_total[5m])) by (job)
topk(3, sum(rate(instance_cpu_time_ns[5m])) by (app, proc))

Prometheus utilise le protocole HTTP et nécessite l'instrumentation des applications en utilisant les librairies clientes disponibles pour différents langages.

Il existe différents Exporter :

  • Des Third-party Exporters, permettant de récupérer des métriques de tout type. L'un des Exporters important est le System Exporter permettant de récupérer toutes les métriques systèmes;
  • Des Blackbox Exporters qui permettent de récupérer des métriques à travers différents protocoles;
  • D'autres outils comme Telegraf permettant d'exposer des données à Prometheus;
  • Créer ses propres Exporters si ceux fournis par défaut ne correspondent pas aux besoins.

Par défaut, Prometheus fonctionne en mode Pull, c'est à dire que le serveur interroge à intervalle régulier les instances clientes sur lesquelles les Exporters sont installés.

Il est possible, quand cela s'avère nécessaire de fonctionner en mode Push en utilisant le projet Prometheus Push Gateway. Le seul cas où ce module aurait un intérêt serait pour la supervision de jobs asynchrones. Ces jobs pourraient envoyer des données au Prometheus Server.

Pour superviser une infrastructure complexe qui comporte plusieurs niveaux d'isolations, le mode Pull devient problématique. Au lieu d'utiliser le mode Push qui vient à l'esprit naturellement, Prometheus fournit un proxy permettant de conserver le modèle Pull, et de superviser tous les systèmes derrières le(s) Firewall(s).

Le Proxy est décomposé en deux parties :

  • Le proxy qui s'exécute sur la même zone que le serveur ;
  • L'agent qui s'exécute derrière le firewall et gère les requêtes en provenance du Proxy.

L'agent peut s'exécuter :

  • Comme standalone serveur ;
  • Embarqué dans un autre serveur ;
  • Comme simple Agent Java.

Un proxy peut gérer un ou plusieurs agents.

Prometheus peut se connecter à un module nommé Alertmanager qui est capable de transmettre les alarmes à différents types de média (Mail, PagerDuty, etc…). Le module Alertmanager possède les fonctionnalités suivantes :

  • Grouper les alertes : une seule notification, regroupant toutes les alertes des N dernières secondes / minutes, est envoyée ;
  • Suppression des notifications : les alertes relatives à une conséquence ne sont pas envoyées si l'alerte concernant la cause racine a déjà été envoyée ;
  • Rendre muettes les alertes : ne pas envoyer la même alerte pendant une période déterminée ;
  • Haute disponibilité : Alertmanager supporte la configuration en mode Cluster permettant la haute disponibilité.

L'ensemble de l'alerting est configurable par les fichiers de configuration.

Prometheus fournit par défaut une interface Web qui permet d'effectuer des requêtes pour voir les données présentes en base, mais cette interface n'est absolument pas pratique pour exploiter et superviser l'infrastructure.

Grafana est un logiciel Open Source pour la visualisation et la supervision d'une infrastructure. Ce logiciel propose une connexion native à Prometheus et propose une liste de dashboards pré-générés pour récupérer les informations en provenance de Prometheus.

Pour le déploiement de notre plateforme Prometheus/Grafana nous allons utiliser les roles ansible fournis par la communauté.

AlerteManager est dans notre cas optionnel.

Depuis la version 4.3.2 de grafana, l'alerting est native au produit et permet de gèrer plusieurs canaux de notifications.

Le déploiement de la solution sera réalisé avec les rôles ansible officiel.

Assurez-vous que les flux “ssh” sont bien ouverts entre le serveur de déploiement et la plateforme Prometheus/Grafana ainsi que les nœuds.

1 serveur deploy :

  • OS : Debian 10
  • Ansible >= 2.7
  • Git
  • Gestionnaire de package pip
  • Package “jmespath”

1 serveur avec Prometheus / Grafana / Prometheus-node-exporter / Alertemanager

1 ou Plusieurs serveur “Node” (Serveur où nous allons récupérer les métriques)

Déploiement des packages sous debian pour le bon fonctionnement des roles ansible.

root@deploy:~# apt install curl wget ansible git python3-pip
root@deploy:~# pip install jmespath

Depuis le serveur de déploiement, créer l'arborescence suivantes :

Dans le dossier “ansible-prometheus”

root@deploy:~$ ansible-prometheus
      - roles/
      - inventory/
                 - hosts
      - ansible.cfg
      - site.yml 

Dans le dossier roles, nous allons récupérer les roles ansible pour prometheus et prometheus-node-exporter:

root@deploy:~$ cd roles
root@deploy:~$ git clone https://github.com/cloudalchemy/ansible-prometheus.git prometheus
root@deploy:~$ cd prometheus
root@deploy:~$ git checkout -b 4.0.0
root@deploy:~$ cd ..
root@deploy:~$ git clone https://github.com/cloudalchemy/ansible-node-exporter.git node-exporter
root@deploy:~$ cd node-exporter
root@deploy:~$ git checkout -b 2.0.0

On modifie le fichier hosts contenu dans “inventory” et on déclare notre hosts :

root@deploy:~$ cd ../..
root@deploy:~$ nano inventory/hosts
[prometheus-server]
10.0.45.8
 
[node]
10.0.44.214
10.0.44.220
10.0.44.216

On créer notre fichier “ansible.cfg”

# config file for ansible -- https://ansible.com/
# ===============================================
 
[defaults]
remote_tmp             = /tmp
local_tmp              = ~/.ansible/tmp
forks                  = 10
log_path               = ~/.ansible/ansible.log
host_key_checking      = False
ansible_managed        = Ansible managed : modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
display_skipped_hosts  = False
display_args_to_stdout  = False
command_warnings        = False
 
[privilege_escalation]
become            = True
become_method     = sudo
become_user       = root
become_ask_pass   = False
 
[paramiko_connection]
record_host_keys  = False
 
[ssh_connection]
ssh_args = -o StrictHostKeyChecking=no -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null
pipelining = True

on créer le fichier “site.yml” :

---
 
- name: Bootstrap instance - Example plateforme
  hosts: prometheus-server
  gather_facts: true
 
  roles:
      - prometheus
      - node-exporter
 
  vars:
    prometheus_targets:
      node:
      - targets:              #
        - debian:9100         # All this is a targets section in file_sd format
        - node01:9100
        - node02:9100
        - node03:9100
        labels:               #
          env: test           #

On lance le déploiement de notre playbook :

Assurer vous que vous avez bien le droit de déployer le playbook sur l'hôte distant.

root@deploy:~$ ansible-playbook -i inventory/hosts site.yml

On vérifie que prometheus et bien opérationnel. Pour cela, il suffira de ce rendre sur l'URL de notre hôte (FQDN/IP) avec le port “9090”

Depuis le serveur de déploiement, toujours sur notre arborescence :

Dans le dossier “ansible-prometheus”

root@deploy:~$ ansible-prometheus
      - roles/
      - inventory/
                 - hosts
      - ansible.cfg
      - site.yml 

Dans le dossier rôles, nous allons récupérer le rôles ansible pour grafana :

root@deploy:~$ cd roles
root@deploy:~$ git clone https://github.com/cloudalchemy/ansible-grafana.git grafana
root@deploy:~$ git checkout -b 0.18.0

On modifie le fichier “site.yml” et on ajoute le rôle grafana :

---
 
- name: Bootstrap instance - Example plateforme
  hosts: prometheus-server
  gather_facts: true
 
  roles:
      - prometheus
      - node-exporter
      - grafana
 
  vars:
    # Variable pour la déclaration du node-exporter
    prometheus_targets:
      node:
      - targets:              #
        - debian:9100         # All this is a targets section in file_sd format
        - node01:9100
        - node02:9100
        - node03:9100
        labels:               #
          env: test           #
    # Variable pour l'accès à l'interface de "grafana", On vous demandera de
    # changer le mote de passe à la première connexion
    grafana_security:
      admin_user: admin
      admin_password: admin
    grafana_datasources:
      - name: prometheus
        type: prometheus
        access: proxy
        url: 'http://{{ prometheus_web_listen_address }}'
        basicAuth: false

Une fois le déploiement via ansible réalisé, il nous suffira de nous rendre sur l'adresse du server : "http://<FQDN/IP>:3000"

Utilisé le login/password déclaré dans le playbook, ici : admin/admin

Grafana vous demande de changer le mots de passe, entrer un nouveau mots de passe et cliquer sur SAVE

Nous voilà sur l'interface de grafana.

Depuis le serveur de déploiement, toujours sur notre arborescence :

Dans le dossier “ansible-prometheus”

root@deploy:~$ ansible-prometheus
      - roles/
      - inventory/
                 - hosts
      - ansible.cfg
      - site.yml 

Dans le dossier rôles, nous allons récupérer les rôles ansible pour prometheus et prometheus-node-exporter:

root@deploy:~$ cd roles
root@deploy:~$ git clone https://github.com/cloudalchemy/ansible-grafana.git grafana
root@deploy:~$ git checkout -b 0.16.0

on modifie le fichier “site.yml” et on ajoute le rôle grafana :

---
 
- name: Bootstrap instance - Example plateforme
  hosts: prometheus-server
  gather_facts: true
 
  roles:
      - prometheus
      - node-exporter
      - grafana
 
  vars:
    prometheus_targets:
      node: 
      - targets:              #
        - debian:9100         # All this is a targets section in file_sd format
        - node01:9100
        - node02:9100
        - node03:9100
        labels:               #
          env: test           #
    grafana_security:
      admin_user: admin
      admin_password: admin
    grafana_datasources:
      - name: prometheus
        type: prometheus
        access: proxy
        url: 'http://{{ prometheus_web_listen_address }}'
        basicAuth: false
    grafana_dashboards:
      - dashboard_id: 11074
        revision_id: 2
        datasource: prometheus

Une fois le déploiement via ansible réalisé, il nous suffira de nous rendre sur l'adresse du server : "http://<FQDN/IP>:3000"

Utilisé le login/password déclaré dans le playbook, ici : admin/admin

Grafana vous demande de changer le mots de passe, entrer un nouveau mots de passe et cliquer sur SAVE

Nous voilà sur l'interface de grafana avec notre dashboard pour le serveur prometheus.

Depuis le serveur de déploiement, toujours sur notre arborescence :

Dans le dossier “ansible-prometheus”

root@deploy:~$ ansible-prometheus
      - roles/
      - inventory/
                 - hosts
      - ansible.cfg
      - site.yml 

Dans le dossier “roles”, nous allons récupérer le rôles ansible pour grafana :

root@deploy:~$ cd roles
root@deploy:~$ git clone https://github.com/cloudalchemy/ansible-alertmanager.git alertemanager
root@deploy:~$ git checkout -b 0.15.1

on modifie le fichier “site.yml” et on ajoute le rôle alertemanager :

---
 
- name: Bootstrap instance - Example plateforme
  hosts: prometheus-server
  gather_facts: true
 
  roles:
      - prometheus
      - node-exporter
      - grafana
      - alertemanager
 
  vars:
    # Variable pour la déclaration du node-exporter
    prometheus_targets:
      node:
      - targets:              #
        - debian:9100         # All this is a targets section in file_sd format
        - node01:9100
        - node02:9100
        - node03:9100
        labels:               #
          env: test           #
 
    # Variable pour l'accès à l'interface de "grafana", On vous demandera de
    # changer le mote de passe à la première connexion
    grafana_security:
      admin_user: admin
      admin_password: admin
    grafana_datasources:
      - name: prometheus
        type: prometheus
        access: proxy
        url: 'http://{{ prometheus_web_listen_address }}'
        basicAuth: false
    grafana_dashboards:
      - dashboard_id: 11074
        revision_id: 2
        datasource: prometheus
 
    # EXEMPLE de Configuration d'alertemanager pour envoyer des emails via gmail
    alertmanager_external_url: "http://{{ ansible_host }}:9093"
    alertmanager_receivers:
      - name: mail
        email_configs:
        - send_resolved: true
          to: 'ssssss@gmail.com'
          from: 'noreply@gmail.com'
          smarthost: 'smtp.gmail.com:587'
          auth_username: 'ssssss@gmail.com'
          auth_identity: 'ssssss@gmail.com'
          auth_password: 'xxxxxxxxx'
    alertmanager_route:
      group_by: ['alertname', 'cluster', 'service']
      group_wait: 30s
      group_interval: 1m
      repeat_interval: 30m
      receiver: mail

Une fois le déploiement via ansible réalisé, il nous suffira de nous rendre sur l'adresse du server : "http://<FQDN / IP>:9093"

La première chose à faire est déjà de s’assurer que l’envoi des alertes fonctionne correctement.

on va « Curler », donc utiliser la commande CURL avec :

root@prometheus:~$  curl -H "Content-Type: application/json" -d '[{"labels":{"alertname":"Test"}}]' localhost:9093/api/v1/alerts

C’est d’ailleurs de cette façon que Prometheus déclenchera Alertmanager.

Et peu de temps après, un email doit arriver.

Nginx est un serveur Web puissant et un excellent proxy inverse.

Dans notre cas, nous souhaitons l’utiliser devant notre application Grafana :

  • Pour gérer toutes les configurations de sécurité telles que les certificats SSL et la sécurité des demandes entrantes.
  • Pour autoriser toutes les demandes entrantes à atteindre les ports http traditionnels 80/443 et à laisser le service Grafana s'exécuter en interne sur le port 3000.

Pour les distributions Debian et dérivée.

root@monitoring:~# apt-get install nginx

On vérifier l'état du service “nginx”.

root@monitoring:~# systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2019-07-24 21:49:46 CEST; 1min 22s ago
     Docs: man:nginx(8)
  Process: 7108 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 7107 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 7111 (nginx)
    Tasks: 2 (limit: 4915)
   CGroup: /system.slice/nginx.service
           ├─7111 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           └─7112 nginx: worker process

Action réalisable pour l'interface WEB UI de prometheus / grafana

On crée le “vhosts” grafana qui va proxifier les flux du nom de domaine “grafana.mondomaine.lan” vers la “localhost” sur le port “3000”.

Ci joint un vhosts fonctionnel.

root@monitoring:~# nano /etc/nginx/sites-available/grafana
upstream grafana{
    server 127.0.0.1:3000;
}
 
server{
    listen      80;
    server_name grafana.mondomaine.lan;
 
    access_log  /var/log/nginx/grafana.access.log;
    error_log   /var/log/nginx/grafana.error.log;
    ignore_invalid_headers off;
 
    location / {
 
        proxy_set_header    Host            $host:$server_port;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;
 
        proxy_pass          http://grafana;
        proxy_read_timeout  90;
 
        proxy_redirect      http://127.0.0.1:3000 http://grafana.mondomaine.lan;
 
    }
}

On créer le lien symbolique pour activer ce vhosts

root@monitoring:~# cd /etc/nginx/sites-enabled/
root@monitoring:/etc/nginx/sites-enabled# ln -s /etc/nginx/sites-available/grafana

On vérifie la configuration de “nginx” avant de le redémarrerSous la distribution “debian”, on crée le liens symbolique.

root@monitoring:/etc/nginx/sites-enabled# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

On redémarre le service “nginx”.

root@monitoring:/etc/nginx/sites-enabled# systemctl restart nginx

On pourra à présent accéder au service “grafana” à travers l'URL définie dans notre vhosts : "http://grafana.mondomaine.lan".

Une fois l'accès au travers de “nginx” réalisé, il nous suffira de limiter le service “grafana-server” en localhost.

root@monitoring # nano /etc/grafana/grafana.ini

Remplacer les variables :

# http_addr = 0.0.0.0
# root_url = http://0.0.0.0:3000

Par :

http_addr = 127.0.0.1
root_url = http://127.0.0.1:3000

On relance le service “grafana”.

root@monitoring # systemctl restart grafana-server

Arrivé à cette étapes, notre plateforme Prometheus/Grafana/prometheus-node-exporter est opérationnelle.

Nous allons voir comment ajouter un nouveau nœud à monitorer, et pour cela, nous allons utiliser notre playbook ansible en déclarant notre nouveau serveur.

---
 
- name: Bootstrap instance - Prometheus
  hosts: prometheus-server
  gather_facts: true
 
  roles:
      - prometheus
      - node-exporter
      - grafana
 
  vars:
    prometheus_targets:
      node:
      - targets:
        - debian:9100
        - node01:9100      #  <----- ON DECLARE LE NOUVEAU NOEUD
        labels:
          env: test
    grafana_security:
      admin_user: admin
      admin_password: admin
    grafana_datasources:
      - name: prometheus
        type: prometheus
        access: proxy
        url: 'http://{{ prometheus_web_listen_address }}'
        basicAuth: false
    grafana_dashboards:
      - dashboard_id: 11074
        revision_id: 2
        datasource: prometheus
 
#  ----- A PARTIR D'ICI ON DEPLOIE
#  ----- LA STACK NODE-EXPORTER SUR LES SERVEURS
- name: Bootstrap instance - Node  
  hosts: node
  gather_facts: true
 
  roles:
      - node-exporter

Si l'on vérifie l'interface Grafana, notre nouveau nœud apparaitra en plus du serveur prometheus lui-même.

Annexe

Ce site web utilise des cookies. En utilisant le site Web, vous acceptez le stockage de cookies sur votre ordinateur. Vous reconnaissez également que vous avez lu et compris notre politique de confidentialité. Si vous n'êtes pas d'accord, quittez le site.En savoir plus