来自多进程Docker容器的日志记录

21

我正在使用Nginx方法将符号链接链接到/dev/stdout,以便任何要在“docker logs”中显示的日志文件都可以出现,但是这似乎无效。

我已经在/etc/crontab中测试过这个简单的cronjob,如果存在符号链接(指向/dev/stdout),它不会写入任何内容(据我所知),但是如果我删除符号链接,则会写入文件。

另外,如果我echo到/dev/stdout,它会被回显到命令行,但在'docker logs'中找不到...

问题:这应该起作用吗?(似乎在nginx中起作用)。否则,如何使'secondary'进程的日志出现在docker logs中。

参考:

Nginx Dockerfile显示了符号链接的方法:https://github.com/nginxinc/docker-nginx/blob/a8b6da8425c4a41a5dedb1fb52e429232a55ad41/Dockerfile

为此创建了一个官方的错误报告:https://github.com/docker/docker/issues/19616

我的Dockerfile:

FROM ubuntu:trusty
#FROM quay.io/letsencrypt/letsencrypt:latest # For testing

ENV v="Fri Jan 22 10:08:39 EST 2016"

# Setup the cronjob
ADD crontab /etc/crontab
RUN chmod 600 /etc/crontab

# Setup letsencrypt logs
RUN ln -sf /dev/stdout /var/log/letsencrypt.log
# Setup cron logs
RUN ln -sf /dev/stdout /var/log/cron.log
RUN ln -sf /dev/stdout /var/log/syslog

# Setup keepalive script
ADD keepalive.sh /usr/bin/keepalive.sh
RUN chmod +x /usr/bin/keepalive.sh

ENTRYPOINT /usr/bin/keepalive.sh

定时任务文件:

* * * * * root date >> /var/log/letsencrypt.log

保持连接脚本 keepalive.sh

#!/bin/bash

# Start cron
rsyslogd
cron

echo "Keepalive script running!"

while true; do

    echo 'Sleeping for an hour...'
    sleep 10

done

1
你有什么问题? - Sobrique
哈...谢谢你,看到编辑了! - geekscrap
1
我已经放弃在容器中管理日志,而是尽可能通过logstash传输到elasticsearch。虽然有一些设置开销,但总体上要少得多痛苦。 - Sobrique
好的,那么作为另一种选择,你有关于那个设置的任何参考资料吗?未来我打算集成一个ELK堆栈... - geekscrap
你的“keepalive.sh”脚本是否运行cron守护进程? - Mark O'Connor
是的,在keepalive.sh文件中的第5行 :) - geekscrap
2个回答

10

最终结果是cron作业的/dev/stdout指向了另一个设备。

/proc/self/fd/1应该是/proc/1/fd/1,因为docker只期望运行一个进程并监视其stdout。

所以,一旦我修改了符号链接,使其指向/proc/1/fd/1,事情应该就能完成,但是主机上的apparmor实际上拒绝了这些请求(并在将内容回显到/proc/1/fd/1时出现权限错误),因为默认的docker配置文件会生成(但可以使用--security-opts进行修改)。

在克服apparmor障碍后,所有操作都正常工作!

尽管如此,在查看需要修改的apparmor内容后,我决定使用下面展示的mkfifo方法。

Dockerfile

FROM ubuntu:latest

ENV v="RAND-4123"

# Run the wrapper script (to keep the container alive)
ADD daemon.sh /usr/bin/daemon.sh
RUN chmod +x /usr/bin/daemon.sh

# Create the pseudo log file to point to stdout
RUN mkfifo /var/log/stdout
RUN mkfifo /var/log/stderr

# Create a cronjob to echo into the logfile just created
RUN echo '* * * * * root date 2>/var/log/stderr 1>/var/log/stdout' > /etc/crontab

CMD "/usr/bin/daemon.sh"

daemon.sh

#!/bin/bash

# Start cron
cron

tail -qf --follow=name --retry /var/log/stdout /var/log/stderr

1
提供的解决方案 /proc/1/fd/1 对我很有用。但是我卡在"权限错误"上了,请问您是如何解决使用--security-opts修改docker配置文件的问题的?(当向/proc/1/fd/1回显时,会出现权限错误,这是由于默认docker配置文件(自动生成但可用--security-opts修改)引起的。)需要知道哪些更改可以解决这些权限错误。代码片段会很有帮助。 - Kumar Basapuram
提供的解决方案是什么?你说得好像这个答案中有任何解决方案,而且你说它起作用了,但我没有看到任何解决方案。最终结果是cron作业的/dev/stdout指向了不同的设备。/proc/self/fd/1应该是/proc/1/fd/1这是什么意思?在整个问题回答线程中都没有提到“/proc/self/fd/1”。 - Alex A

3

好的,评论中提到过,但为了参考 - 我发现最好的解决方案是通常依赖于“标准”的多系统日志记录机制 - 尽可能使用 syslog

这是因为您可以在主机上使用内置的 syslogd,或者使用 logstash 作为 syslogd。它有一个内置的过滤器,但实际上往往会遇到不够灵活的问题,因此我使用 TCP/UDP 监听器,并显式解析日志 - 如 "当 logstash 和 syslog 出现问题时" 所述。

input {
  tcp {
    port => 514
    type => syslog
  }
  udp {
    port => 514
    type => syslog
  }
}

然后过滤日志:

filter {
  if [type] == "syslog" {
    grok {
      match => { "message" => "<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }
    }
    syslog_pri { }
  }
}

你可以将这个logstash传送到elasticsearch - 可以在远程主机、本地容器或者像我现在正在做的那样使用一个多节点elasticsearch实例的docker网络。 (我使用下载和docker文件自己制作了一个,但我相信也存在独立的容器)。
output { 
   elasticsearch {
      hosts => [ "es-tgt" ]
   }
}

这里的优势在于,Docker允许您使用--link--net来指定您的elasticsearch容器的名称,因此您可以将logstash配置别名指向正确的位置。(例如:docker run -d --link my_es_container_name:es-tgt -p 514:514 -p 514:514/udp mylogstash或只需docker run --net es_net ....) Docker网络设置略微复杂,因为您需要设置一个键值存储(我使用了etcd,但其他选项也可用)。或者您可以像使用Kubernetes一样做一些事情。
然后使用kibana进行可视化,再次暴露kibana端口,但转发到elasticsearch网络以与集群通信。

但是一旦设置完成,您可以配置 nginx 记录到syslog,以及您想要定期捕获日志结果的任何其他内容。我认为真正的优势在于,您正在使用单个用于日志记录的服务,该服务可以根据您的需求进行扩展(感谢网络/容器化)。


谢谢你的回复,但我真正想要的是解决将日志记录到/dev/stdout的主要问题的答案。不过我现在可能已经找到了,正在测试中。 - geekscrap
没问题。你只需要在注释中提到它,所以我想插一句话。 - Sobrique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接