Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
Prochaine révisionLes deux révisions suivantes
technique:adminsys:monitoring:alerting:vmalert [2021/08/31 00:36] qduchemitechnique:adminsys:monitoring:alerting:vmalert [2021/09/01 19:11] qduchemi
Ligne 2: Ligne 2:
  
 ## Surveiller les métriques avec vmalert ## Surveiller les métriques avec vmalert
 +
 +<bootnote warning>
 +Il sera plus facile de lire cette article avec une compréhension basique de la [pile de métrologie de Picasoft](https://wiki.picasoft.net/doku.php?id=technique:adminsys:monitoring:metrologie:start). 
 +</bootnote>
 +
 +### Rappels
 +
 +Pour résumer très rapidement ce qui est utile, Picasoft stocke des **métriques** (mesure de n'importe quoi dans l'infrastructure : nombre de requêtes, utilisation CPU...) dans une time series database (TSDB). Une TSDB est une base de données optimisée pour stocker des séries de données associées à un horodatage, nommées *timeseries*. Picasoft utilise [[technique:adminsys:monitoring:metrologie:victoriametrics|Victoria Metrics]].
 +
 +Les métriques suivent des [conventions de nommages](https://prometheus.io/docs/practices/naming) permettant de deviner leur nature (*e.g* `traefik_service_requests_total`, qui s'auto-décrit bien).
 +
 +Chaque métrique est associée à des **labels**, qui portent des métadonnées sur la mesure, par exemple pour préciser le service ou la machine concernée par la métrique.
 +
 +On peut ensuite effectuer des requêtes, comme sur n'importe quelle base de données. Les requêtes sont souvent des calculs sur une timeserie avec un début et une fin. Exemple : « donne moi le nombre de requêtes HTTP par secondes qu'a reçu Mattermost les 5 dernières minutes ». 
 +
 +Le langage de requêtage s'appelle [PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/). La requête d'exemple s'écrirait alors :
 +
 +```
 +rate(traefik_service_requests_total{service_name~="team.picasoft.net"}[5m])
 +```
 +
 +Soit littéralement : par secondes, le nombre de requêtes dont le label `service_name` vaut `team.picasoft.net` pour les dernières 5 minutes.
 +
 +<bootnote web>
 +L'article [PromQL for humans](https://timber.io/blog/promql-for-humans/) constitue une bonne introduction à PromQL.
 +</bootnote>
 +
 +### Préambule
  
 `vmalert` est un outil compatible avec [[technique:adminsys:monitoring:metrologie:victoriametrics|Victoria Metrics]] qui permet d'évaluer des **règles** sur des métriques et de déclencher des alertes selon les règles. `vmalert` est un outil compatible avec [[technique:adminsys:monitoring:metrologie:victoriametrics|Victoria Metrics]] qui permet d'évaluer des **règles** sur des métriques et de déclencher des alertes selon les règles.
  
 <bootnote> <bootnote>
-Dans `vmalert`, une règle est une condition sur le résultat d'une requête [PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/). L'outil a en effet été conçu pour être compatible avec les fichiers d'alertes utilisés dans le monde Prometheus. +Dans `vmalert`, une règle est une condition sur le résultat d'une requête [PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/). PromQL est initialement développé pour faire des requêtes sur une TSDB Prometheus, mais nous utilisons Victoria Metrics, qui est compatible avec l'écosystème Prometheus. Le format de fichier d'alertes `vmalert` est compatible avec le format de fichier d'alertes utilisé dans l'écosystème Prometheus. 
-</boonote>+</bootnote>
  
 `vmalert` est exécuté depuis l'image Docker officielle et la configuration s'effectue avec les arguments de la ligne de commande (voir [Docker Compose](https://gitlab.utc.fr/picasoft/projets/dockerfiles/-/blob/master/pica-metrologie/docker-compose.yml)) et via un fichier de règles. `vmalert` est exécuté depuis l'image Docker officielle et la configuration s'effectue avec les arguments de la ligne de commande (voir [Docker Compose](https://gitlab.utc.fr/picasoft/projets/dockerfiles/-/blob/master/pica-metrologie/docker-compose.yml)) et via un fichier de règles.
 +
 +<bootnote web>
 +Le but de cette documentation n'est pas d'être exhaustif mais de donner une intuition. Voir la [documentation de vmalert](https://docs.victoriametrics.com/vmalert.html) pour un tour d'horizon de toutes les options. Le fichier de règles utilisé en production se trouve [ici](https://gitlab.utc.fr/picasoft/projets/dockerfiles/-/blob/master/pica-metrologie/vmalert-rules.yml).
 +</bootnote>
  
 ### Arguments de ligne de commande ### Arguments de ligne de commande
Ligne 15: Ligne 47:
 En ce qui nous concerne, les arguments essentiels sont : En ce qui nous concerne, les arguments essentiels sont :
  
-* `-datasource.url` : qui détermine à quelle adresse on va aller chercher les métriques sur lesquelles portent les règles. Typiquement, c'est l'adresse du conteneur Victoria Metrics dans le réseau Docker. +* `-datasource.url` : détermine à quelle adresse on va aller chercher les métriques sur lesquelles portent les règles. Typiquement, c'est l'adresse du conteneur Victoria Metrics dans le réseau Docker. 
-* `-remoteWrite.url` et `-remoteRead.url` : typiquement la même chose que `-datasource.url`. Permet de stocker +* `-remoteWrite.url` et `-remoteRead.url` : typiquement la même chose que `-datasource.url`. Permet de persister l'état des règles malgré un redémarrage de `vmalert`, qui ne garde les données qu'en mémoire vive. Or une règle a parfois besoin d'être évaluée positivement pendant 6 heures avant de lever une alerte, donc il est utile de garder trace des états précédents quelque part. 
 +* `-notifier.url` : l'adresse où envoyer les alertes pour traitement ultérieur, typiquement une instance d'[[technique:adminsys:monitoring:alerting:alertmanager|alertmanager]]. 
 +* `-rule` : le chemin vers le fichier de règles. 
 +* `-evaluationInterval` : l'intervalle par défaut entre l'évaluation des différentes règles. On conseille une durée faible (exemple `1m`) afin de détecter rapidement des défaillance critiques. 
 ### Exemple de règle ### Exemple de règle
  
-Prenons un cas simple. Pour chaque service, [[technique:adminsys:monitoring:metrologie:collect:blackbox|Blackbox exporter]] expose une métrique nommée `probe_success`, qui correspond +Prenons un cas simple. Pour chaque service, [[technique:adminsys:monitoring:metrologie:collect:blackbox|Blackbox exporter]] expose une métrique nommée `probe_success`, qui correspond à l'état de santé du service et vaut `0` s'il est *down* et `1` s'il est *up*. 
 + 
 +L'alerte correspondante sera : 
 + 
 +```yaml 
 +  - alert: EndpointDown 
 +    expr: probe_success == 0 
 +    for: "2m" 
 +    labels: 
 +      severity: critical 
 +    annotations: 
 +      summary: "Service down" 
 +      description: "{{ $labels.instance }} is down for more than 2 minutes" 
 +      # Redirect to HTTP or DNS dashboard based on vmagent job name 
 +      dashboard: '{{ if eq $labels.job "blackbox-http" -}}https://grafana.picasoft.net/d/8BOa8W47z/services-web?var-instance={{ $labels.instance }}{{- else if eq $labels.job "blackbox-dns" -}}https://grafana.picasoft.net/d/1twteMV7k/serveurs-dns?var-instance={{ $labels.instance }}{{- end -}}' 
 +``` 
 + 
 +- `alert` est le nom de l'alerte et doit être unique. 
 +- `expr` est la règle en elle-même, une condition sur une requête PromQL. Ici elle est simple et s'évalue positivement si `probe_success` est à 0. 
 +- `for` est la durée pendant laquelle la règle doit s'évaluer positivement pour déclencher une alerte. Ici, on considère qu'un service //down// pendant 2 minutes lève une alerte. 
 +- `labels` permet de rajouter des labels ou d'écraser des labels associés à la métrique qui seront envoyés à `alertmanager`. Pour connaître les labels associés à une métrique, voir [[technique:adminsys:monitoring:alerting:vmalert#exemple|cette section]]. Ici, on a choisi d'assigner une sévérité à l'alerte : `warning` ou `critical`, dépendant de l'urgence. 
 +- `annotations` permet de rajouter des méta-données décrivant l'alerte. On a choisi `summary`, qui donne une brève description de l'alerte, `description`, qui précise le problème et de quelle machine ou service il vient, et `dashboard`, un lien vers le dashboard [[technique:adminsys:monitoring:metrologie:grafana|Grafana]] pour visualiser le graphique correspondant à la métrique. 
 + 
 +<bootnote> 
 +Tous les labels associés à la métrique peuvent être utilisés dans les annotations avec la syntaxe `{{ $labels.nom_label }}`. L'utilité principale est d'ajouter le nom de l'instance concernée (`team.picasoft.net`, par exemple) dans le message de l'alerte pour le rendre plus explicite.</bootnote> 
 + 
 +<bootnote> 
 +Notez que l'expression pour `dashboard` est assez complexe. Elle utilise les [templates Go](https://pkg.go.dev/text/template) et se basent simplement sur une condition. Si le label `job` associé à la métrique est `blackbox-http`, alors c'est un service web qui est //down//, et on renvoie vers le dashboard Grafana des services webs. Si c'est `blackbox-dns`, il faut renvoyer vers le dashboard Grafana des serveurs DNS. 
 +</bootnote> 
 + 
 +### Écrire une nouvelle règle 
 + 
 +En général, on se basera sur des métriques qui ont déjà un dashboard Grafana, et on récupère la requête utilisée pour afficher les graphiques. 
 + 
 +#### Exemple 
 + 
 +<bootnote question> 
 +Comment lever une alerte quand un disque est trop rempli ? 
 +</bootnote> 
 + 
 +Tout ce qui concerne les disques, la mémoire, le CPU... est collecté grâce à [[technique:adminsys:monitoring:metrologie:collect:system_metrics|node_exporter]], et associé à [ce dashboard Grafana](https://grafana.picasoft.net/d/VIb73SGWa/server-overview). On trouve le graphe associé aux disques, et on clique sur `Edit`. 
 + 
 +{{ :technique:adminsys:monitoring:alerting:disk_usage_grafana.png |}} 
 + 
 +On trouve alors l'inspecteur de requêtes et la métrique associée au graphe :  
 + 
 +{{ :technique:adminsys:monitoring:alerting:disk_usage_query.png |}} 
 + 
 +En arrangeant la requête pour obtenir un pourcentage, ça nous donne :  
 + 
 +``` 
 +(1 - (node_filesystem_avail_bytes{fstype=~"ext."} / node_filesystem_size_bytes{fstype=~"ext."})) * 100 > 90 
 +``` 
 + 
 +Elle évalue le pourcentage d'espace occupé sur tous les systèmes de fichier de type `ext` (`ext2`, `ext4`...) et regarde s'il est supérieur à 90%. 
 + 
 +<bootnote>Tout ce qui se trouve entre accolades permet de filtrer sur les labels associés aux métriques, notamment avec des expressions régulières.</bootnote> 
 + 
 +On aimerait pouvoir envoyer une description du genre : 
 +, c'est à dire s'il reste moins de 10% d'espace libre. 
 +``` 
 +Le périphérique X monté sur le dossier Y est plein à Z% 
 +``` 
 + 
 +<bootnote question> 
 +Où trouver ces informations ? 
 +</bootnote> 
 + 
 +Question qu'on se pose très souvent pendant l'écriture d'une règle, et notamment de la description : quelles métadonnées ai-je à ma disposition pour décrire le mieux possible le problème ? Ce sont les labels qui portent ces métadonnées. Alors, quels sont les labels associés à une métrique particulière ? 
 + 
 +Deux manières de procéder. On peut utiliser l'inspecteur de métriques de Grafana et cliquer sur `Expand all` pour voir les labels renvoyées associées aux métriques : 
 + 
 +{{ :technique:adminsys:monitoring:alerting:disk_usage_query_inspector.png?600 |}} 
 + 
 +On voit ici qu'on a pas mal de labels : `device`, `mountpoint`, `fstype` (utilisé dans la requête), `instance`... De quoi décrire tout ce qu'on veut, donc. 
 + 
 +Cependant, il peut arriver qu'on écrive une requête assez différente de ce qu'on a sur le dashboard, ou on voudrait juste vérifier les labels associée à une métrique en particulier. 
 + 
 +Dans ce cas, on peut utiliser l'[API Prometheus](https://prometheus.io/docs/prometheus/latest/querying/api/) sur Victoria Metrics, avec laquelle elle est compatible. 
 + 
 +On se rend sur la machine où tourne Victoria Metrics, on rentre dans le conteneur : 
 + 
 +``` 
 +docker exec -it victoria-metrics sh 
 +``` 
 + 
 +Et on peut ensuite demander à chercher toutes les //timeseries// avec une certaine métrique, ou certains labels. Exemple : 
 + 
 +``` 
 +curl -s http://victoria-metrics:8428/api/v1/series --data-urlencode 'match[]=node_filesystem_avail_bytes' | jq 
 +``` 
 + 
 +Ici, on cherche toutes les //timeseries// associées à la métrique `node_filesystem_avail_bytes`. Extrait de réponse : 
 + 
 +```json 
 +
 +  "status": "success", 
 +  "data":
 +    { 
 +      "__name__": "node_filesystem_avail_bytes", 
 +      "job": "pica01", 
 +      "instance": "pica01", 
 +      "device": "/dev/mapper/vg00-data", 
 +      "fstype": "ext4", 
 +      "mountpoint": "/DATA/docker" 
 +    } 
 +  ] 
 +
 +``` 
 + 
 +On retrouve tous les labels disponibles. 
 + 
 +Les annotations pourront alors ressembler à : 
 + 
 +```yaml 
 +annotations: 
 +  summary: Disk 90% full on {{ $labels.instance }} 
 +  description: Device {{ $labels.device }} mounted on {{ $labels.mountpoint }} is {{ printf "%.0f" $value }}% full 
 +``` 
 + 
 +<bootnote>Remarquer l'utilisation de la fonction `printf` pour formater la valeur en enlevant les virgules, et de `$value` qui contient la valeur ayant fait évaluer la règle positivement.</bootnote> 
 + 
 +Ne reste plus qu'à ajouter le lien du dashboard Grafana, où on ajoutera une variable à l'URL pour filtrer directement par la machine concernée : 
 + 
 +```yaml 
 +dashboard: https://grafana.picasoft.net/d/VIb73SGWa/server-overview?var-node={{ $labels.instance }} 
 +``` 
 + 
 +<bootnote>Le nom de la variable (`var-node`) se déduit simplement en se rendant sur le dashboard, en changeant d'instance (`pica01`, `pica02`...) et en regardant l'URL, ou alors en se rendant dans la section `Variables` des paramètres du dashboard.</bootnote> 
 + 
 +#### Enrichir une métrique avec des métadonnées 
 + 
 +C'est un cas très spécifique mais qui peut rendre perplexe. Parfois, certaines métriques ne portent pas toutes les métadonnées qui les concernent, pour plusieurs [bonnes raisons](https://www.robustperception.io/target-labels-are-for-life-not-just-for-christmas) : notamment, ne pas dupliquer des informations sur les disques dans toutes les métriques concernant les disques. 
 + 
 +Par exemple, la métrique `pve_disk_usage_bytes`, de [[technique:adminsys:monitoring:metrologie:collect:proxmox_metrics|l'exporter Proxmox]], ne contient que quelques labels, par exemple : 
 + 
 +```json 
 +
 +  "__name__": "pve_disk_usage_bytes", 
 +  "job": "proxmox", 
 +  "instance": "alice.picasoft.net:9221", 
 +  "id": "storage/alice/save" 
 +
 +``` 
 + 
 +Or, pour notre message d'alerte, on aimerait bien savoir à quel [[technique:infrastructure:hyperviseurs:install_proxmox#configuration_du_stockage_proxmox|stockage Proxmox]] celui-ci correspond. 
 + 
 +<bootnote learn> 
 +La façon idiomatique de stocker des métadonnées associées à une métrique sans lui ajouter trop de labels est de créer une [pseudo-métrique](https://prometheus.io/docs/practices/naming/), suffixée par `_info`, et valant 1. De la sorte, on peut combiner les labels de la métrique dont la valeur nous intéresse avec les labels de la pseudo-métrique via une multiplication, qui ne change rien au résultat, puisque la pseudo-métrique vaut 1. 
 +</bootnote> 
 + 
 +Par exemple, pour Proxmox, la pseudo-métrique est `pve_storage_info`, dont voici un extrait : 
 + 
 +``` 
 +
 +  "__name__": "pve_storage_info", 
 +  "job": "proxmox", 
 +  "instance": "alice.picasoft.net:9221", 
 +  "node": "alice", 
 +  "id": "storage/alice/save", 
 +  "storage": "save" 
 +
 +``` 
 + 
 +On voit que cette métrique contient bien `storage`, le nom du stockage Proxmox. Voici une requête qui permet de combiner les deux :  
 + 
 +``` 
 +pve_disk_usage_bytes * on (id) group_left(storage) pve_storage_info 
 +``` 
 + 
 +On récupère la valeur de `pve_disk_usage_bytes` et on la multiplie par `pve_storage_info`, qui vaut 1. Entre les deux, l'opération ressemble à une jointure au sens SQL : 
 + 
 +* La clause `on(id)` va récupérer, pour chaque *timeserie* associée `pve_disk_usage_bytes`, la *timeserie* associée à `pve_storage_info` **dont le label `id` a la même valeur**. 
 +* Ensuite, la clause `group_left(storage)` va enrichir l'opérande de gauche (`pve_disk_usage_bytes`) de la valeur du label `storage` de l'opérande de droite (`pve_storage_info`). 
 + 
 +On se retrouve donc, à la fin de cette expression, avec un label `storage` utilisable pour la description de l'alerte. 
 + 
 +<bootnote warning> 
 +Si on avait essayé l'expression `pve_disk_usage_bytes * on (id) pve_storage_info`, le seul label qui aurait été conservé serait `id`. On a donc pas le choix que d'utiliser `group_left` pour enrichir les labels de l'opérande de gauche avec un ou plusieurs labels de l'opérande de gauche. 
 +</bootnote> 
 + 
 +<bootnote web> 
 +Plus d'explications et d'exemples en anglais [ici](https://www.robustperception.io/left-joins-in-promql). 
 +</bootnote>
  • technique/adminsys/monitoring/alerting/vmalert.txt
  • de ppom