Journalisation des applications Docker avec Filebeat et Logstash

j'ai un ensemble d'applications dockerisées dispersées sur plusieurs serveurs et essayant de configurer la journalisation centralisée au niveau de la production avec ELK. Je suis d'accord avec la partie ELK elle-même, mais je suis un peu confus sur la façon d'avancer les logs à mes logs. J'essaie D'utiliser Filebeat, à cause de sa fonction loadbalance. J'aimerais aussi éviter d'empaqueter des morceaux de viande (ou autre chose) dans tous mes dockers, et les garder séparés, dockerisés ou non.

Comment puis-je procéder?

j'ai essayé le suivant. Mon Dockers journal sur la sortie standard stdout donc avec un non-dockerized Filebeat configuré pour lire l'entrée standard stdin je fais:

panneau de journaux -f mycontainer | ./ filebeat-e-c filebeat.yml

cela semble fonctionner au début. Les premiers logs sont envoyés à mon logstash. La mise en cache un, je suppose. Mais à un moment ça coince et continuer à envoyer le même événement

Est-ce juste un bug ou je me dirige dans la mauvaise direction? Quelle solution avez-vous le programme d'installation?

18
demandé sur Gianluca 2015-10-30 12:47:46

6 réponses

Docker vous permet de spécifier le logDriver en cours d'utilisation. Cette réponse ne se soucie pas de Filebeat ou d'équilibrage de charge.

dans une présentation j'ai utilisé syslog pour transmettre les logs à une instance Logstash (ELK) écoutant sur le port 5000. La commande suivante envoie constamment des messages via syslog à Logstash:

docker run -t -d --log-driver=syslog --log-opt syslog-address=tcp://127.0.0.1:5000 ubuntu /bin/bash -c 'while true; do echo "Hello $(date)"; sleep 1; done'
6
répondu michaelbahr 2015-10-30 10:06:14

Voici une façon de l'avant docker logs pour le WAPITI de la pile (nécessite un docker >= 1,8 pour le gelf journal pilote):

  1. Logstash récipient avec de l' gelf entrée plugin pour lit de gelf et sorties pour un Elasticsearch hôte (ES_HOST:port):

    docker run --rm -p 12201:12201/udp logstash \
        logstash -e 'input { gelf { } } output { elasticsearch { hosts => ["ES_HOST:PORT"] } }'
    
  2. maintenant, démarrez un conteneur Docker et utilisez le gelf Docker journalisation pilote. Voici un exemple stupide:

    docker run --log-driver=gelf --log-opt gelf-address=udp://localhost:12201 busybox \
        /bin/sh -c 'while true; do echo "Hello $(date)"; sleep 1; done'
    
  3. charger Kibana et les choses qui auraient atterri dans docker logs sont maintenant visibles. code source gelf montre que certains champs pratiques sont générés pour vous (Hat-tip:Christophe Labouisse):_container_id,_container_name,_image_id,_image_name,_command,_tag,_created.

si vous utilisez docker-composer (assurez-vous d'utiliser docker-composer >= 1.5) et ajoutez les paramètres appropriés dans docker-compose.yml après démarrage du conteneur logstash:

log_driver: "gelf"
log_opt:
  gelf-address: "udp://localhost:12201"
17
répondu Pete 2015-11-20 00:01:41

Utilisation de la filebeat vous pouvez simplement pipe docker logs sortie comme vous l'avez décrit. Le comportement que vous voyez ressemble certainement à un bug, mais peut aussi être la configuration partielle de lecture de ligne qui vous frappe (renvoie des lignes partielles jusqu'à ce que le symbole newline soit trouvé).

un problème que je vois avec la tuyauterie est la contre-pression possible dans le cas où aucune Digue n'est disponible. Si filebeat ne peut pas envoyer d'événements, il va amortir les événements en interne et à un certain point arrêter la lecture de stdin. Aucune idée comment / si docker protège contre le fait que stdout ne réagisse pas. Un autre problème avec la tuyauterie pourrait être le comportement de redémarrage de filebeat + docker si vous utilisez docker-composer. docker-compose par défaut réutilise les images + l'état de l'image. Ainsi, lorsque vous redémarrez, vous redirigerez tous les vieux journaux (étant donné que le fichier journal sous-jacent n'a pas encore été mis en rotation).

au lieu de la tuyauterie, vous pouvez essayer de lire les fichiers journaux écrits par docker sur le système hôte. Le pilote par défaut de docker log est le json journal pilote . Vous pouvez et devez configurer le pilote de journalisation json pour faire la rotation des journaux + garder quelques vieux fichiers (pour la mise en tampon sur le disque). Voir les options max-size et max-file. Le pilote JSON met une ligne de données "json" pour chaque ligne à enregistrer. Sur le panneau d'accueil du système, les fichiers journaux sont enregistrés dans /var/lib/docker/conteneurs/container_id/container_id-json.journal. Ces fichiers seront transmis par filebeat à logstash. Si logstash ou le réseau devient indisponible ou filebeat est redémarré, il continue à rediriger log les lignes où il reste de (les fichiers donnés n'ont pas été supprimés en raison de la rotation des logs). Aucun événement ne sera perdu. Dans logstash, vous pouvez utiliser le codec ou le filtre de json_lines pour analyser les lignes json et un filtre de grok pour obtenir plus d'informations à partir de vos journaux.

Il y a discussion sur l'utilisation de libbeat (utilisé par filebeat pour l'expédition des fichiers journaux) pour ajouter un nouveau journal pilote à docker. Peut-être est-il possible de collecter des logs via dockerbeat dans l'avenir par utiliser l'api Docker logs (je n'ai connaissance d'aucun plan d'utilisation de l'api logs).

utiliser syslog est aussi une option. Peut-être que vous pouvez obtenir un relais syslog sur votre serveur docker équilibrant les événements log. Ou demander à syslog d'écrire des fichiers journaux et d'utiliser filebeat pour les transmettre. Je pense que rsyslog a au moins un mode de basculement. Vous pouvez utiliser logstash syslog input plugin et rsyslog pour transférer les logs vers logstash avec le support de basculement dans le cas où l'instance active logstash devient indisponible.

8
répondu urso 2015-11-20 13:59:36

j'ai créé ma propre image docker en utilisant L'API Docker pour collecter les journaux des conteneurs qui tournent sur la machine et les expédier à Logstash grâce à Filebeat. Pas besoin d'installer ou de configurer quoi que ce soit sur l'ordinateur hôte.

Vérifier et me dire si cela convient à vos besoins: https://hub.docker.com/r/bargenson/filebeat/.

Le code est disponible ici: https://github.com/bargenson/docker-filebeat

7
répondu Brice Argenson 2016-02-07 06:17:47

juste pour aider les autres qui ont besoin de faire cela, vous pouvez simplement utiliser Filebeat pour expédier les journaux. J'utiliserais le container de @brice-argenson, mais j'avais besoin du support de SSL donc je suis allé avec une instance de Filebeat installée localement.

Le prospecteur de filebeat est (répétez l'opération pour plus de conteneurs):

- input_type: log
  paths:
    - /var/lib/docker/containers/<guid>/*.log
  document_type: docker_log
  fields:
    dockercontainer: container_name

ça craint un peu que vous ayez besoin de connaître les GUIDs car ils pourraient changer sur les mises à jour.

sur le serveur logstash, configurer la source d'entrée filebeat habituelle pour logstash, et l'utilisation d'un filtre comme ceci:

filter {
  if [type] == "docker_log" {
    json {
      source => "message"
      add_field => [ "received_at", "%{@timestamp}" ]
      add_field => [ "received_from", "%{host}" ]
    }
    mutate {
      rename => { "log" => "message" }
    }
    date {
      match => [ "time", "ISO8601" ]
    }
  }
}

ceci analysera le JSON à partir des logs du Docker, et réglera l'horaire sur celui rapporté par le Docker.

Si vous lisez les journaux de la nginx Docker image, vous pouvez ajouter ce filtre ainsi:

filter {
  if [fields][dockercontainer] == "nginx" {
    grok {
      match => { "message" => "(?m)%{IPORHOST:targethost} %{COMBINEDAPACHELOG}" }
    }
    mutate {
      convert => { "[bytes]" => "integer" }
      convert => { "[response]" => "integer" }
    }
    mutate {
      rename => { "bytes" => "http_streamlen" }
      rename => { "response" => "http_statuscode" }
    }
  }
}

le convert / renames sont optionnels, mais corrige une erreur dans le COMBINEDAPACHELOG expression où elle ne lance pas ces valeurs à des entiers, les rendant indisponibles pour agrégation dans Kibana.

0
répondu Kenneth 2016-11-25 09:25:10

j'ai vérifié ce qu'erewok a écrit ci-dessus dans un commentaire:

d'Après les docs, vous devriez être en mesure d'utiliser un modèle comme ceci dans votre prospecteurs.chemins: /var/lib/docker/conteneurs/*/*.log-erewok 18 avril à 21: 03

les guids du conteneur docker, représentés par le PREMIER '*', sont correctement résolus lorsque filebeat démarre. Je ne sais pas ce qui se passe lorsque des contenants sont ajoutés.

0
répondu Arun Gupta 2017-09-13 22:14:56