Table des matières

Pourquoi Prometheus ?

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é :

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

Architecture de Prometheus

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

Comment fonctionne-t-il ?

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.

Comment récupérer les données enregistrées ?

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

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 :

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))

A quoi servent les Exporters ?

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 :

Fonctionnement mode Pull / Push

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.

Utilisation de Prometheus derrière un ou plusieurs Firewalls

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 :

L'agent peut s'exécuter :

Un proxy peut gérer un ou plusieurs agents.

Alerting dans Prometheus

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 :

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

Intégration avec Grafana

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.

Plateforme Prometheus / Grafana

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.

Architecture de validation

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 :

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

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

Pré-requis serveur de déploiement

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

Installation de prometheus

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”

Installation de Grafana sans dashboard

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.

Installation de Grafana avec dashboard

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.

Installation d'Alertemanager

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"

Utilisation d'Alertemanager

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.

Reverse proxy nginx

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

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

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

Ajout d'un nœud à monitorer

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

https://github.com/prometheus/node_exporter

https://grafana.com/docs/grafana/latest/installation/configuration/