结构化日志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!