Gestion des logs avec Logstash, ElasticSearch & Kibana

Posté par . Édité par yannig, rogo, palm123, Benoît Sibaud, NeoX, Benoît et eMerzh. Modéré par Xavier Claude. Licence CC by-sa
30
29
sept.
2013
Supervision

Tout bon administrateur a un jour dû chercher une info à coup de grep, tail, awk dans les fichiers de logs des équipements qu'il gère.
Or la recherche est toujours un peu fastidieuse, avec les questions qui reviennent : "Où est-ce qu'ils sont ces logs ?", "Et c'est quoi le format déjà ?", "Tu connais le mot de passe pour se connecter sur le routeur ?".

Si on peut mettre en place une récupération des logs de façon centralisée avec des outils connus comme syslog, le trio Logstash, ElasticSearch et Kibana est un très bon candidat pour gérer et trouver efficacement des informations dans les milliers de lignes de traces que peuvent générer les divers services.

Sommaire

Présentation des logiciels

Logstash

Logstash est un outil de collecte, analyse et stockage de logs. Aujourd'hui en version 1.2.1, il est développé en Java, sous licence Apache 2.0.

Pour la collecte, il sait gérer plus d'une trentaine d'événements. Un événement peut être un message syslog, un mail via le protocole IMAP, un tweet ou encore une commande IRC.

Il va ensuite analyser ces événements, et les mettre en forme à l'aide de filtres. Il existe également une vingtaine de filtres : standardisation de la date, découpage du message, structuration du message via grok.
Après filtrage, on obtient un message relativement clair, avec des couples clé-valeur que l'on pourra exploiter plus tard.

Enfin, il exporte ces données, traitées ou non, sous divers formats : email, sortie standard, fichier texte, alarme Nagios, entrée en base de données ElasticSearch.

Ainsi, on peut très bien traiter plusieurs flux de logs différents, appliquer un filtre à chacun pour harmoniser le tout, et les stocker correctement.

ElasticSearch

ElasticSearch est un moteur de recherche distribué, intégrant une base de données NoSQL, et RESTful, basé sur le moteur Apache Lucene.

La société ElasticSearch derrière le produit éponyme, est d’ailleurs l'employeur actuel du créateur de Logstash et de Kibana.

Kibana

Kibana est une interface web permettant de rechercher des infos stockées par Logstash dans ElasticSearch

Dans la seconde partie de la dépêche, nous reviendrons sur les fonctionnalités de ces 3 outils, avec un exemple de déploiement et utilisation.

Mise en place

Premiers pas avec logstash

Même si logstash est fait pour fonctionner sur un environnement distribué, il peut très bien s'utiliser sur une machine seule. Autre point de détail intéressant, le jar de logstash embarque une version d'ElasticSearch ainsi que Kibana.

Nous allons donc voir un premier exemple qui prendra le contenu des fichiers de log se trouvant dans le répertoire /var/log pour l'insérer directement dans une instance ElasticSearch.

Première chose, il nous faut un fichier logstash.conf avec le contenu suivant :

input {
  file {
    'exclude' => ['*.gz']
    'path' => ['/var/log/*.log']
    'type' => 'system logs'
  }
}
output {
  elasticsearch {
    embedded => true
  }
}

Téléchargeons la dernière version de logstash à l'emplacement suivant : http://logstash.net/ (version 1.2.1 au moment de la rédaction de cet article).

Il nous faut ensuite démarrer logstash avec la ligne de commande suivante :

java -jar logstash-1.2.1-flatjar.jar agent -f logstash.conf

Vous pouvez maintenant interroger votre instance ElasticSearch pour voir comment se porte tout ce petit monde :

curl http://localhost:9200/_status?pretty=true

Cette commande devrait vous renvoyer une longue liste au format JSON sur l'état de fonctionnement du moteur ElasticSearch (ici embarqué) :

{
  "ok" : true,
  "_shards" : {
    "total" : 10,
    "successful" : 5,
    "failed" : 0
  },
...
}

Afin de rendre la manipulation de tout ceci plus simple, nous allons activer Kibana. Pour cela, il suffit d'ajouter quelques options. La ligne de commande devrait maintenant ressembler à ça :

java -Xmx128M -jar logstash-1.2.1-flatjar.jar agent -f logstash.conf -- web

Lançons maintenant un navigateur et pointons sur l'adresse de cette interface (http://nomserveur:9292). Vous devriez voir apparaître l'interface de Kibana 3.

Alimentons maintenant un fichier avec un contenu quelconque :

echo une ligne > /var/log/unfichier.log

Si nous lançons maintenant une recherche sur le mot ligne, merveille des merveilles, Kibana nous la renvoie.

Couplage avec un ElasticSearch externe

Dans ce qui a précédé, nous avons vu comment utiliser Kibana et le moteur ElasticSearch embarqué dans le jar de logstash. Nous allons maintenant voir comment faire pour centraliser nos événements dans une seule instance ElasticSearch et pour cela, nous allons en démarrer une.

Pour cela, rien de bien compliqué, récupérer l'archive d'ElasticSearch et de la décompresser (version 0.90.3 téléchargeable à l'adresse suivante : http://www.elasticsearch.org/download/) :

tar xfv ~/elasticsearch-0.90.3.tar.gz

Jetons rapidement un coup d'œil au fichier elasticsearch-0.90.2/config/elasticsearch.yml. Pas grand chose à signaler puisque les valeurs par défaut devraient nous suffire. Notons toutefois qu'il est possible de spécifier un nom de cluster avec l'option cluster.name (dans le cas où nous voudrions augmenter le niveau de résilience et/ou de performance de notre moteur ElasticSearch) ainsi que le nom de notre nœud avec l'option node.name (par défaut, ce dernier prendra un nom aléatoire de super héros comics). A noter qu'il existe d'autres options pour spécifier le rôle qu'occupera le nœud courant dans le cluster (passif, répartiteur de requête etc.).

Une fois nos options passées en revue, lançons notre moteur avec la commande suivante :

cd ~/elasticsearch-0.90.2/bin
./elasticsearch -f

NB : Ici, nous lancerons ElasticSearch en mode bloqué. Si vous voulez laisser le démon tourner en arrière plan, il vous suffit de supprimer l'option -f.

Modifions maintenant notre fichier logstash.conf afin de faire référence à notre moteur ElasticSearch :

input {
  file {
    'exclude' => ['*.gz']
    'path' => ['/var/log/*.log']
    'type' => 'system logs'
  }
}
output {
  elasticsearch {
    bind_host => "mon-serveur-elasticsearch"
    cluster => "mon-cluster-elasticsearch"
    port => 9300
  }
}

Un arrêt/relance de logstash plus tard, voici notre moteur ElasticSearch en place. Il est possible d'y accéder au travers l'URL http://mon-serveur-elasticsearch:9300

Passons maintenant à la mise en place de l'interface Kibana.

Mise en place de Kibana

À noter que nous allons procéder à l'installation de la version 3 de Kibana qui n'est pas encore sortie mais qui apporte énormément de nouveautés.

Le côté innovant de cette interface est surtout qu'elle est écrite en javascript pur et ne fait appel à aucun langage comme Ruby, PHP ou autre Python. Ici, il suffit de disposer d'un espace de stockage quelconque accessible via un serveur Web (Apache, nginx), décompresser l'archive de Kibana, éditer votre fichier config.js (afin de pointer sur votre moteur ElasticSearch), y accéder au travers un navigateur et voilà !

Dans mon cas, j'utilise une instance Apache (sous RHEL/CentOS) et l'installation se fait de la manière suivante :

cd /var/www/html
tar xfv ~/kibana-master.tar.gz
mv kibana-master kibana3

A noter que la valeur présente dans le fichier config.js est par défaut la bonne ("http://"+window.location.hostname+":9200") si votre serveur apache est sur le même serveur que le moteur ElasticSearch.

Il suffit maintenant de se rendre sur l'adresse suivante : http://mon-serveur-apache/kibana3/ pour pouvoir commencer à travailler.

Attention ! Cette interface est très moderne et réclame un navigateur web moderne. Je ne parle même pas de problème avec le moteur IE puisque j'ai même rencontré des soucis avec des versions de Firefox un peu vieilles (version 10, ne me demandez pas pourquoi, je ne suis pas au service de déploiement des packages bureautiques). Pour ma part, j'utilise la dernière version de Chrome.

Par défaut, vous tomberez sur une interface de présentation de Kibana. Comme je pense que le blabla ne devrait pas trop vous intéresser, je vous invite à cliquer sur le lien Sample Dashboard en bas du texte à droite de la page.

De là, vous pourrez personnaliser votre requête afin d'en faire le tableau de bord que vous voudrez. Une fois que vous serez content de votre résultat et surtout afin de briller en société, vous pourrez soit :

  • Exporter votre tableau de bord sous la forme d'une URL ;
  • Sauvegarder sous la forme d'un fichier JSON ;
  • Mais le fin du fin reste de le sauvegarder dans le moteur ElasticSearch lui même.

Pour les plus curieux, voici à quoi ressemble cette interface :

Exemple de tableau de bord sous Kibana 3

Pour aller plus loin

Maintenant que nous avons mis en place notre infrastructure de recherche, il faut être conscient que nous sommes tout de même face à un cas simplissime. En effet, pour chaque serveur, nous faisons appel à une instance logstash ce qui implique le lancement d'une JVM qui - je précise que je n'ai rien contre Java - consomme quand même pas mal de mémoire et peut se révéler embêtant si vous deviez déployer votre application dans un cloud. En effet, pour chaque VM que vous aurez à lancer, vous lancerez également un processus Java.

Logstash décentralisé

Le travail d'indexation peut également se révéler très consommateur de ressource. C'est là où vous pourrez éventuellement avoir à déployer des produits comme lumberjack, ou coupler logstash avec redis afin de mieux distribuer votre charge :

  • De petites instances logstash se chargent de remonter vos logs dans redis (on parle de shipper) ;
  • Redis centralise les messages ;
  • Une instance de logstash consomme les messages afin de les indexer dans ElasticSearch (ici, logstash est configuré en indexeur) ;
  • ElasticSearch stocke et met à disposition nos messages ;
  • Enfin, Kibana nous sert à faire de la restitution.

Liens utiles :

  • # J'adore :)

    Posté par (page perso) . Évalué à 3.

    Merci pour cette news,

    A noter que le créateur de Logstash a été engagé par ElasticSearch…

    Pour les retours, moi j'apprécie beaucoup le produit… demande un peu de configuration mais est très simple a mettre en place.

    Kibana est impressionnant et utile mais j'ai du mal a le configurer pour mes différents type de logs… ça prend pas mal de temps …

    Je suis a la recherche d'un client CLI pour ES/Logstash genre faire un Tail / search, quelqu'un a une idée?

    • [^] # Re: J'adore :)

      Posté par (page perso) . Évalué à 3.

      J'ai essayé sur mon serveur suite à la dépêche et c'est vrai que ça l'air bien Kibana mais ça n'a pas l'air facile à configurer.

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

  • # très bon en effet

    Posté par . Évalué à 3. Dernière modification le 29/09/13 à 20:42.

    J'ai eu l'occasion de le voir en action au boulot, et c'est en effet assez interessant.
    Cela dit, je pense que l'un des principaux avantage se trouve dans kibana qui rajoute un couche graphique un peu sympa. Il est finalement assez facile d'avoir le même résultat avec un rsyslogd et un Solr (bien que je préfère elasticsearch a solr). Autre avantage de rsyslogd, RELP!
    Ceci mis à part ca, ce sont de très bons produits. Merci pour le highlight.

    • [^] # Re: très bon en effet

      Posté par . Évalué à 1.

      Il est finalement assez facile d'avoir le même résultat avec un rsyslog et un Solr

      le même résultat que logstash? Je demande à voir. rsyslogd est pas du tout comparable à logstash (ça a déjà carrément moins de transports in/out et de transformation possibles). Par contre, tu peux faire discuter un rsyslog avec un logstash.

      • [^] # Re: très bon en effet

        Posté par . Évalué à 0. Dernière modification le 01/10/13 à 19:01.

        Rsyslog te permet de manipuler les champs syslog très simplement à des fin de filtrages ou de réécriture ou pour définir des conditions.
        Il dispose aussi d'un moteur de regex qui permet de définir des pattern pour chaque champ, là encore à des fins de transformation par exemples, quant à l'input, il suffit de définir des templates afin de prendre en charge un format.

        Pour ce qui est des sorties… là encore c'est très flexible et ça supporte nativement nombre de bdd, des pipes et là encore il y a des templates a disposition.
        Je ne pense pas qu'il y ai bcp de limites fonctionnelles, après on peut discuter perf… mais c un autre sujet.

        • [^] # Re: très bon en effet

          Posté par (page perso) . Évalué à 1.

          Est-ce que certain utilisent ou ont essayé le connecteur omelasticsearch ?

          http://wiki.rsyslog.com/index.php/HOWTO:_rsyslog_%2B_elasticsearch

          • [^] # Re: très bon en effet

            Posté par . Évalué à 0.

            Non je ne savais même pas qu'il existait…
            Par contre, j'ai pu tester un connecteur Solr similaire. Ca marchait pas mal mais je ne l'ai pas utilisé en prod pour d'autres raisons:

            https://github.com/johnl/rsyslog-solr

          • [^] # Re: très bon en effet

            Posté par . Évalué à 2.

            Bonjour!

            Avez-vous eu l'occasion de configurer Rsyslog avec ElasticSearch en utilisant le module omelasticsearch ?
            J'essaie mais impossible de faire interagir les deux. J'ai dû louper un épisode.
            Rsyslog et Elasticsearch fonctionnent correctement, sauf que les messages ne sont pas envoyés vers ou n'arrivent pas dans ES.
            Voici la configuration côté Rsyslog :

            # this is for index names to be like: logstash-YYYY.MM.DD
            template(name="logstash-index" type="list") {
                    constant(value="logstash-")
                    property(name="timereported" dateFormat="rfc3339" position.from="1" position.to="4")
                    constant(value=".")
                    property(name="timereported" dateFormat="rfc3339" position.from="6" position.to="7")
                    constant(value=".")
                    property(name="timereported" dateFormat="rfc3339" position.from="9" position.to="10")
            }
            
            # this is for formatting our syslog in JSON with @timestamp
            template(name="plain-syslog" type="list") {
                    constant(value="{")
                    constant(value="\"@timestamp\":\"")     property(name="timereported" dateFormat="rfc3339")
                    constant(value="\",\"host\":\"")        property(name="hostname")
                    constant(value="\",\"severity\":\"")    property(name="syslogseverity-text")
                    constant(value="\",\"facility\":\"")    property(name="syslogfacility-text")
                    constant(value="\",\"tag\":\"")         property(name="syslogtag" format="json")
                    constant(value="\",\"message\":\"")     property(name="msg" format="json")
                    constant(value="\"}")
            }
            
            # this is where we actually send the logs to Elasticsearch (localhost:9200 by default)
            action(type="omelasticsearch" template="plain-syslog" searchIndex="logstash-index" dynSearchIndex="on" server="monserveur.elasticsearch")

            Mon cluster côté elasticsearch a pour nom CLUSTERLOG.

            Ce n'est pas vraiment le sujet du post initial, mais ça pourra toujours éventuellement servir comme alternative. Merci

            • [^] # Re: très bon en effet

              Posté par (page perso) . Évalué à 2.

              Non, mais ça m'intéresse !

              N'hésite pas à faire un journal si tu t'en sors.

              • [^] # Re: très bon en effet

                Posté par . Évalué à 0.

                Bonjour!

                J'ai fini par faire fonctionner le tout, mais il y a un "mais"…
                Pour rappel, mes clients Rsyslog envoient leurs messages (pour l'instant, ils envoient tout type de messages : connexion ssh, erreurs appli, erreurs systèmes, etc.) vers un serveur Rsyslog. Ce dernier renvoie tout ce qu'il récupère vers un autre serveur Elasticsearch.
                Le seul pb que j'ai, c'est le traitement des messages UTF8.
                En effet, quand un client envoie un message contenant des caractères accentués par exemple, le serveur Rsyslog n'arrive pas à l'insérer dans ES.
                Côté ES, j'ai le message suivant :

                Caused by: org.elasticsearch.common.jackson.core.JsonParseException: Invalid UTF-8 middle byte

                J'ai pu trouver certains posts liés à ce message d'erreur, mais rien qui n'ait pu me faire avancer.
                A partir de la version 7.5.4 de Rsyslog (encore en développement), il existe un module "mmutf8fix" qui corrige les problèmes liés à l'encodage en UTF8. Mais je n'ai pas réussi à mettre la main sur un RPM de ce module.
                Il ne me reste plus qu'à compiler, mais vu le nombre de dépendances, la tâche me parait ardue.
                Je cherche encore. Pour l'instant, je suis obligé d'intercaller LOGSTASH entre le serveur Rsyslog et ElasticSearch, mais je trouve cela un peu dommage…

  • # question subsidiaire...

    Posté par . Évalué à 0.

    "ElasticSearch est un moteur de recherche distribué, intégrant une base de données NoSQL"
    De quoi parle t'on là?
    Pour autant que je saches Lucene est un moteur FTS, pas une DB NoSQL…?

    • [^] # Re: question subsidiaire...

      Posté par (page perso) . Évalué à 1.

      Pour autant que je saches Lucene est un moteur FTS, pas une DB NoSQL…?

      C'est vrai, mais je pense que la confusion vient du fait qu'un index Lucene
      permet de stocker le document indexé dans sa forme initiale en plus des index en eux-même.
      D'ailleurs certain utilisateur d'Elasticsearch stocke leurs documents uniquement dans celui-ci.

    • [^] # Re: question subsidiaire...

      Posté par . Évalué à 3.

      Quitte à vouloir préciser, Lucene n'est pas limité au full text, c'est un moteur d'indexation et de recherche de données.

      Elasticsearch peut tout à fait être vu comme un moteur nosql, après tout c'est pas comme si la définition de nosql était gravée dans le marbre.

  • # ES n'est pas spécialisé dans l'indexation des logs

    Posté par (page perso) . Évalué à 3.

    Ce moteur a été spécialement conçu pour rechercher des données dans des logs.

    Elasticsearch est bien sûr un moteur totalement généraliste et n'est en aucune façon spécialisé dans l'indexation des logs.

  • # Merci aux contributeurs !

    Posté par . Évalué à 5.

    Même si je suis l'initiateur de la dépêche, je voulais remercier les contributeurs qui en ont écrit dix fois plus que moi ;)

    C'est beau la contribution !

  • # Une alternative: Graylog2

    Posté par . Évalué à 4. Dernière modification le 29/09/13 à 22:09.

    Graylog2: http://graylog2.org/ (qui utilise aussi Elastic Search pour la recherche)

    • [^] # Re: Une alternative: Graylog2

      Posté par . Évalué à 1.

      Je viens d'en mettre un en test au taff (des pointes à 1500 messages /sec) et c'est vraiment puissant et très utile !
      J'ai cependant rencontré des problèmes de consommation de RAM (montée à plus de 6Go) de rsyslogd sur certaines machines, j'essaie de trouver pour l'instant la cause du problème.

  • # Ruby, pas Java

    Posté par . Évalué à 4.

    En fait, logstash est principalement développé en Ruby. Il doit tourner sur un JVM car il utilise le runtime JRuby, et il se base donc sur des libs Java (pour éviter de réinventer la roue ou pour aller plus vite).

    • [^] # Re: Ruby, pas Java

      Posté par (page perso) . Évalué à 1.

      J'ai cru comprendre que la raison du "packaging jar" c'est surtout pour en simplifier le déploiement sur n'importe quel environment.

      • [^] # Re: Ruby, pas Java

        Posté par . Évalué à 2.

        L'idée du jar c'est de proposer un fichier unique contenant toutes les dépendances (même Elastic Search en embedded).
        D'après ce que j'avais entendu l'auteur dire dans une conférence, Logstash doit tourner sur n'importe quelle VM Ruby.

  • # et pour revoir le message de log dans son contexte initial ?

    Posté par . Évalué à 2.

    Je suis en train de jouer avec logstash, c'est carrément cool pour chercher quelque chose dans whatmille fichiers sur whatmille serveurs.

    Par contre… une fois qu'on a une entrée/ligne de log je vois pas du tout comment la visualiser dans son contexte = avec les entrées qui suivent et qui précédent dans le même fichier de log ou avec les entrées qui suivent et qui précèdent pour un même type de serveur.

    Je dis pas que c'est pas possible, juste que je trouve pas.

    • [^] # Re: et pour revoir le message de log dans son contexte initial ?

      Posté par . Évalué à 1.

      Je ne sais pas si tu peux faire ça avec Kibana, qui me semble plus orienté tableau de bord que requêtage précis (comme l'est plus Graylog) dans la mine présente dans ElasticSearch.

      Il va falloir sortir le curl pour lancer les requêtes à la main!

      • [^] # Re: et pour revoir le message de log dans son contexte initial ?

        Posté par . Évalué à 1.

        Kibana, qui me semble plus orienté tableau de bord que requêtage précis

        Comme le tableau de bord est filtrable par une requête, tu tape un numéro de transaction ou n'importe quel identifiant présent dans les logs et hop t'as le joli tableau avec les camemberts et les histogrammes mais filtré avec cet identifiant, ainsi que la liste des traces correspondantes. Et dans les traces en question t'as juste à cliquer sur tel ou tel champs pour restreindre la recherche sur un critère supplémentaire.

        Des outils pas fait pour requêter précisément comme ça, j'en veux bien quelques uns ;-)

  • # Couplage avec un ElasticSearch externe

    Posté par . Évalué à 1.

    Bravo pour cette news,

    J'ai pu mettre en place le trio applicatif, c'est vraiment au top.

    Par contre, quand j'ai voulu déployer vers un environnement de prod j'ai été confronté à un problème de communication entre logstash et elasticsearch (distant).

    En utilisant la config logstash : output > elasticsearch > host, j'obtiens l'erreur : "failed to connect to master"

    Et en utilisant la config : output > elasticsearch > bind_host, j'obtiens l'erreur : "Failed to bind to [9300-9400]" (alors que mon admin sys m'affirme que ces ports sont ouverts)

    Quelqu'un aurait une idée du problème ou bien saurait ou trouver des ressources sur le sujet ?

    Merci d'avance et vive elasticsearch ;-)

    j

    • [^] # Re: Couplage avec un ElasticSearch externe

      Posté par (page perso) . Évalué à 1.

      Quand tu veux te coupler vers un ElasticSearch externe, il faut donner le nom de ton cluter et celui de ta machine (paramètre host et cluster). Ci-dessous un exemple :

      output {
        elasticsearch {
          host=> "robert"
          cluster => "elasticsearch"
        }
      }
      

      Si tu veux vérifier ta communication vers ton serveur, tu peux lancer la commande telnet avec le nom de la machine + le numéro de port que tu veux atteindre. Ici, ça ressemblerait à telnet elasticnode 9300. Si ça ne t'affiche rien, c'est que tu as un problème d'ouverture de port, si ça t'affiche quelque chose, tu as un autre problème :).

      • [^] # Re: Couplage avec un ElasticSearch externe

        Posté par . Évalué à 1.

        Merci de ta réponse,

        La commande telnet me renvoit bien qqch sur le port 9300,

        Avec la conf ci-dessous l'erreur que j'obtiens est "failed to connect to master [[~nom de mon elastic search~]]". Donc la communication se fait bien puisqu'il me remonte le nom de mon instance elastic, mais toujours cette erreur de connexion au master :-(

        output {
        elasticsearch {
        host => "123.456.789.123"
        cluster => "elasticsearch"
        index => "logstash-dev-%{+YYYY}"
        }
        }

        N'y a-t-il vraiment rien à modifier dans le elasticsearch.yml pour autoriser cette connexion distante ? (j'ai tout laissé par défaut)

        j

  • # Un compagnon de Logstash

    Posté par . Évalué à 1. Dernière modification le 01/10/13 à 12:28.

    Pour les fans de Logstash, je vous recommande également ceci : Riemann

    Logstash fourni un plugin de sortie pour cette application

  • # Logstash pour debian

    Posté par . Évalué à 1.

    La version 1.3.1 de Logstash a été packagée (.deb) sur www.dogstash.net. Ce paquet contient notamment un script d'init qui permet de gérer plusieurs instances de Logstash.

Suivre le flux des commentaires

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