假设我在Docker中部署了一个Java Web应用程序,其中有几个组件在容器内生成日志:

  • Web应用程序本身,记录到STDOUTSTDERR
  • 应用程序服务器,记录到server.log
  • JVM,将GC事件记录到gc.log
  • 其他,例如底层Linux操作系统

  • 应用程序日志被路由到Splunk,但是我们应该如何检索其他组件的日志?

    似乎至少有两个选择:
  • 将所有内容记录到STDOUT。这是不理想的,因为这会混合日志并产生更难以分离的输出,因为不同的组件会产生不同格式的日志。
  • 对主进程以外的每个进程都使用sidecar容器,并让这些sidecar从例如server.loggc.log,并将它们通过管道传递到STDOUT。更好,但这会对磁盘使用产生重大影响。

  • 有更好的解决方案吗?

    最佳答案

    TLDR;不要混用日志流,使用Sidecar是更好的解决方案,并且对磁盘使用率没有“重大影响”。使用边车将日志重定向到stdout,并依靠容器生态系统读取单个容器日志的能力。
    注意:具有日志重定向逻辑的Sidecar不会产生大量开销。我引用Kubernetes documentation来支持此操作-“重定向日志的逻辑极小,因此开销不大”

    关键是不要混淆日志流,因为如果不是不可能的话,以后从混合日志流中分离单个流可能是乏味的(带有跨多行的异常堆栈跟踪之类的日志事件)。例如,如果您混合了日志流,则要分析GC,您需要先将GC日志事件单独分离出来,然后再将其输入到您选择的工具中。
    解决方案是使用side-car pattern,并带有示例here进行详细说明
    关注Single Responsibility Principle。每个sidecar尾部都有一个日志文件,并将其流式传输到stdout。为了实现这一点,所有小汽车都应该可以访问webapp容器的日志卷挂载(例如/ var / log),并且webapp应该将其所有日志写入共享卷挂载。
    该Web应用程序会将自己的日志写入stdout(通过LogBack或Log4j的ConsoleAppender说)以及共享卷挂载下的任何其他其他日志文件(例如/ var / log)。例如,对于GC日志,设置JVM参数,以使日志在共享卷挂载-Xloggc:/var/log/mywebapp/gc.log下生成。
    对于每个其他日志文件,您都需要将sidecar尾部(重定向)日志记录到stdout。因此,在您的情况下,您将需要三个辅助工具,一个用于gc.log,一个用于server.log,另一个用于/ var / log / syslog
    下面给出了示例性边车集装箱定义摘录。

      - name: count-log-1
        image: busybox
        args: [/bin/sh, -c, 'tail -n+1 -f /var/log/mywebapp/gc.log']
        volumeMounts:
        - name: varlog
          mountPath: /var/log
    
    上面的示例显示了一个从/ var / log共享卷安装到stdout的重定向/尾部日志文件的单个sidecar定义。该示例是从this Kubernetes documentation复制而来的。

    关于java - 如何从单个Docker容器捕获多个日志流?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60452635/

    10-12 04:40
    查看更多