结构化日志logging从Docker容器中logging

在Docker容器中写入结构化日志以logging日志的最佳方式是什么?

例如,我有一个使用sd_journal_send写入的应用程序,而不是更改应用程序,我尝试通过

-v / var / log / systemd / journal:/ var / log / systemd / journal

它适用于我的Ubuntu 16.04桌面,但不适用于运行应用程序的CoreOS实例(使用Ubuntu 16.04基础镜像)。 我不太明白为什么。 也许有更好的方式发送到期刊?

docker journald输出日志选项有什么限制? 它没有出现,它支持的应用程序不仅仅是写消息字段。

所以我发现我需要-v /dev/log:/dev/log

但是还有另一个问题,那就是启动Docker容器的服务文件没有关联。 手动添加UNIT:servicename.service没有解决它。 所以当查看和运输服务的日志时,它与exe相关联,而不是与容器或服务相关联。 谁遇到过这些问题,你是如何解决这些问题的?

好吧,让我扩大一点。

AC程序可以这样写入systemd日志:

 #include <systemd/sd-journal.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[]) { sd_journal_send("MESSAGE=Hello World!", "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555", "PRIORITY=5", "HOME=%s", getenv("HOME"), "TERM=%s", getenv("TERM"), "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE), "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN), NULL); return 0; } 

这写入日记并添加像HOME,TERM,PAGE_SIZE等自定义字段。当我使用journalbeat将它们发送到ELK堆栈时,这些字段在elasticsearch中很好地结束,我可以直接search它们。

然而,看起来docker只是简单地接收应用程序的标准输出,并将其提供给journald,只添加几个字段。 例如CONTAINER_ID。

在Docker容器中使用像这样的程序,然后从服务文件运行它时,会产生一个小问题。

1)我必须通过一些目录和设备文件才能使用sd_journal_send来写入。

2)如果您从systemd .service文件启动容器,并期望使用journalctl -u servicename并查看消息,则不会看到这些日志消息,因为它们进入日志不同的路由,并且不会与运行它们的服务。

3)你可以使用docker的日志logging驱动添加一些任意的字段/标签,它们是固定的,一次添加将会出现在每个发送的消息上并且是不变的。 他们不是像我从上面的C代码想要的dynamic字段。

从本质上讲,日志logging驱动程序对我来说是不够的。

任何关于如何链接服务名称的build议,所以journalctl -u显示来自sd_journal_send的日志消息? 因为那样会修复它。

– 我find了一个解决scheme。 我会在下面的答案,以防其他人对我如何解决它感兴趣。

最终的解决scheme变得非常简单。

我转而写我的消息为纯json。 所以journalctl -u现在可以工作并显示现在包含json数据的MESSAGE字段。

然后我用journalbeat把它发送到logstash。

为了logstash.conf我添加了:

 filter { json { source => "message" } } 

它所做的是在将消息字段中的json数据发送到弹性search之前,将它们扩展到顶层的单独字段中。

关于logstash的jsonfilter的细节可以在这里find

您需要安装journald侦听的套接字。 在Ubuntu的情况下,它是/run/systemd/journal/socket 。 映射这个内部你的docker容器,它会正常工作

在你的示例代码中使用strace显示出来

 sendmsg(3, {msg_name(29)={sa_family=AF_LOCAL, sun_path="/run/systemd/journal/socket"}, msg_iov(23)=[{"CODE_FILE=test.c", 16}, {"\n", 1}, {"CODE_LINE=13", 12}, {"\n", 1}, {"CODE_FUNC=main", 14}, {"\n", 1}, {"MESSAGE=Hello World!", 20}, {"\n", 1}, {"MESSAGE_ID=52fb62f99e2c49d89cfbf"..., 43}, {"\n", 1}, {"PRIORITY=5", 10}, {"\n", 1}, {"HOME=/home/vagrant", 18}, {"\n", 1}, {"TERM=xterm-256color", 19}, {"\n", 1}, {"PAGE_SIZE=4096", 14}, {"\n", 1}, {"N_CPUS=1", 8}, {"\n", 1}, {"SYSLOG_IDENTIFIER=", 18}, {"a.out", 5}, {"\n", 1}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 208 

并使用下面的Ubuntu的docker集装箱testing它

 docker run -v /run/systemd/journal/socket:/run/systemd/journal/socket -v $PWD:/jd -it -w /jd ubuntu:16.04 ./a.out 

我在journalctl -f (在主机上)

 Aug 15 21:40:33 vagrant a.out[11263]: Hello World!