Docker 日志最佳实践

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker 日志最佳实践相关的知识,希望对你有一定的参考价值。

当运行在 docker 容器中的应用程序打印日志时,日志会输出到标准输出流 stdout 和标准错误流 stderr。容器日志驱动可以访问这些流,并将日志发送到文件、本机运行的日志收集器或远端的日志服务端点(endpoint)。本文将介绍选择不同的日志驱动及配置对容器应用的性能和稳定性带来的影响,以及推荐最能满足日志记录需求和性能的日志驱动及配置。

选择日志驱动

Docker 提供了若干内置的日志驱动,不同的日志驱动会把日志分发到不同的地方,每个容器只能只能指定一种日志驱动。

Docker 使用 json-file 作为默认日志驱动,该驱动把日志以 json 的格式写入宿主机指定文件:

/var/lib/docker/containers/CONTAINER_ID-json.log

下面是由 hello world 镜像启动的容器创建的 json 日志实例:

"log":"Hello from Docker!\\n","stream":"stdout","time":"2022-05-29T22:51:31.549390877Z"
"log":"This message shows that your installation appears to be working correctly.\\n","stream":"stdout","time":"2022-05-29T22:51:31.549396749Z"

也可以通过命令行直接查看日志:

docker logs <CONTAINER_ID> or docker logs <CONTAINER_NAME>
Hello from Docker!
This message shows that your installation appears to be working correctly.

其中,docker 提供了以下内置日志驱动:

  • none

禁用日志,且 docker logs 指令不返回任何内容。

  • local

保存日志内容到本地文件并对内容进行压缩。

  • json-file

以 json 格式保存日志内容到本地文件,默认日志驱动。

  • syslog

保存日志内容到 syslog,syslog daemon 必须运行在宿主机上。

  • journald

保存日志内容到 journald,journald daemon 必须运行在宿主机上。

  • gelf

保存日志内容到 GELF - Graylog Extended Log Format 端点,如 Graylog 和 Logstash。

  • fluentd

保存日志内容到 fluentd,fluentd daemon 必须运行在宿主机上。

  • awslogs

保存日志内容到 Amazon CloudWatch。

  • splunk

保存日志内容到 splunk。

  • etwlogs

保存日志内容到 ETW - Event Tracing for Windows,只能在 Windows 平台上使用。

  • gcplogs

保存日志内容到 GCP - Google Cloud Platform。

  • logentries

保存日志内容到 Rapid7 Logentries。

配置日志驱动

Docker 容器默认使用 json-file 日志驱动,大部分情况下,建议直接使用该驱动。如果你的应用场景确实需要使用其它驱动,可以在 docker run 指令中使用 --log-driver 选项来覆盖默认驱动,以下是使用 fluntd 作为日志驱动的示例:

docker run --log-driver fluentd httpd:latest

也可以通过修改 daemon.json 来配置日志驱动,以下是使用 fluntd 作为日志驱动的示例:


  "log-driver": "fluentd",
  "log-opts": 
    "fluentd-address": "fluentd-ip:fluentd-port"
  

重启 docker 使上述配置生效,后续创建的容器都将使用 fluentd 作为日志驱动,并把日志发送到指定的 fluentd address。

日志分发模式

无论选择了什么日志驱动,都可以指定日志的分发模式:阻塞或非阻塞。

阻塞模式

阻塞模式是日志分发的默认模式,在该模式下,日志每次发送时会阻塞应用程序,以保证日志能正常到达指定位置,这会增加应用程序的处理延迟,降低应用程序的性能。如果日志驱动一直处于繁忙,容器会延迟应用程序的其他任务,直到日志传输完毕。

阻塞模式对应用程序性能的潜在影响取决于选择的日志驱动。例如,json-file 日志驱动日志写入速度非常快,并且写入的是本地文件,所以不太可能出现阻塞并导致延迟。相反的,gcplogs 和 awslogs 这些需要打开远程连接的日志驱动,很可能会出现长时间的阻塞,并对应用程序带来明显的延迟。

非阻塞模式

在非阻塞模式下,容器首先把日志写入内存环形缓冲区,直到日志驱动可以处理它们为止。即使日志驱动很忙,容器也可以立即将日志输出到缓冲区,并继续执行应用程序。这确保了大量日志活动不会影响容器中运行的应用程序的性能。

与阻塞模式相比,非阻塞模式不能保证日志能正常到达指定位置。如果应用程序产生日志的速度快于日志驱动处理日志的速度,环形缓冲区的内存将会耗尽。如果发生这种情况,缓冲区较早的 日志将被删除,然后才能传递给日志驱动,造成日志丢失。可以通过 max-buffer-size 选项来设置环形缓冲区的大小,max-buffer-size 的默认值为 1MB。如果宿主机有足够内存的话,

配置分发模式

阻塞模式是日志分发的默认模式,可以在创建容器时使用--log-opt选项来设置非阻塞模式:

docker run --log-opt mode=non-blocking httpd:latest

也可以通过修改 daemon.json 来配置分发模式:


  "log-driver": "fluentd",
  "log-opts": 
    "fluentd-address": "fluentd-ip:fluentd-port",
    "mode": "non-blocking"
  

选择适合的日志驱动及分发模式

大部分场景下,建议使用阻塞模式 + json-file,日志写入本地文件速度非常快,在阻塞模式下能够捕获所有日志,但不会降低应用程序性能。

可以使用日志收集 agent,如 fluentd/fluent-bit 来 tail 本地日志文件,并将日志转发到日志中心。json 格式的日志易于解析,可以按属性筛选日志,识别日志趋势并作相应警报,以及对容器应用进行分析。

阻塞模式 + json-file 虽然能满足大部分应用场景,但在某些情况下,可能需要考虑其它的日志驱动及分发模式组合。

磁盘密集型应用

如果应用程序产生大量日志并频繁执行 I/O 操作,请考虑使用非阻塞模式 + json-file。该组合可保持应用程序的性能,同时仍可提供可靠的结构化日志记录。将日志写入本地存储很快,环形缓冲区不太可能被填满。如果不需要支持记录峰值时的日志(此时可能会填满环形缓冲区),那么非阻塞模式 + json-file 可以捕获所有的日志,而不会中断应用程序。

不能使用本地日志的内存密集型应用

如果应用程序本身很需要内存资源,并且日志不能存放在本地,需要使用 gcplogs 或 awslogs 等驱动把日志发送到远端时,应考虑阻塞模式。因为如果出现网络阻塞时,已无足够内存可分配给环形缓冲区。

虽然使用阻塞模式可以确保捕获所有日志,但通常不建议在阻塞模式下使用 json-file 以外的日志驱动,因为应用程序的性能可能会受到影响。

对于日志无法存放到本地,但性能要求又高于日志可靠性的应用程序,建议为环形缓冲区提供足够的内存,并使用非阻塞模式。这样可以确保应用程序性能不会受到日志记录的影响,同时也为捕获主要日志提供了足够的空间。

参考总结

以上就是本文希望分享的内容,如果大家有什么问题,欢迎在公众号 - 跬步之巅留言交流。

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于Docker 日志最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

为啥Docker官方镜像不按照“最佳实践”的要求使用USER

大规模Mesos&Docker在去哪儿网的最佳实践

5个Kubernetes监控最佳实践

PHP中日志自定义异常的最佳实践

后端日志最佳实践

自我总结,编写Dockerfile的9大最佳实践