如何使用docker在微服务架构中传送日志?

2024-02-13

Heroku 在其中描述了日志十二因素应用程序清单 http://12factor.net/作为简单的事件流:

日志是从所有正在运行的进程和支持服务的输出流收集的聚合的、按时间排序的事件流。原始形式的日志通常是一种文本格式,每行一个事件(尽管异常的回溯可能跨越多行)。日志没有固定的开始或结束,但只要应用程序正在运行,就会不断流动。

此外,应用程序应该简单地将日志写入stdout,把任务交给“环境”。

十二因素应用程序从不关心其输出流的路由或存储。它不应尝试写入或管理日志文件。相反,每个正在运行的进程都会将其未缓冲的事件流写入标准输出。在本地开发期间,开发人员将在终端的前台查看此流以观察应用程序的行为。

在登台或生产部署中,每个流程的流将由执行环境捕获,与应用程序中的所有其他流整理在一起,并路由到一个或多个最终目的地以供查看和长期存档。这些归档目标对应用程序不可见或不可配置,而是完全由执行环境管理。开源日志路由器(例如 Logplex 和 Fluent)可用于此目的。

那么在 docker 环境中实现这一点的可靠性、效率和易用性方面的最佳方法是什么?我想我会想到以下问题:

  • 依赖 Docker 自己的日志设施是否安全(docker logs)?
  • 独立运行 docker 并将其输出视为日志流是否安全?
  • Can stdout直接重定向到文件(磁盘空间)?
  • 如果使用文件,它应该位于 docker 映像还是绑定卷内(docker run --volume=[])?
  • 是否需要对数轮转?
  • 将 stdout 直接重定向到 logshipper(以及哪个 logshipper)是否安全?
  • 命名管道(又名 FIFO)是一种选择吗?
  • (还有更多问题吗?)

码头工人1.6介绍 https://blog.docker.com/2015/04/docker-release-1-6/的概念记录驱动程序 https://docs.docker.com/reference/run/#logging-drivers-log-driver提供对日志输出的更多控制。这--log-driver标志配置在哪里stdout & stderr应从容器中运行的进程进行定向。也可以看看配置日志记录驱动程序 https://docs.docker.com/reference/logging/overview/.

有多个驱动程序可用。请注意,所有这些除了json-file禁用docker logs收集容器日志。

  • none - 禁用容器日志。
  • json-file - 行为与之前一样,json 格式的 stdout 可用/var/lib/docker/containers/<containerid>/<containerid>-json.log
  • syslog - 将消息写入系统日志。还接受--log-opt通过 TCP、UDP 或 Unix 域套接字将日志消息定向到指定的系统日志。还禁用docker logs
  • Journald - 写入 systemd 日志。
  • *gelf - Graylog 扩展日志格式 (GELF)。将日志消息写入 GELF 端点,例如 Graylog 或 Logstash
  • * Fluentd - 将容器日志发送到fluentd http://www.fluentd.org。接受一些选项来自定义 Fluentd 的地址并发送带有日志消息的标签。
  • **awslogs - 将日志消息写入 AWS CloudWatch Logs

* Docker 1.8 中的新功能

** Docker 1.9 中的新功能

例如:

docker run --log-driver=syslog --log-opt syslog-address=tcp://10.0.0.10:1514 ...

这是 Docker 推荐的软件解决方案,用于将日志消息写入stdout & stderr。但是,某些软件不会将日志消息写入stdout/stderr。例如,它们会写入日志文件或系统日志。在这些情况下,下面原始答案中的一些细节仍然适用。回顾一下:

如果应用程序写入本地日志文件,请从主机安装卷(或使用仅数据容器 http://docs.docker.com/userguide/dockervolumes/到容器并将日志消息写入该位置。

如果应用程序写入系统日志,有多种选择:

  • 通过挂载主机的 syslog 套接字发送到主机的 syslog (/dev/log)到容器中使用-v /dev/log:/dev/log.
  • 如果应用程序在其配置中接受 syslog 端点,请将主机的 syslog 守护进程配置为通过 Docker 桥接网络上的 TCP 和/或 UDP 进行侦听,并使用该端点。或者只是发送到远程系统日志主机。
  • 在容器中运行 syslog 守护进程,并使用 Docker 链接从其他正在运行的容器访问它。
  • Use logspout https://github.com/progrium/logspout通过 UDP 自动将容器日志路由到远程系统日志

不要忘记容器内的任何日志都应该像在主机操作系统上一样进行轮换。


Docker 1.6 之前的原始答案

依赖 Docker 自己的日志工具(docker log)安全吗?

docker logs每次都会打印整个流,而不仅仅是新日志,因此这是不合适的。docker logs --follow会给tail -f-类似的功能,但是你有一个一直在运行的 docker CLI 命令。因此,虽然它是safe to run docker logs,这不是最优的。

独立运行 docker 并将其输出视为日志流是否安全?

您可以使用 systemd 启动容器而不是守护进程,从而捕获 systemd 日志中的所有标准输出,然后可以由主机根据您的需要进行管理。

stdout可以直接重定向到文件(磁盘空间)吗?

你可以这样做docker run ... > logfile当然可以,但它感觉很脆弱,而且更难自动化和管理。

如果使用文件,它应该位于 docker 映像还是绑定卷内(docker run --volume=[])?

如果您在容器内写入,则需要在容器中运行 logrotate 或其他东西来管理日志文件。最好从主机安装卷并使用主机的日志轮换守护程序控制它。

是否需要对数轮转?

当然,如果应用程序写入日志,您需要像在本机操作系统环境中一样轮换它们。但是,如果您在容器内写入,则会更困难,因为日志文件位置不可预测。如果您在主机上轮换,日志文件将位于以下位置,例如使用 devicemapper 作为存储驱动程序,/var/lib/docker/devicemapper/mnt/<containerid>/rootfs/...。需要一些丑陋的包装器才能让 logrotate 找到该路径下的日志。

将 stdout 直接重定向到 logshipper(以及哪个 logshipper)是否安全?

最好使用syslog并让日志收集器处理syslog。

命名管道(又名 FIFO)是一种选择吗?

命名管道并不理想,因为如果管道的读取端死亡,写入器(容器)将得到一个损坏的管道。即使该事件由应用程序处理,它也会被阻止,直到再次有读者为止。再加上它规避了docker logs.

另请参阅此用 docker 在 fluidd 上发帖 http://jasonwilder.com/blog/2014/03/17/docker-log-management-using-fluentd/.

请参阅 Jeff Lindsay 的工具logspout https://github.com/progrium/logspout从正在运行的容器收集日志并根据需要路由它们。

最后,请注意,容器中的 stdout 日志记录到主机上的文件中/var/lib/docker/containers/<containerid>/<containerid>-json.log.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用docker在微服务架构中传送日志? 的相关文章

随机推荐