Journal présentation de fuse_kafka, un agent de logging pour kafka fondé sur FUSE

Posté par  (site web personnel) . Licence CC By‑SA.
18
2
déc.
2014

Cher journal,

Je voudrais te présenter le logiciel que je développe en ce moment, à savoir fuse_kafka.
Il s'agit d'un agent de logging: il a pour but de permettre la centralisation de logs hétérogènes.
Il se fonde sur FUSE pour récupérer les écritures dans des fichiers dans des répertoires surveillés
et envoyer ces dernières dans la file de message kafka, dans un format fondé sur celui du système de gestion de log logstash.

fuse kafka

Démo

Voici une session terminal (ttyrec) montrant le système en fonctionnement:

Les dépendances

Kafka

Kafka permet de mettre en place des files de messages distribuées à fort débit.
Il écrit les messages de manière séquentielle sur disque et profite donc des optimisations du pagecache de l'OS.
Il utilise aussi sendfile pour copier directement le contenu du pagecache vers des sockets
(évitant ainsi des copies et commutations espace utilisateur / espace noyau inutiles).

FUSE

FUSE permet d'écrire ses propres systèmes de fichiers pour Linux, et ce dans un processus en espace utilisateur.
Voici le détail de son fonctionnement.

Logstash

Logstash permet de centraliser et de traiter des logs.
Il est facilement installable et extensible grace à jruby.
Ce n'est pas une dépendance directe de fuse_kafka,
mais ce dernier enregistre dans kafka les logs dans un format proche de celui de logstash.

Fonctionnement

Voici un graphique qui résume le fonctionnement global:

fuse kafka

Grâce à FUSE, le logiciel écoute les appels au système de fichier sur des répertoires bien définis.
fuse_kafka fonctionne en overlay, c'est à dire que le driver FUSE retransmet les appels au
système de fichier sous-jacent: quand vous accédez à des fichiers dans un répertoire géré,
vous accédez aussi vraiment au disque.
Les appels systèmes d'écriture, quand à eux sont transmis à kafka, avec des méta-données.

Exemple d'événement écrit dans kafka

Le événements sont écrits dans kafka sous format JSON/logstash, par exemple:

    { /* chemin du fichier où l'écriture a eu lieu */
     "path": "/var/log/redis_6380.log", 
     /* identifiant du processus ayant fait l'écriture */
     "pid": 1262,
     /* identifiants utilisateurs et groupes effectifs ayant fait l'écriture */
     "uid": 0, "gid": 0,
     /* contenu de l'écriture en base64, ici "hello world" */
     "@message": "aGVsbG8gd29ybGQ=",
     /* date de l'écriture */
     "@timestamp": "2014-09-11T14:19:09.000+0000",
     /* utilisateurs et groupes effectifs ayant fait l'écriture */
     "user": "root", "group": "root",
     /* commande ayant fait l'écriture */
     "command": "L3Vzci9sb2NhbC9iaW4vcmVkaXMtc2VydmVyIC",
     /* version de l'agent de logging */
     "@version": "0.1.3",
     /* champs définis lors du lancement de fuse kafka permettant
       de rajouter des meta données */
     "@fields": {
         "first_field": "first_value",
         "second_field": "second_value" },
     /* tags définis au lancement de fuse kafka permettant
       de rajouter des méta données */
     "@tags": ["mytag"]
    }

Système de quota

Il est possible de définir un quota (nombre d'octet par seconde) tel que si ce dernier est dépassé par un fichier,
L'écriture n'est pas transmise à kafka.
Cela permet de ne pas transférer des grosses écritures telles que faites sur
des fichiers comme des core dumps ou des rotations de logs.

Performances

L'écriture dans kafka est faite de manière asynchrone grace à librdkafka.
Néanmoins, FUSE ajoute nombre de commutations entre espace utilisateur et espace kernel,
ce qui ralenti les appels systèmes d'accès disques,
voilà pourquoi ce système ne devrait pas être utilisé pour les applications nécessitant un fort débit.
Des benchmarks sont disponibles ici.

Intérêts

Je vois plusieurs intérêts à cette approche:

  • Ce système permet de récupérer les traces de logiciels différents, n'utilisant pas le même système de logging, (tant que leurs logs se retrouvent dans des fichiers).
  • Il permet de récupérer des métadonnées intéressantes, telles que l'utilisateur, la ligne de commande ayant produit la trace.
  • les événements générés contiennent la date d'écriture effective, le système de centralisation de logs n'a donc pas à parser les logs à la recherche de cette information.
  • Le fait d'utiliser un format de type logstash permet de pouvoir profiter des nombreuses fonctionnalités de ce dernier.
  • # inotify

    Posté par  (site web personnel) . Évalué à 3.

    On a eu une dépêche il y a quelques jours sur inotify, du coup je me demande si ce mécanisme n'aurait pas été suffisant (au lieu de fuse). Ça serait sûrement plus performant, par contre il y a peut être moins de métadonnées accessibles.

    Il existe deux catégories de gens : ceux qui divisent les gens en deux catégories et les autres.

    • [^] # Re: inotify

      Posté par  . Évalué à 4.

      Non seulement avec inotify il y aurait moins de meta-données disponibles (pas de connaissance du process qui écrit les logs, ni du user/group de ce process), mais surtout avec fuse_kafka il est envisageable de proposer une petite évolution pour que les logs interceptées ne soient plus écrites sur le système de fichiers local:

      1. Pour éviter le remplissage des disques par les X applications pour lesquels la rotation des logs a été oubliée ou est faite mais sans taille max des logs tournées… grand classique des pannes pour qui fait de la production!
      2. Pour sécuriser les machines et le contenu des applications, car les logs contiennent souvent des traces sur des données (voire au pire, des mots de passe… déjà vu!) qui devraient rester confinées dans des stockages sécurisés / situés sur un réseau distinct de celui des machines accessible depuis Internet.

      Un système d'interception des logs basé sur inotify ne pourrait pas empêcher l'écriture sur les système de fichiers, à moins que je n'ai raté quelque-chose ?

      Al3x

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.