Docker应用程序使用Filebeat和Logstash进行日志logging

我有一套dockerized应用程序分散在多个服务器上,并尝试使用ELK设置生产级集中式日志logging。 我对ELK部分本身可以,但是我对如何将日志转发到我的logstash有点困惑。 我试图使用Filebeat,因为它的负载均衡function。 我还想避免将Filebeat(或其他任何东西)包装到我的所有docker中,并将它们分开,dockerized或不。

我如何继续?

我一直在尝试以下。 我的Dockerslogin标准输出,所以configuration了一个非dockerized Filebeat从标准input读取我做:

docker日志-f mycontainer | ./filebeat -e -c filebeat.yml

这似乎开始工作。 第一个日志被转发到我的logstash。 caching的我猜。 但是在某个时候,它会卡住并继续发送相同的事件

这只是一个错误,或者我是在一个错误的方向? 你有什么解决scheme?

Docker允许你指定使用的logDriver 。 这个答案不关心Filebeat或负载平衡。

在演示文稿中,我使用syslog将日志转发到侦听端口5000的Logstash(ELK)实例。以下命令不断通过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' 

以下是将docker logs转发到ELK堆栈的一种方法(需要docker> = 1.8作为gelf日志驱动程序):

  1. 使用gelfinput插件启动Logstash容器,以从gelf中读取数据并输出到Elasticsearch主机(ES_HOST:port):

     docker run --rm -p 12201:12201/udp logstash \ logstash -e 'input { gelf { } } output { elasticsearch { hosts => ["ES_HOST:PORT"] } }' 
  2. 现在启动一个Docker容器并使用gelf Docker日志驱动程序 。 这是一个愚蠢的例子:

     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. 加载Kibana,现在可以看到Docker docker logs中的内容。 gelf源代码显示为您生成了一些方便的字段(hat-tip: Christophe Labouisse ): _container_id_container_name_image_id_image_name_command_tag_created

如果您使用docker-compose(确保使用docker-compose> = 1.5)并在启动logstash容器后在docker docker-compose.yml添加适当的设置:

 log_driver: "gelf" log_opt: gelf-address: "udp://localhost:12201" 

使用filebeat你可以像刚才所描述的那样pipe理docker docker logs输出。 您看到的行为绝对听起来像一个错误,但也可以是部分行读取configuration(重新发送部分行,直到find新行符号)。

如果没有logstash可用,我用pipe道看到的问题可能是背压。 如果filebeat不能发送任何事件,它会在内部缓冲事件,并在某个时候停止从标准input读取。 不知道如何/如果docker保护标准输出反应迟钝。 pipe道的另一个问题可能是filebeat + docker的重新启动行为,如果您使用的是docker-compose。 docker – 默认情况下重新使用图像+图像状态。 所以当你重新启动的时候,你会再次发送所有的旧日志(因为底层的日志文件还没有被旋转)。

您可以尝试读取docker写入主机系统的日志文件,而不是pipe道。 默认的docker日志驱动程序是json日志驱动程序 。 你可以也应该configurationjson日志驱动程序做日志轮换+保留一些旧文件(用于缓冲在磁盘上)。 请参阅最大大小和最大文件选项。 json驱动程序为每一行logging一行“json”数据。 在docker主机系统上,日志文件写入/var/lib/docker/containers/container_id/container_id-json.log。 这些文件将通过filebeat转发到logstash。 如果logstash或networking变得不可用或filebeat重新启动,它将继续转发它所剩下的日志行(由于日志旋转,给定的文件未被删除)。 没有事件将会丢失。 在logstash中,您可以使用json_lines编解码器或filter来parsingjson行和grokfilter,从日志中获取更多信息。

关于使用libbeat(由filebeat用于传送日志文件)向docker添加新的日志驱动程序已经有一些讨论 。 也许有可能通过使用docker日志api通过dockerbeat收集日志(虽然我不知道有关使用日志api的计划)。

使用系统日志也是一个选项。 也许你可以在你的docker主机负载平衡日志事件上获得一些syslog中继。 或者让系统日志写入日志文件并使用filebeat转发它们。 我认为rsyslog至less有一些故障转移模式。 可以使用logstash sysloginput插件和rsyslog将日志转发到具有故障转移支持的日志,以防活动logstash实例变得不可用。

我使用Docker API创build了自己的Docker镜像,以收集在机器上运行的容器的日志,并通过Filebeat将它们发送到Logstash。 不需要在主机上安装或configuration任何东西。

检查出来,并告诉我,如果它适合您的需要: https : //hub.docker.com/r/bargenson/filebeat/ 。

代码可以在这里find: https : //github.com/bargenson/docker-filebeat

只是为了帮助那些需要这样做的人,您可以简单地使用Filebeat来发送日志。 我会通过@ brice-argenson使用容器,但是我需要SSL支持,所以我使用了本地安装的Filebeat实例。

filebeat的探矿者(重复更多的容器):

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

它有点儿需要知道GUID,因为它们可能会更新。

在logstash服务器上,为logstash设置常用的filebeatinput源,并使用如下的filter:

 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" ] } } } 

这将parsingDocker日志中的JSON,并将时间戳设置为Docker报告的时间戳。

如果您正在从nginx Docker镜像读取日志,则还可以添加此筛选器:

 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" } } } } 

转换/重命名是可选的,但在COMBINEDAPACHELOGexpression式中修正了一个监督,它不会将这些值转换为整数,从而使它们不可用于在Kibana中进行聚合。

我在一个评论中证实了erewok在上面写的东西:

根据文档,你应该能够在你的prospectors.paths中使用这样的模式:/var/lib/docker/containers/*/*.log – erewok Apr 18 at 21:03

在filebeat启动时,正确parsingdocker器容器guid(以第一个“*”表示)。 我不知道容器被添加会发生什么。