Docker 日志的 10 大陷阱

Docker不仅改变了应用程序的部署方式,还改变了日志管理的工作流程。容器不但无需将日志写入文件,反而是将日志写入控制台(stdout / stderr),然后Docker Logging Drivers将日志转发到目标。针对Docker GitHub问题的检查很快会显示用户在处理Docker日志时遇到各种问题。使用Docker管理日志貌似有点棘手,且需要深入理解Docker Logging Driver的实现和替代方法,以解决报告的问题。

那么,Docker日志的十大陷阱是什么?

首先,让我们从Docker Logging Drivers和选项的概述开始,将日志发送到集中式日志管理解决方案,如Elastic Stack(前身ELK Stack)或Sematext Cloud。

Docker 日志的 10 大陷阱

在Docker的早期,容器日志只能通过Docker远程API,即通过“docker logs”命令和一些高级的日志传送工具才能使用。之后,Docker引入日志驱动程序作为插件,以打开Docker与各种日志管理工具进行集成。这些日志驱动程序是作为docker守护进程中的二进制插件实现的。最近,插件体系结构得到了扩展,以便于运行日志驱动程序作为外部进程,不但可以注册为插件,还可以通过Unix套接字检索日志。目前,Docker二进制文件附带的日志记录驱动程序是二进制插件,但在不久的将来可能会发生变化。

Docker Logging Drivers接收容器日志并将其转发到远程目标或文件。默认的日志驱动程序是“json-file”。它在本地磁盘上以JSON格式存储容器日志。Docker有一个用于日志记录驱动程序的插件体系结构,所以有插件可用于开源工具和商业工具:

  • Journald – 将容器日志存储在系统日志中
  • Syslog Driver – 支持UDP,TCP,TLS
  • Fluentd- 支持TCP或Unix套接字连接到fluentd
  • Splunk - 将HTTP / HTTPS转发到Splunk服务器
  • Gelf - 将UDP日志转发到Graylog2

对于完整的日志管理解决方案,需要包含附加工具:

日志解析器来构造日志,通常是日志传送工具(fluentd,rsyslog,logstash,logagent等)的一部分

日志索引,可视化和警报:

  • Elasticsearch和Kibana(Elastic Stack,也被称为ELK Stack),
  • Splunk,
  • Logentries,
  • Loggly,
  • Sumologic,
  • Graylog OSS / Enterprise
  • Sematext Cloud/Enterprise
  • 还有很多 …

为了将日志发送到其中一个后端,你可能需要选择一个支持所选日志管理解决方案的日志驱动程序或日志记录工具。如果你的工具需要Syslog输入,则可以选择Syslog驱动程序。

Docker日志的十大陷阱

1. Docker日志命令只在使用json-file日志驱动程序时可工作

默认的日志驱动程序“json-file”将日志写入本地磁盘,而json-file驱动程序是唯一与“docker logs”命令并行工作的驱动程序。只要有人使用替代日志驱动程序,例如Syslog,Gelf或Splunk,则Docker日志API调用就会失败,而“docker logs”命令将显示报告限制的错误,而不是在控制台上显示日志。docker log命令不仅会失败,而且很多其他使用Docker API的日志工具,比如像Portainer这样的Docker用户界面,或者像Logspout这样的日志集合容器,都不能在这种情况下显示容器日志。

请参阅https://github.com/moby/moby/issues/30887

2. Docker Syslog驱动程序可以阻止容器部署

使用Docker Syslog驱动程序与TCP或TLS是提供日志的可靠方式。但是,Syslog日志驱动程序需要在启动容器时建立与Syslog服务器的TCP连接。如果无法在容器启动时建立此连接,则容器启动失败,并显示错误消息如

docker: Error response from daemon: Failed to initialize logging driver: dial tcp

这意味着暂时的网络问题或高网络延迟可以阻止容器的部署。此外,Syslog服务器的重新启动可能会将所有通过TCP / TS的容器日志记录到中央Syslog服务器,这绝对是要避免的情况。

请参阅:https://github.com/docker/docker/issues/21966

3.当目标关闭时,Docker Syslog驱动程序会丢失日志

与上面的问题#2类似,导致日志丢失的原因是Docker日志驱动程序在日志无法传递到远程目标时缺少了缓冲磁盘日志的能力。

一个有趣的问题要看:https://github.com/moby/moby/issues/30979

4. Docker日志驱动程序不支持像Error Stack Traces这样的多行日志

当我们考虑日志时,大多数人都会想到简单的单行日志,比如Nginx或Apache日志。但是,日志也可以跨越多个行。例如,异常跟踪通常跨越多行,因此为了帮助Logstash用户,我们分享了如何使用Logstash处理堆栈跟踪。在容器世界中情况也不见得好一点,甚至反而更加复杂,因为在容器中运行的所有app的日志都被输出到相同的输出——标准输出。难怪看到问题#22920以“Closed. Don’t care.”结束使得这么多人失望了。幸运的是,像Sematext Docker Agent这样的工具可以立即可用地解析多行日志,以及应用自定义的多行模式。

5. Docker服务日志命令与非JSON日志记录驱动程序挂起

虽然json-files驱动程序看起来很健壮,但其他日志驱动程序可能仍然会造成Docker Swarm模式的麻烦。

请参阅Github问题:https://github.com/docker/docker/issues/28793

6.如果fluentd守护进程已经失效并且缓冲区已满,则Docker守护进程会崩溃

另一种日志驱动程序在远程目标不可访问时会导致问题的情境——在这种情况下,日志驱动程序会抛出导致Docker后台程序崩溃的异常。

7.在Splunk驱动程序失败时,Docker Container陷入创建状态

如果Splunk服务器在容器启动时返回504,则容器实际上是启动的,但是Docker报告容器未能启动。一旦处于这种状态,容器将不再出现在docker ps下,并且容器进程不能通过docker kill停止。停止该过程的唯一方法是手动kill。

Github:https://github.com/moby/moby/issues/24376

8. Docker日志跳过/缺少应用程序日志(journald驱动程序)

事实证明,这个问题是由journald速率限制引起的,当Docker为所有正在运行的应用程序创建日志时,需要增加日志速率限制,而由于其速率限制设置,journald可能会跳过某些日志。所以当你连接Docker的时候要注意你的journald设置。

9.Gelf驱动程序问题

Gelf日志驱动程序缺少TCP或TLS选项,并且仅支持UDP,当UDP数据包丢失时可能会有丢失日志消息的风险。有些问题报告了使用GELF驱动程序进行DNS解析/缓存的问题,所以当你的Graylog服务器IP更改时,你的日志可能会发送到“Nirvana” ——这使用容器部署可能会快速发生。

10. Docker不支持多个日志驱动程序

将日志存储在本地服务器上并将其发送到远程服务器是很好的。目前,Docker不支持多个日志驱动程序,所以用户不得不选择单个日志驱动程序。

尽管已经知道了这篇文章中列出的各种问题,但抉择起来依然不是一件易事。

相关推荐