Préambule

Les travaux pratiques s'effectuent sur deux plateformes distinces.

La première est un Prometheus déjà installé sur un cluster Kubernetes qui permet d'effectuer des requêtes PromQL afin de se concentrer sur l'apprentissage du langage.

La seconde est un ensemble de machines individuelles sur lesquelles chacun d'entre vous pourra se connecter afin de procéder à l'installation et au paramétrage de Prometheus et de différents exporteurs.

L'accès aux différentes plateformes est protégé par une gateway 0 trust sur laquelle il faudra s'enregistrer au préalable en utilisant les liens individuels fournis en séance.

Accès au sujet de TP

https://sqli-prom-activities.ext-gw.datailor.fr/

Passerelle 0 trust

https://ext-gw.datailor.fr

Plateforme #1 : Cluster Kubernetes

Prometheus

https://sqli-training-prometheus.ext-gw.datailor.fr/graph

Plateforme #2 : Serveurs personnels

Machine : prom01

Machine : prom02

Machine : prom03

Machine : prom04

Machine : prom05

Machine : prom06

Machine : prom07

Machine : prom08

Machine : prom09

Machine : prom10

Machine : prom11

Machine : prom12

Exercices - Partie 1 le PromQL

Exercices à effectuer sur le cluster Kubernetes

Exercice 1

Sujet

Trouver la charge CPU par instance, par CPU sur l'ensemble du cluster

Métrique : node_cpu_seconds_total

Modes à prendre en compte :

  • user
  • system
  • nice
  • irq
  • iowait
  • softirq
  • steal

Mode à ne pas prendre en compte :

  • idle

Solution

show
sum(node_cpu_seconds_total{mode!="idle"}) by (instance,cpu)
sum by (instance,cpu) (node_cpu_seconds_total{mode!="idle"})


sum(node_cpu_seconds_total{mode=~"user|system|nice|irq|iowait|softirq|steal"}) by (instance,cpu)


node_cpu_seconds_total{mode="user"}
+ ignoring(mode) node_cpu_seconds_total{mode="system"}
+ ignoring(mode) node_cpu_seconds_total{mode="nice"}
+ ignoring(mode) node_cpu_seconds_total{mode="irq"}
+ ignoring(mode) node_cpu_seconds_total{mode="iowait"}
+ ignoring(mode) node_cpu_seconds_total{mode="softirq"}
+ ignoring(mode) node_cpu_seconds_total{mode="steal"}

Exercice 1bis

Sujet

Afficher maintenant uniquement les modes user et system :

Solution

show
sum by (instance,cpu) (node_cpu_seconds_total{mode=~"user|system"})

Exercice 2

Sujet

Identifier l'espace disque disponible restant sur chacune des instances du cluster sur la partition racine.

Métrique : node_filesystem_free_bytes

Solution

show
node_filesystem_free_bytes{mountpoint="/"}
sum by (instance) (node_filesystem_free_bytes{mountpoint="/"})

ATTENTION: node_filesystem_free_bytes correspond à l'espace disque restant prenant en compte la marge de 5% de linux, pour avoir la quantité d'espace disque utilisable utiliser node_filesystem_avail_bytes

Exercice 3

Sujet

Identifier le pourcentage d´espace disque disponible restant sur chacune des instances du cluster sur la partition racine.

Métriques :
- node_filesystem_free_bytes <-- Quantité d´espace disque disponible
- node_filesystem_size_bytes <-- Quantité d´espace disque total

Solution

show
node_filesystem_free_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100

node_filesystem_free_bytes{mountpoint="/"} / node_filesystem_size_bytes

Exercice 4

Sujet

Sur la base de la requête précédente, identifier la tendance d'évolution de l'espace disque disponible restant sur la partition racine sur les 4 dernières heures (ou 5 dernières minutes si vous êtes sur ADSL).

Fonctions possibles :

  • deriv
  • rate
  • irate

Solution

show
deriv(node_filesystem_avail_bytes[4h])

NOTE: rate et irate sont inapplicables et donnent des résultats qui peuvent porter à confusion car la métrique est une jauge et non un compteur

Exercice 4bis

Sujet

Utiliser la fonction rate sur la métrique node_cpu_seconds_totalsur un période de 5m puis sur une période de 2m

Quelle observation faites-vous du résultat obtenu ?

Solution

show
rate(node_cpu_seconds_total[5m])
rate(node_cpu_seconds_total[2m])

Le rate sur 5m est plus lissé que le rate sur 2m. Pour obtenir un graphe de consommation CPU au plus juste on priviligégie la période de 2m ou encore un irate

Exercice 5

Sujet

Pondérer le résultat de la requête précédente avec la tendance d'évolution de la charge CPU sur les 12 dernières heures

Solution

show
# a * rate2m + b * rate12h
# a + b = 1
# 0 < a < 1
# 0 < b < 1
0.1 * rate(node_cpu_seconds_total{mode="idle"}[2m]) + 0.9 * rate(node_cpu_seconds_total{mode="idle"}[12h])

Exercice 6

Sujet

Sur la base des requêtes précédentes, prédire la quantité d'espace disque disponible restant sur la partition racine.

Solution

show
predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 4 * 3600)

Exercice 7

Sujet

Utiliser la fonction holt_winters sur la métrique node_filesystem_free_bytes pour construire un graphe pertinent de l'évolution de l'espace disque disponible restant sur la partition racine, jouez sur les paramètres sfet tfpour voir leur impact et identifier des cycles

Solution

show
holt_winters(node_filesystem_free_bytes{mountpoint="/"}[4h], 0.1, 0.93)

Exercice 8

Sujet

Sur la base de la requête de l'exercice 1, calculer la tendance d'évolution de la charge CPU par instance, par CPU sur l'ensemble du cluster sur les 4 dernières heures (ou 5 dernières minutes si vous êtes sur ADSL)

Solution

show
deriv(irate(node_cpu_seconds_total{mode="idle"}[2m])[4h])

NOTE: Impossible car on ne peut appliquer un range sur le résultat d'un calcul

sum (rate (node_cpu_seconds_total{mode!="idle"}[4h])) by (instance,cpu)

Exercice 9

Sujet

Soustraire la métrique scrape_samples_scraped à la valeur du compte des métriques

  • Commencer par compter le nombre de métriques (Utiliser __name__)

Solution

show
count({__name__!=""}) - sum(scrape_samples_scraped)

Exercice 10

Sujet

Écrire une requête basée sur le compteur node_cpu_seconds_total pour connaître le pourcentage d'utilisation CPU par instance

Solution

show
sum by (instance) (irate(node_cpu_seconds_total{mode!="idle"}[2m]))

/ on (instance)

count by (instance) (node_cpu_seconds_total{mode="idle"})

* 100

Ou

sum by (instance) (irate(node_cpu_seconds_total{mode!="idle"}[2m]))

/ on (instance)

sum by (instance) (irate(node_cpu_seconds_total[2m]))

* 100

Exercice 11

Sujet

Écrire une requête basée sur le compteur prometheus_http_requests_total pour connaître l'évolution des requêtes sur 5m

Solution

show
rate(prometheus_http_requests_total[5m])

Exercice 12

Sujet

Identifier le ratio de requêtes http en erreur 400 par rapport aux requêtes http ok (status 200). Utiliser la métrique prometheus_http_requests_total

Solution

show
sum(increase(prometheus_http_requests_total{code="400"}[2m])) / sum(increase(prometheus_http_requests_total{code="200"}[2m]))

Exercice 13

Sujet

Identifier le ratio de requêtes http en erreurs (quel que soit le code) par rapport aux requêtes http ok (i.e. valides). Utiliser la métrique prometheus_http_requests_total

Solution

show
sum(increase(prometheus_http_requests_total{code=~"4[0-9][0-9]|5[0-9][0-9]"}[2m]))
/
sum(increase(prometheus_http_requests_total{code=~"1[0-9][0-9]|2[0-9][0-9]"}[2m]))

Exercice 14

Sujet

Identifier le 90e percentile de la durée des requêtes http. Utiliser la métrique prometheus_http_request_duration_seconds_bucket

90e percentile = 0.9 quantile

Solution

show
histogram_quantile(0.9, prometheus_http_request_duration_seconds_bucket)

Exercice 14bis

Sujet

Écrire la requête du calcul de l'apdex :

Étant données les SLA suivantes :

  • Satisfaisant : req <= 0.2s
  • Tolérable : req <= 1s > 0.2s
  • Frustrante : req > 1s

Et la formule suivante :

\[ Apdex = \left( \frac{ Sat \times 1 + Tol \times 0.5 + Fru \times 0 }{ Nb_{req} } \right) \]

Solution

show

APDEX Long terme par handler

(
  # Requêtes satisfaisantes
  prometheus_http_request_duration_seconds_bucket{le="0.2"}
  + ignoring(le)
  (
    (
      # Requêtes tolérables
      prometheus_http_request_duration_seconds_bucket{le="1"}
      - ignoring(le)
      prometheus_http_request_duration_seconds_bucket{le="0.2"}
    )
    *
    0.5
  )
)
/ ignoring(le)
# Nombre total de requêtes
prometheus_http_request_duration_seconds_bucket{le="+Inf"}

APDEX Long terme

(
  # Requêtes satisfaisantes
  sum(prometheus_http_request_duration_seconds_bucket{le="0.2"})
  +
  (
    (
      # Requêtes tolérables
      sum(prometheus_http_request_duration_seconds_bucket{le="1"})
      -
      sum(prometheus_http_request_duration_seconds_bucket{le="0.2"})
    )
    *
    0.5
  )
)
/
# Nombre total de requêtes
sum(prometheus_http_request_duration_seconds_bucket{le="+Inf"})

APDEX Court terme

(
  # Requêtes satisfaisantes
  sum(increase(prometheus_http_request_duration_seconds_bucket{le="0.2"}[2m]))
  +
  (
    (
      # Requêtes tolérables
      sum(increase(prometheus_http_request_duration_seconds_bucket{le="1"}[2m]))
      -
      sum(increase(prometheus_http_request_duration_seconds_bucket{le="0.2"}[2m]))
    )
    *
    0.5
  )
)
/
# Nombre total de requêtes
sum(increase(prometheus_http_request_duration_seconds_bucket{le="+Inf"}[2m]))

Exercices - Partie 2 l'installation et le paramétrage

Exercices à effectuer sur votre serveur personnel

Exercice 15

Mise en place des dossiers et configuration docker-compose :

apt update

mkdir -p /opt/prometheus/data
mkdir -p /opt/prometheus/config
touch /opt/prometheus/docker-compose.yml
touch /opt/prometheus/config/prometheus.yml

echo "autocmd FileType yaml setlocal ts=2 sts=2 sw=2 expandtab" >> ~/.vimrc

echo "set listchars=tab:▸\ ,trail:·,precedes:·,extends:·,eol:$,space:·" >> ~/.vimrc

echo "set list" >> ~/.vimrc
vim /opt/prometheus/config/prometheus.yml

Contenu du fichier prometheus.yml


global:
  scrape_interval: 15s
  evaluation_interval: 15s

Lancement de Prometheus (version simple)

Sur le serveur personnel


cd /opt/prometheus
apt install -y docker-compose
vim /opt/prometheus/docker-compose.yml

Contenu du fichier docker-compose.yml :


version: '3.5'

services:
  prometheus:
    image: prom/prometheus
    ports:
    - 9090:9090
    volumes:
    - "/opt/prometheus/config/:/etc/prometheus/"
    command: --config.file=/etc/prometheus/prometheus.yml --log.level=debug # Uniquement pour mettre prometheus en mode debug

  node-exporter:
    image: quay.io/prometheus/node-exporter
    volumes:
    - "/:/host:ro,rslave"
    ports:
    - 9100:9100
    command: --path.rootfs=/host

Démarrage du node-exporter et du serveur Prometheus


docker-compose up -d && docker-compose logs -f

Exercice 16

Sujet

Est-ce que les métriques du node-exporter sont disponibles dans le serveur prometheus

Solution

show
Non

Exercice 17

Sujet

Rajouter la configuration dans scrape_configs pour récupérer les métriques du node-exporter avec une static_config

Utiliser la documentation suivante : https://prometheus.io/docs/prometheus/latest/configuration/configuration/

docker-compose restart prometheus # Redémarrer prometheus
docker-compose logs prometheus # Lire les logs du serveur prometheus

Solution

show
#file: /opt/prometheus/config/prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
- job_name: node-exporter
  static_configs:
  - targets:
    - 10.102.28.XX:9100
    labels:
      node: promXX

Exercice 18

Sujet

Rajouter la configuration dans scrape_configs pour récupérer les métriques du prometheus

Solution

show
#file: /opt/prometheus/config/prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
- job_name: node-exporter
  static_configs:
  - targets:
    - 10.102.28.XX:9100 # node exporter
    labels:
      node: promXX
- job_name: prometheus
  static_configs:
  - targets:
    - 10.102.28.XX:9090 # prometheus
    labels:
      node: promXX

Exercice 19

Sujet

  • Chercher la documention du scraper sur https://prometheus.io/
  • Transformer la configuration de scraping du node-exporter en file discovery et redémarrer le serveur prometheus
  • Ajouter le node exporter 10.102.28.72:9100 sans redémarrer le serveur prometheus

Solution

show
#file: /opt/prometheus/config/prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
- job_name: prometheus
  static_configs:
  - targets:
    - 10.102.28.XX:9090 # prometheus
    labels:
      node: promXX

- job_name: node-exporter
  file_sd_configs:
  - files:
    - ./node-exporters.yml
    refresh_interval: "15s"
#file: /opt/prometheus/config/node-exporters.yml

- targets:
  - 10.102.28.XX:9100 # node exporter
  - 10.102.28.72:9100
  labels:
    node: promXX

Exemple plus complet et dynamique :

#file: /opt/prometheus/config/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
- job_name: prometheus
  static_configs:
  - targets:
    - 10.102.28.XX:9090 # prometheus
    labels:
      node: promXX

- job_name: node-exporter
  file_sd_configs:
  - files:
    - ./targets/node-exporters/*.yml
    refresh_interval: "15s"

#file: /opt/prometheus/config/targets/node-exporters01.yml
- targets:
  - 10.102.28.XX:9100 # node exporter
  labels:
    node: promXX

Exercice 20

Sujet

Installer un nouvel exporter (MySQL, Docker avec cAdvisor) et l'intégrer dans votre instance prometheus

Installation de MySQL

Installer et configurer MySQL


apt install -y mysql-server
sed -i -e 's/127.0.0.1/0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
rm -rf /var/lib/mysql
mkdir /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
mysqld --initialize-insecure --console
service mysql stop
service mysql start
mysql -uroot -h localhost

mysql> create user 'prometheus' identified by 'prometheus';
mysql> grant all on *.* to 'prometheus'@'%';
mysql> create database bdd;
mysql> grant all on *.* to 'prometheus'@'%';
mysql> use bdd;
mysql> create table test_table (id int primary key, test varchar(100));

Ajouter au docker-compose.yml:


  mysqld-exporter:
    image: prom/mysqld-exporter
    ports:
    - 9104:9104
    environment:
    - DATA_SOURCE_NAME=prometheus:prometheus@(<IP>:3306)/bdd

Pour lancer le mysqld-exporter, il suffit de faire :


docker-compose up -d

Pour lire les logs :


docker-compose logs mysqld-exporter

Sujet

Scraper les données de votre mysqld-exporter puis trouver la métrique qui permet de savoir que le serveur mysql tourne bien :

Solution

show

#file: /opt/prometheus/targets/mysqld-exporters01.yml
- targets:
  - 10.102.28.XX:9104
  labels:
    node: promXX


#file: /opt/prometheus/config/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
- job_name: prometheus
  static_configs:
  - targets:
    - 10.102.28.XX:9090 # prometheus
    labels:
      node: promXX

- job_name: node-exporter
  file_sd_configs:
  - files:
    - ./targets/node-exporters/*.yml
    refresh_interval: "15s"

- job_name: mysqld-exporter
  file_sd_configs:
  - files:
    - ./targets/mysqld-exporters/*.yml
    refresh_interval: "15s"

Sujet

Trouver la métrique qui permet de savoir si Mysql est bien up & running.

Solution

show
mysql_up

Exercice 21 - cAdvisor

Ajouter au docker-compose.yml:


  cadvisor:
    image: google/cadvisor:latest
    ports:
    - 8080:8080
    volumes:
    - "/:/rootfs:ro"
    - "/var/run:/var/run:ro"
    - "/sys:/sys:ro"
    - "/var/lib/docker/:/var/lib/docker:ro"
    - "/dev/disk/:/dev/disk:ro"
    privileged: true

Exécuter docker-compose up -d dans le dossier /opt/prometheus

Sujet

Scraper les métriques de cAdvisor

Solution

show
#file: /opt/prometheus/config/cadvisors01.yml
#file: /opt/prometheus/config/prometheus.yml

Sujet

Lister les conteneurs qui ont été vus pour la dernière fois il y a moins d'une minute :

Solution

show
(time() - container_last_seen) < 60

Sujet

Superviser la consommotion CPU, mémoire et réseau de Prometheus et lancer en parallèle la requête promql {__name__=~".+"}

Solution

show

Consommation CPU des containers

sum by (id) (irate(container_cpu_usage_seconds_total{id=~"/docker/.*"}[2m]))

Consommation RAM des containers

container_memory_usage_bytes{id=~"/docker/.*"}

Capacité RAM occupée en %

container_memory_usage_bytes{id=~"/docker/.*"} / ignoring (id, instance, job) group_left node_memory_MemTotal_bytes * 100

container_memory_usage_bytes{id=~"/docker/.*"} / container_spec_memory_reservation_limit_bytes

container_memory_usage_bytes{id=~"/docker/.*"} / (container_spec_memory_reservation_limit_bytes != 0)

container_memory_usage_bytes{id=~"/docker/.*"} / container_spec_memory_limit_bytes

container_memory_usage_bytes{id=~"/docker/.*"} / (container_spec_memory_limit_bytes != 0)

Quantité réseau utilisée en réception

irate(container_network_receive_bytes_total[2m])

Quantité réseau utilisée en émission

irate(container_network_transmit_bytes_total[2m])

Exercice 22

Déployer le blackbox exporter

mkdir /opt/prometheus/blackbox

wget https://raw.githubusercontent.com/prometheus/blackbox_exporter/master/example.yml -O /opt/prometheus/blackbox/blackbox.yml

Ajouter au docker-compose.yml:

  blackbox:
    image: prom/blackbox-exporter:master
    ports:
    - 9115:9115
    command: "--config.file=/config/blackbox.yml"
    volumes:
    - "/opt/prometheus/blackbox:/config"

Sujet

Configurer prometheus pour qu'il scrape les métriques des probe du blackbox exporter pour le site orange.fr

Attention, bien utiliser le module http_2xx_example à la place de http_2xx

Solution

show
# file:prometheus.yml
- job_name: blackbox
  file_sd_configs:
  - files:
    - ./targets/blackbox/*.yml
    refresh_interval: "15s"
  metrics_path: /probe
  params:
    module: [http_2xx_orange_fr]
  relabel_configs:
  - source_labels: [__address__]
    target_label: __param_target
  - source_labels: [__param_target]
    target_label: instance
  - target_label: __address__
    replacement: 10.102.28.71:9115


# file:./targets/blackbox/orange-targets.yml
- targets:
  - orange.fr
  labels:
    node: promXX

Suite à la modification dans le docker-compose.yml effectuer :


docker-compose up -d

Note: Pour redémarrer le blackbox exporter :

docker-compose restart blackbox

Sujet

Trouver le code retour HTTP du site orange.fr tel que récupéré depuis le blackbox exporter

Solutions

show
probe_http_status_code{instance="orange.fr"}

Sujet

Résoudre le soucis en modifiant les headers HTTP dans la configuration du blackbox exporter

Solutions

show

#file: /opt/prometheus/blackbox/blackbox.yml
modules:
  http_2xx_orange_fr:
    prober: http
    timeout: 5s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: []  # Defaults to 2xx
      method: GET
      headers:
        Host: orange.fr
        Accept-Language: en-US
        Origin: orange.fr
      follow_redirects: true
      fail_if_ssl: false
      fail_if_not_ssl: false
      fail_if_body_matches_regexp:
        - "Could not connect to database"
      fail_if_body_not_matches_regexp:
        - "[Oo]range"
      fail_if_header_matches: [] # Verifies that no cookies are set
      fail_if_header_not_matches:
        - header: Set-Cookie
          allow_missing: true
          regexp: '.*'
      tls_config:
        insecure_skip_verify: false
      preferred_ip_protocol: "ip4" # defaults to "ip6"
      ip_protocol_fallback: false  # no fallback to "ip6"

Sujet

Trouver le temps de réponse global d'orange.fr

Solution

show
probe_duration_seconds{instance="orange.fr"}
sum by (instance) (probe_http_duration_seconds{instance="orange.fr"})

Exercice 23

Sujet

Rajouter à votre supervision un cluster Kubernetes (URL et token ci-dessous) en utilisant kubernetes_sd_configs


api_server: https://rancher.k8s.datailor.fr/k8s/clusters/c-mdmxl
role: ingress
authorization:
  credentials: kubeconfig-u-crd2h8kh77:mgs57kl5z54l76qnqvj8dwvnlsqn5bw6cm68dp2277hm6hc4vvw7wt

Rajouter les role: ingress à votre scrape config du blackbox exporter.


Liste des ingress présentes dans le cluster :
NAMESPACE           NAME                 CLASS    HOSTS                                     ADDRESS                     PORTS     AGE
cattle-prometheus   prometheus-ingress   <none>   prometheus.formation.public.datailor.fr   10.102.28.13,10.102.28.14   80, 443   2d21h
cattle-prometheus   prometheus-ingress   <none>   grafana.formation.public.datailor.fr   10.102.28.13,10.102.28.14   80, 443   2d21h

Solution

show
#file:prometheus.yml
- job_name: blackbox_kubernetes
  kubernetes_sd_configs:
  - role: ingress
    api_server: https://rancher.k8s.datailor.fr/k8s/clusters/c-mdmxl
    authorization:
      credentials: kubeconfig-u-crd2h8kh77:mgs57kl5z54l76qnqvj8dwvnlsqn5bw6cm68dp2277hm6hc4vvw7wt
  metrics_path: /probe
  params:
    module: [http_2xx]
  relabel_configs:
  - source_labels: [__address__]
    target_label: __param_target
  - source_labels: [__param_target]
    target_label: instance
  - target_label: __address__
    replacement: 10.102.28.XX:9115
#file: /opt/prometheus/blackbox/blackbox.yml
modules:
  http_2xx:
    prober: http
    timeout: 5s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: []  # Defaults to 2xx
      method: GET
      headers: {}
      follow_redirects: true
      fail_if_ssl: false
      fail_if_not_ssl: false
      fail_if_body_matches_regexp: []
      fail_if_body_not_matches_regexp: []
      fail_if_header_matches: [] # Verifies that no cookies are set
      fail_if_header_not_matches: []
      tls_config:
        insecure_skip_verify: false
      preferred_ip_protocol: "ip4" # defaults to "ip6"
      ip_protocol_fallback: false  # no fallback to "ip6"

Exercice 24

Dans docker-compose.yml rajouter :


  grafana:
    image: grafana/grafana
    ports:
    - 3000:3000
    volumes:
    - grafana-config:/etc/grafana
    - grafana-data:/var/lib/grafana
    - grafana-logs:/var/log/grafana

volumes:
  grafana-config:
  grafana-data:
  grafana-logs:

Pour prendre en compte la modification


docker-compose up -d && docker-compose logs -f grafana

Mot de passe par défaut admin:admin

  1. Créer la datasource Prometheus
  2. Importer le tableau de bord 1860 (node exporter)
  3. D'analyser les requêtes qui sont faites pour ressortir la charge CPU
  4. Trouver et importer un tableau de bord pour MySQL, analyser sa cohérence
  5. Trouver et importer un tableau de bord pour le blackbox exporter, analyser sa cohérence

https://grafana.com/grafana/dashboards/

Exercice 25

Créer le dossier $ mkdir /opt/prometheus/config/rules et ajouter dans /opt/prometheus/config/prometheus.yml :


rule_files:
- rules/*.rules.yml

Exécuter docker-compose restart prometheus && docker-compose logs -f prometheus

Exercice 26

https://awesome-prometheus-alerts.grep.to/rules.html

Créer le fichier /opt/prometheus/config/rules/basic.rules.yml et ajouter :


groups:
- name: example
  rules:
  - alert: (PXX) Instance down
    expr: count(up == 0) >= 1
    for: 1m
    labels:
      severity: page
    annotations:
      summary: (PXX) Instance down
      description: >
        (PXX) Instance down {{ range query "up == 0" }}
        - {{ .Labels.instance }} - {{ .Labels.job }}
        {{ end }}

Exercice 27

Ajouter au docker-compose.yml :


  alertmanager:
    image: prom/alertmanager
    ports:
    - 9093:9093
    volumes:
    - "/opt/prometheus/alertmanager/config/:/prometheus"
    - "/opt/prometheus/alertmanager/data/:/data"
    command: --config.file=/prometheus/alertmanager.yml --storage.path=/data

Exécuter :


mkdir -p /opt/prometheus/alertmanager/config/
mkdir -p /opt/prometheus/alertmanager/data/
chmod 777 -R /opt/prometheus/alertmanager/data/

Ajouter dans /opt/prometheus/alertmanager/config/alertmanager.yml :


global:
  #

route:
  receiver: 'mattermost'
  repeat_interval: 10s
  group_interval: 10s
  group_wait: 10s

receivers:
- name: mattermost
  slack_configs:
  - api_url: "https://chat.datailor.fr/hooks/am7kpp6f8pnq8xat37pap8usqa"
    send_resolved: true
    title: "(AXX){{ range .Alerts }}{{ .Annotations.summary }}\\n{{ end }}"
    text: "(AXX){{ range .Alerts }}{{ .Annotations.description }}\\n{{ end }}"

Exécuter docker-compose up -d && docker-compose logs -f

Ajouter dans /opt/prometheus/config/prometheus.yml :

alerting:
  alertmanagers:
  - scheme: http
    static_configs:
    - targets:
      - "<IP>:9093"

Exécuter docker-compose restart prometheus && docker-compose logs -f prometheus

Exercice 28

Écrire plusieurs alertes et les router différement selon leurs labels dans les receivers suivants :

Solution

show

#basic.rules:
groups:
- name: example
  rules:
  - alert: (PXX) Instance down
    expr: count(up == 0) >= 1
    for: 5s
    labels:
      severity: page
    annotations:
      summary: (PXX) Instance down
      description: >
        (PXX) Instance down {{ range query "up == 0" }}
        - {{ .Labels.instance }} - {{ .Labels.job }}
        {{ end }}
  - alert: (PXX) Instance down
    expr: count(up == 0) >= 1
    for: 5s
    labels:
      severity: pager
    annotations:
      summary: (P11) Instance down
      description: >
        (PXX) Instance down {{ range query "up == 0" }}
        - {{ .Labels.instance }} - {{ .Labels.job }}
        {{ end }}

#alertmanager.yml:
global:
  #

route:
  receiver: 'mattermost'
  repeat_interval: 10s
  group_interval: 10s
  group_wait: 10s
  routes:
  - match:
      severity: ticket
    receiver: mattermost-ticket
  - match:
      severity: info
    receiver: mattermost-info
  - match:
      severity: pager
    receiver: mattermost-pager


receivers:
- name: mattermost
  slack_configs:
  - api_url: "https://chat.datailor.fr/hooks/am7kpp6f8pnq8xat37pap8usqa"
    send_resolved: true
    title: "(AXX){{ range .Alerts }}{{ .Annotations.summary }}\\n{{ end }}"
    text: "(AXX){{ range .Alerts }}{{ .Annotations.description }}\\n{{ end }}"
- name: mattermost-pager
  slack_configs:
  - api_url: "https://chat.datailor.fr/hooks/bfyy41uny3y39pjmet46hnnijh"
    send_resolved: true
    title: "(AXX){{ range .Alerts }}{{ .Annotations.summary }}\\n{{ end }}"
    text: "(AXX){{ range .Alerts }}{{ .Annotations.description }}\\n{{ end }}"
- name: mattermost-ticket
  slack_configs:
  - api_url: "https://chat.datailor.fr/hooks/n73mdxdtq3fpd8r4x5zkmauaiy"
    send_resolved: true
    title: "(AXX){{ range .Alerts }}{{ .Annotations.summary }}\\n{{ end }}"
    text: "(AXX){{ range .Alerts }}{{ .Annotations.description }}\\n{{ end }}"
- name: mattermost-info
  slack_configs:
  - api_url: "https://chat.datailor.fr/hooks/otwsdx3a33df5ctc915hbn5xmc"
    send_resolved: true
    title: "(AXX){{ range .Alerts }}{{ .Annotations.summary }}\\n{{ end }}"
    text: "(AXX){{ range .Alerts }}{{ .Annotations.description }}\\n{{ end }}"

Exercice 29

Sujet

Écrire une recording rule correspondant à la somme des requêtes http de prometheus sur 5 minutes.

Solution

show
- name: recordings
  rules:
  - record: any:prometheus_http_requests:sum5m
    expr: sum(increase(prometheus_http_requests_total[5m]))

Exercice 30

Sujet

Écrire 2 recording rules, l'une pour calculer la moyenne sur 12h et l'autre l'écart type sur 12h de la recording rule précédente

Solution

show
- name: recordings
  rules:
  - record: any:prometheus_http_requests:sum5m
    expr: sum(increase(prometheus_http_requests_total[5m]))

  - record: any:avg_prometheus_http_requests:12h
    expr: avg_over_time(any:prometheus_http_requests:sum5m[12h])
  - record: any:stddev_prometheus_http_requests:12h
    expr: stddev_over_time(any:prometheus_http_requests:sum5m[12h])

Exercice 31

Sujet

Écrire la recording rule du z-score du nombre de requêtes http sur le serveur prometheus grâce à la formule suivante :

Z-score = (Métrique observée - moyenne de la métrique) / écart-type de la métrique

Solution

show
- name: recordings
  rules:
  - record: any:prometheus_http_requests:sum5m
    expr: sum(increase(prometheus_http_requests_total[5m]))

  - record: any:avg_prometheus_http_requests:12h
    expr: avg_over_time(any:prometheus_http_requests:sum5m[12h])
  - record: any:stddev_prometheus_http_requests:12h
    expr: stddev_over_time(any:prometheus_http_requests:sum5m[12h])

  - record: any:zscore_prometheus_https_requests:12h
    expr: >
      (
        any:prometheus_http_requests:sum5m
        -
        any:avg_prometheus_http_requests:12h
      )
      /
      any:stddev_prometheus_http_requests:12h

Exercice 32

Construire une fédération entre vos Prometheus

- job_name: federation
  static_configs:
  - targets:
    - 10.102.28.XX:9090
    - 10.102.28.72:9090
  metrics_path: /federate
  honor_labels: true
  honor_timestamps: true
  params:
    'match[]':
      - '{__name__=~"node_cpu_.*", instance=~"10.102.28.XX.*"}'
      - '{__name__=~"node_cpu_.*", instance=~"10.102.28.72.*"}'

Exercice 33

Sujet

Lire l'article de Gitlab sur la détection d'anomalies avec Prometheus (https://about.gitlab.com/blog/2019/07/23/anomaly-detection-using-prometheus/) et améliorer notre requête précédente.

Références utiles