Blog de dada

DevOps, bidouilleur et routard plein de logiciels libres

grafana

Si on regardait les bots des moteurs de recherche

Rédigé par dada / 08 février 2021 / 3 commentaires


Il y a un peu plus d'un an, je me suis amusé à comparer les moteurs de recherche en analysant leur capacité d'indexation sur mon blog. À l'époque, l'affaire de l'index de Qwant battait son plein : on se demandait qui étaient ces moteurs de recherche à l'indépendance douteuse.

Parler de moteur de recherche, qu'il soit éthique, écologique ou encore respectueux de la vie privée, c'est un foutoir sans nom. Notez que Lord s'est lancé dans la bataille et je vous invite à lire son billet. Il a pris le temps de vous expliquer en quoi on se fait toutes et tous avoir, plus ou moins.

Bref, ici, j'ai envie de vous partager le fruit d'une partie de mon travail en vous montrant la fréquence de passage des robots des différents moteurs de recherche. Oui, je mets en place des machins qui dépiautent les logs dans tous les sens possibles. Mais jamais pour un usage commercial !

Méthode : J'ai lancé une requête simple dans Grafana/Loki qui remonte les occurrences des différents bots dans les logs d'accès à mon blog tout le long du mois de janvier, avec un maximum de 5 000 requêtes*.
Note : L'intégration des images dans PluXml n'est pas parfaite, du coup, pensez à les clic droit Afficher l'image.
Note 2 : Les échelles sont différentes en fonction des graphiques. Oui, je sais, c'est pas top !

Duckduckgo


Ce moteur de recherche** n'est passé que deux fois me faire des coucous. Deux fois assez terribles puisqu'on remarque 2 pics d'un peu plus de 250 requêtes en quelques secondes.
En regardant ce qu'il a récupéré, je peux vous dire que ce n'est pas jojo : ça ne concerne que le thème de ce site.

Qwant



Avec le champion européen, on se rend compte qu'il bosse un peu plus que DDG. J'ai 2154 requêtes (avec un pic à 542 !) espacées de plusieurs jours. C'est un peu mieux au niveau de la diversité des infos relevées : Qwantify s'est promené un peu partout dans les articles, les images et même les flux RSS des commentaires.

Bing



Avec Bing, on arrive à ce que j'imagine être la quantité de travail d'un moteur de recherche. On est entre 30 et 100 requêtes par jour, tous les jours. C'est clairement trop pour mon petit site qui n'est pas mis à jour aussi souvent. Pour un site professionnel, ou un machin à buzz type Ouest-France ou 20Minutes, ça doit être important.

Mojeek



Je dois avouer que je ne pensais pas le trouver, ce nouveau moteur de recherche britannique. Il passe de temps en temps, principalement pour analyser mon robots.txt ! Bon, il se veut écolo, respectueux de la vie privée et surtout très jeune. En poussant un peu mes recherches, j'ai découvert qu'il était passé chez moi pour la première fois le 22 août 2020.

Google


Le Patron : le GoogleBot. Je suis surpris de ne pas le voir plus tranchant que le robot de Bing. C'est pas flagrant : les deux touchent les limites de mon test : 5000 requêtes. Comme pour Bing, quel est l'intérêt de passer si souvent ? Mystère.

Comparaison

En plus du graphique ci-dessous, je vous offre un instantané plus joli pour mettre tout ça en perceptive.

Conclusion

Non, pas de conclusion. Ce que je vous montre n'est qu'un coup d’œil à un instant donné. Comme il est impossible de savoir vraiment ce qui peut déclencher le retour d'un bot sur tel ou tel site, il est impossible de comprendre la fréquence de passage d'un bot. Ici, je me fends d'un billet une ou deux fois par mois : autant dire qu'un passage par mois est largement suffisant pour indexer tout le contenu. Rien ne justifie 30 ou 200 requêtes par jour.

Enfin voilà, des bisous



* Pourquoi un maximum de 5 000 ? Parce que Googlebot.
** Pas vraiment, mais bon.

De l'alerting à base de logs v2

Rédigé par dada / 06 novembre 2020 / Aucun commentaire



À l'époque, mi-février 2020, je découvrais les pipelines de Promtail, une façon rudimentaire de parcourir des logs, d'y chercher ce qu'on veut et de déclencher une alerte si besoin. C'était ma v1 de l'alerting à base de logs.
Dans les faits, ça marche bien, mais ce n'est pas vraiment simple à mettre en place et ça demande des bidouilles pas possible quand on commence à vouloir trifouiller dans des choses plus complexes, comme Docker.

Il y a quelques semaines, j'ai découvert qu'il y avait un moyen encore plus simple et mieux intégré pour faire de l'alerting avec Grafana / Loki / Promtail : Loki lui-même.

Configurer Loki comme Datasource de type Prometheus

Si vous avez l'habitude de jongler avec toute cette stack, le titre de cette partie devrait vous faire tilter. C'est pourtant ce qu'il faut faire : pour Grafana, Loki va se la jouer Prometheus.


En version texte :
  • Name : ce que vous voulez
  • URL : http://localhost:3100/loki
Dans la partie Explore de Grafana, vous deviez maintenant avec PromLoki comme Datasource :


Et c'est à partir de maintenant qu'on peut commencer à jouer !

Créer un panel lié à une alerte

On va s'amuser à créer un panel pour analyser les logs qui nous intéressent.

Notez qu'on a bien choisi PromLoki comme datasource.


Dans mon exemple, ce sont les logs de Pixelfed que je veux parcourir pour pouvoir agir en cas de production.ERROR :
count_over_time(({hostname="pixelfed"} |= "production.ERROR")[1m])
Maintenant qu'on sait ce qu'on cherche, on va configurer les règles qui déclencheront les alertes.


Dans les Rules :
- Choisissez un nom.
- On évalue toute le 10s

Dans les conditions :
- When : on fait la moyenne en choisissant avg()
- Of : cliquez sur les variables entre les virgules pour préciser vos réglages
- Above : ici, j'attends plus de 3 occurrences pour déclencher une alerte

Si vous avez le coup d’œil, vous avez remarquez que les deux captures d'écran présentées ci-dessus ont une ligne rouge : c'est la limite de tolérance de l'alerte. En dessous, tout va bien, au dessus, c'est la fin du monde.

Recevoir les alertes

Maintenant que vous avez la possibilité de déclencher alertes, il faut les recevoir d'une façon ou d'une autre. Grafana peut se brancher à un paquet d'outil, de Telegram à Elements en passant par Discord et l'Alert Manager de Prometheus voire Grafana llui-même: faites votre choix !


Perso, je me sers de mon AlertManager, il me noie sous les mails en cas de souci et c'est très bien comme ça !


De l'alerting à base de logs

Rédigé par dada / 12 février 2020 / 2 commentaires


Cela fait un moment que je cherche un moyen de déclencher des alertes à partir d'erreurs spécifiques dans les logs. En fait, ça fait depuis la sortie de Loki que j'en rêve.



Pour rappel, le couple Loki/Promtail, permet de centraliser des logs dans Grafana pour les visualiser calmement plus tard. En gros, ça peut donner un truc comme ça, ou comme ça.
Après avoir mis tout ça en place, je trouvais dommage de ne pas pouvoir continuer l'intégration jusqu'au bout : repérer un message d'erreur dans des logs et transformer l'écran de monitoring en sapin de Noël.

En fait, c'était déjà possible, j'avais juste raté l'information !

Préambule

Ce dont je vais parler dans la suite du billet nécessite d'avoir déjà la stack Loki + Promtail + Grafana + Prometheus + Alert-manager. Ça demande un peu d'huile de coude et de temps mais ça s'installe très bien.

Les Pipelines

Promtail, comme tout exporter, expose des metrics de toute sorte. De base, il fait des choses simples, mais avec les Pipelines, on peut pousser le truc plus loin : ajouter le timestanp à une ligne de log, modifier des labels, ajouter clairement le numéro de ligne du log et, on y est, créer une metric custom !

Créer une metric custom

On va commencer par un exemple très simple :
scrape_configs:
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs
      __path__: /var/log/*log
      hostname: diaspodon.fr
  pipeline_stages:
  - match:
      selector: '{job="varlogs"}'
      stages:
      - regex:
          expression: ".*(?P<error_message>error_message.*)"
      - metrics:
          error_total:
            type: Counter
            description: "total count of errors"
            source: error_message
            config:
              action: inc
Ceci est une partie de la configuration du Promtail en place sur mon serveur Mastodon. Ce n'est pas la plus propre du monde mais ça fera l'affaire.

Le job

On y voit la configuration qui permet de remonter les logs système de /var/log/*.log avec le label varlogs et un hostname forcé :
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs
      __path__: /var/log/*log
      hostname: diaspodon.fr

Le pipeline

On enchaîne ensuite avec le fameux pipeline, que je vais présenter en deux parties : le selector et les metrics 

- La partie selector
  pipeline_stages:
  - match:
      selector: '{job="varlogs"}'
      stages:
      - regex:
          expression: ".*(?P<error_message>error_message.*)"
Le selector permet de s'y retrouver. On va aller chercher à bidouiller les logs du job varlogs, pas ailleurs. Le stage permet de mettre en place une expression régulière en RE2, la version Google est regexp, pour filtrer l'information dont on a besoin.
Ici, je veux qu'une action soit déclenchée à chaque fois que error_message apparaît dans les logs. Celles et ceux qui ont une instance Mastodon savent de quoi je parle. Pour les autres, c'est quand un message ne peut pas atteindre son destinataire. C'est très courant.

- La partie metrics

Pour finir, la partie metrics est carrément celle qui nous intéresse le plus : elle va, comme son nom l'indique, créer une metric qui sera remontée à Prometheus.
      - metrics:
          error_total:
            type: Counter
            description: "total count of errors"
            source: error_message
            config:
              action: inc
On va lire la configuration lentement : La variable error_total sera de type Counter avec la description "total count of errors" et sera alimentée par error_message, défini dans la regexp précédente (entre les <>). De 0, la variable sera incrémentée de 1 à chaque match.

Prometheus

Vérifier la configuration

Vous voyez le truc ? On vient de mettre en place une metric custom qui sera remontée par Promtail vers Prometheus. À l'heure où j'écris ces lignes, cette metric ressemble à ça :
root@diaspodon ~ # curl -s http://localhost:9080/metrics   | grep custom
# HELP promtail_custom_error_total total count of errors
# TYPE promtail_custom_error_total counter
promtail_custom_error_total{filename="/var/log/daemon.log",hostname="diaspodon.fr",job="varlogs"} 92831
promtail_custom_error_total{filename="/var/log/syslog",hostname="diaspodon.fr",job="varlogs"} 50050
On retrouve bien la metric déclarée dans Promtail : error_total, avec son nom complet : promtail_custom_error_total.

Vous me direz que ce n'est pas très joli et vous aurez parfaitement raison. C'est un exemple, juste un exemple !

Mettre en place de l'alerting

Maintenant que vous avez des données dans Prometheus, rédiger une règle d'alerting est assez simple. On devrait s'en sortir avec ce type de chose :
  - alert: Error_total
    expr: promtail_custom_error_total > 1
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "Instance {{ $labels.instance }} is invaded by custom errors!"
Simple, rapide, efficace. Si une erreur apparaît, elle sera repérée et une alerte sera déclenchée. Y'a plus qu'à faut qu'on vérifier que votre installation spamme correctement les développeurs pour les mettre sur le coup rapidement.

Pour aller plus loin

Je viens de rapidement parcourir le sujet pour vous donner envie d'y mettre le nez. En l'état, la configuration proposée a un gros problème : une fois qu'une erreur est détectée, le Counter sera incrémenté et rien ne lui permettre de revenir à 0. C'est assez chiant.

J'ai deux façons de contourner le problème : la première avec les développeurs, la deuxième avec ses seuls moyens.

Si les développeurs sont adorables, ils peuvent mettre en place un petit bout de code qui va écrire dans les logs que tout est revenu à la normale. En passant du Counter à une Gauge, on peut dire à Promtail d'incrémenter la metric quand un souci est détecté puis de la décrémenter quand tout redevient fonctionnel. Ça permet de jongler entre 0 et 1 et pas plus.

Par contre, si vous êtes tout seul, vous pouvez tricher en décidant de mettre en place une règle d'alerting qui fait un rate() sur 1h, ou la durée que vous voulez, pour avoir des passages à vide et des périodes de souci. Ça permet d'éviter de passer d'un Counter à une Gauge mais ça demande à mettre un délai de retour au calme long et d'être assidu sur les chan/salon/mail d'alerting.

Bref, c'est encore un point sur lequel je réfléchis. Si vous avez des idées, je prends.

Enfin voilà.

Des bisous

Loki : jouer avec ses logs dans Grafana

Rédigé par dada / 18 juin 2019 / 7 commentaires



Le 3 juin dernier est sortie la première version beta de Loki : la v0.1.0. J'attendais cette première version depuis un bon moment ! Depuis le FOSDEM, pour être précis. Grand fan de la stack Prometheus / Grafana, je bavais d'impatience de pouvoir mettre les mains dans un système d'agrégation de logs directement dans Grafana. On y est alors regardons comment ça se passe !

Loki

Loki se comporte comme Prometheus : c'est un logiciel que vous allez installer sur votre machine qui sert pour le monitoring de votre infrastructure et le laisser vivre sa vie. Comme son mentor, ou presque, il va falloir lui associer des exporters pour le gaver de données : Promtail.

Installation

Pour le moment, je me sers de Loki dans un conteneur docker, parce que c'est marrant et parce que voilà. Pour le faire tourner comme j'en ai envie, j'ai besoin de deux fichiers :

- le Dockerfile
FROM grafana/loki

COPY local-config.yaml /etc/loki/local-config.yaml

CMD ["/bin/loki", "-config.file=/etc/loki/local-config.yaml"]
- Les conf dans local-config.yaml :
auth_enabled: false

server:
  http_listen_port: 3100

ingester:
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
  chunk_idle_period: 15m

schema_config:
  configs:
  - from: 2018-04-15
    store: boltdb
    object_store: filesystem
    schema: v9
    index:
      prefix: index_
      period: 168h

storage_config:
  boltdb:
    directory: /tmp/loki/index

  filesystem:
    directory: /tmp/loki/chunks

limits_config:
  enforce_metric_name: false
  reject_old_samples: true
  reject_old_samples_max_age: 168h

chunk_store_config:
  max_look_back_period: 0

table_manager:
  chunk_tables_provisioning:
    inactive_read_throughput: 0
    inactive_write_throughput: 0
    provisioned_read_throughput: 0
    provisioned_write_throughput: 0
  index_tables_provisioning:
    inactive_read_throughput: 0
    inactive_write_throughput: 0
    provisioned_read_throughput: 0
    provisioned_write_throughput: 0
  retention_deletes_enabled: false
  retention_period: 0

Il n'y a pas grand-chose à raconter sur ces deux fichiers. J'ai volontairement réduit le Dockerfile au strict minimum puisque je ne m'en sers que pour copier la configuration de Loki directement dans le conteneur, histoire de réduire la liste des paramètres à son lancement.

Exécution

Pour lancer Loki, on va taper ça dans son terminal :
docker run -d -p 3100:3100 loki
Si tout s'est bien passé, vous devriez avoir un conteneur qui vous répond des politesses :
root@monito:~# curl 127.0.0.1:3100
404 page not found
C'est normal. Par contre, si vous avez autre chose, c'est pas normal.

Maintenant que Loki tourne comme un grand, il faut bien comprendre qu'il ne sert à rien sans son comparse Promtail.

Promtail

Installation

Pour installer Promtail, on va faire exactement comme avec Loki : un conteneur simple avec un peu plus de paramètres au lancement.

- Le Dockerfile :
FROM grafana/promtail

COPY docker-config.yaml /etc/promtail/docker-config.yaml

ENTRYPOINT ["/usr/bin/promtail", "-config.file=/etc/promtail/docker-config.yaml"]
- La conf dans docker-config.yaml :
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://IP_SRV_LOKI:3100/api/prom/push

scrape_configs:
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs
      __path__: /var/log/*log
Si vous avez le coup d’œil, vous devriez avoir remarqué que cette configuration ressemble furieusement à celle de Prometheus : surtout la partie scrape_configs. On y retrouve la conf des jobs, les targets, labels, etc.
Remarquez qu'ici, vous devez remplacer IP_SRV_LOKI par l'IP du serveur sur lequel vous avez effectivement lancé Loki.
Ici, Promtail va aller gratter tous les fichiers locaux se terminant par log dans le répertoire /var/log/ le tout en les classant dans le job system avec le label varlogs.
Locaux, vous dites ? Mais nous sommes dans un conteneur : par quelle magie est-ce possible ? En jonglant avec les volumes !

Exécution

On build le conteneur :
docker build -t promtail .
Dans ce cas simple, on peut lancer Promtail comme ceci :
docker run -d -p 9095:9095  -v /var/log:/var/log promtail
Voyez qu'on monte les logs locaux de la machine dans le conteneur, les rendant accessibles à Promtail. N'hésitez pas à jouer de exec -it pour vérifier qu'ils sont bien là.

On se retrouve avec un Loki capable d'être gavé et d'un Promtail qui, pour le coup, gave Loki. Chouette.

Grafana

Maintenant que les bases sont en place, allons dire à Grafana de nous afficher tout ça. Si, comme moi, Grafana tourne sur la même machine que Loki, ça va être facile. Il faut ajouter un nouveau Data Source local : http://localhost:3100.

Une fois que c'est fait, foncez jouer dans la rubrique Explore et faites votre sélection ! Bon, pour le moment, vous n'avez que les logs system d'une seule machine, mais c'est déjà ça. Si je vous montre le graphique des logs Nginx de ma machine principale, vous avez ce genre de chose :


Si vous affichez cette capture d'écran en grand, vous devriez bien remarquer le manque de sérieux dans quelques-unes de mes configurations (rien de grave, rassurez-vous). On y voit du gris, du vert et du rouge.

Non, vous n'aurez pas les logs à proprement parler mais faites moi confiance, ils s'entassent en dessous.

L'affichage des logs est manipulable avec le Log Stream Selector. Ce machin permet de filtrer l'affichage simplement. Dans mon exemple, remarquez que je sélectionne le job nginxlogs et le hostname de ma machine.
Vous pouvez aussi filtrer le contenu même des logs, le texte en gros, mais je vais vous laisser chercher par vous-même.

Si vous avez vraiment le coup d’œil, dans la configuration de Promtail que je vous propose juste au dessus, il n'y a pas de hostname, ni de log Nginx d'ailleurs.

Pour que ça marche chez vous, vous devez déjà monter le répertoire de log de Nginx dans le conteneur et utiliser cette configuration :
- job_name: nginx
  static_configs:
  - targets:
      - localhost
    labels:
      job: nginxlogs
      __path__: /var/log/nginx/*log
      hostname: b2d
Vous pouvez l'ajouter à la suite de ce que je propose déjà, ça vous fera déjà plus de logs à parcourir !

Bref. Afficher des logs dans Grafana, c'est chouette, mais Loki ne permet heureusement pas que ça sinon il n'y aurait aucun intérêt à parler d'un truc pas encore terminé.

Loki et Prometheus

Avoir un Loki en parallèle d'un Prometheus, ça permet de coupler la puissance des exporters Prometheus avec les logs pompés par Loki. Et ça, c'est beau ! Comment ? En cliquant sur "split" pour partager l'écran de Grafana en choisissant Loki d'un côté et Prometheus de l'autre.

En image ça donne quelque chose comme ça :


Ce qu'on y voit ? La corrélation entre les logs Nginx et le load de la machine. Bon, certes, ce n'est pas foufou mais je n'avais pas d'exemple super pertinent à vous montrer. Quoi qu'il en soit, cette combinaison Loki/Prometheus vous permet de mettre en image ce que vous voulez et ainsi réagir comme il faut, le tout avec un peu de PromQL et des filtres.

Deux yeux, un affichage unifié, c'est franchement cool. Et je ne vous parle pas encore de l'extase si vous avez bien fait l'effort de faire correspondre les labels entre les deux outils...!

Perso, je trouve ça absolument génial et j'ai hâte de continuer à approfondir ma maîtrise de ces beautés !

Astuces du dimanche #6

Rédigé par dada / 06 janvier 2019 / Aucun commentaire


Ça faisait longtemps que je n'avais pas fait de ADD. En voici une très orienté Kubernetes.

Grafana

Vous avez installé le Prometheus Operator et vous ne savez pas où est passé le traditionnel couple utilisateur/mot de passe admin/admin ? L'info est ici : l'utilisateur est bien admin, mais le mot de passe est prom-operator.

Rook

Impossible de mettre la main sur le Dashboard ? La configuration a changé avec la version 0.9 : tout est ici.
Votre cluster hurle à coup de HEALTH_ERR ? Toujours à cause de la 0.9, deux modules sont en erreur : l'issue est ici. Rien de grave, le cluster tourne bien malgré les alertes. Les manipulations pour corriger le tir sont décrites par là.

Version de Docker

Les versions de docker se suivent et ne sont pas toujours compatibles avec ce que demande Kubernetes, pour installer une version précise :
export VERSION=18.03 && curl -sSL get.docker.com | sh
Prenez le temps de bien supprimer/purger l'ancienne version de docker avant de lancer la commande et d'installer Git. Notez aussi que ça vous empêchera d'utiliser le bon vieux couple "apt update && apt upgrade".

Init d'un Cluster k8s

Si vous installez un master sur un serveur n'ayant qu'un seul CPU, ignorez l'erreur avec :
--ignore-preflight-errors=NumCPU
Si vous voulez forcer l'API à utiliser un réseau spécifique, genre un réseau privé basé sur, disons, WireGuard :
--apiserver-advertise-address="10.0.42.1"
Où 10.0.42.1 est l'IP de l'interface VPN de votre Master.

Méfiez-vous des Resources

Utiliser Kubernetes sur des petits serveurs comme ceux que j'utilise chez Hetzner peut vous pousser à mettre en place des limitations de ressources sur vos conteneurs. Dans mon cas très particulier, où je suis quasiment le seul utilisateur, il est plus efficace de ne pas limiter les conteneurs, quitte à les voir éclater le CPU pendant quelques secondes. Avec des limitations, j'ai réussi à monter à plus de 200 de load pour 2 CPU. Voilà.