从 docker 容器内结构化日志记录到日志

2023-11-26

从 docker 容器内将结构化日志写入日志的最佳方法是什么?

例如,我有一个使用以下方式编写的应用程序sd_journal_发送我没有尝试更改应用程序,而是尝试通过

-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 相关联,但与容器或服务无关。谁遇到过这些问题,您是如何解决的?

-- 好吧,让我扩展一下。

C 程序可以像这样写入 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 中,我可以直接搜索它们。

然而,docker 似乎只是简单地获取应用程序的标准输出,并将其提供给日志,仅包含它自己添加的几个字段。例如CONTAINER_ID。

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

1)我必须传递一些目录和设备文件才能使用 sd_journal_send 进行写入。

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

3)您可以使用docker的journald日志记录驱动程序添加一些任意字段/标签,它们是固定的,一次性添加,将出现在发送的每条消息上并且不变。它们不是我想要的上面 C 代码中的动态字段。

本质上,journald 日志驱动程序在我的情况下是不够的。

关于如何链接服务名称以便journalctl -u 显示来自sd_journal_send 的日志消息有什么建议吗?这样就可以解决问题了。

-- 我找到了解决方案。我将把答案放在下面,以防其他人对我如何解决它感兴趣。


您需要在其上安装插座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 容器中测试它

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

从 docker 容器内结构化日志记录到日志 的相关文章

随机推荐