为了账号安全,请及时绑定邮箱和手机立即绑定

运行在k8s中的容器如何读取自己的日志?

运行在k8s中的容器如何读取自己的日志?

Go
胡说叔叔 2023-03-07 14:04:35
我有一个设计为作为 K8s 应用程序运行的应用程序,它导入了一些运行 s 的依赖项(我不拥有)exec.Cmd。这很好,除了我想捕获那些日志。出于某种原因,当我这样做时:r := bufio.NewReader(os.Stdout) ... line, err := r.ReadString('\n')抛出一个错误,说这/dev/stdout是一个bad file descriptor. 怎么会这样?这不是控制台输出的标准本地目标吗?kubectl logs似乎能够捕获输出,更具体地说,我们的中央日志转发器也能够捕获它。但是尝试从实际生成这些日志的容器内的 kube API 服务器捕获日志似乎有点愚蠢……有没有更好的方法来做到这一点?
查看完整描述

2 回答

?
SMILET

TA贡献1796条经验 获得超4个赞

通常,stdin是一个只读流,用于检索写入程序的输入,而stdout是一个只写流,用于发送程序编写的输出。换句话说,没有人可以从 /dev/stdout 读取,除了 Chuck Norris。


默认情况下,stdout“指向”您的终端。但是可以stdout从您的终端重定向到一个文件。此重定向是在您的程序启动之前设置的。


通常会发生以下情况:容器运行时将容器进程重定向stdout到运行容器的节点上的文件(例如,/var/log/containers/<container-name>-<container-id>.log)。当您使用 请求日志时kubectl logs,kubectl 连接到 kube-apiserver,它连接到运行容器的节点上的 kubelet,并要求它从日志文件发回内容。


另请查看https://kubernetes.io/docs/concepts/cluster-administration/logging/,其中解释了各种日志记录设计方法。


从安全性和可移植性的角度来看,您绝对不会实施的解决方案是hostPath在您的容器中添加一个挂载,挂载/var/log/containers您的节点目录并直接访问容器日志。


一个合适的解决方案可能是更改图像的命令并将输出写入stdout容器以及容器内的本地文件。这可以使用命令来实现tee。然后您的应用程序可以从该文件中读回日志。但请记住,如果没有适当的轮换,日志文件将不断增长,直到您的容器终止。


apiVersion: v1

kind: Pod

metadata:

  name: log-to-stdout-and-file

spec:

  containers:

  - image: bash:latest

    name: log-to-stdout-and-file

    command: 

    - bash

    - -c

    - '(while true; do date; sleep 10; done) | tee /tmp/test.log'

稍微复杂一点的解决方案是,将容器中的日志文件替换为使用mkfifo. 这避免了文件大小不断增长的问题(只要您的应用程序不断从命名管道文件中读取日志)。


apiVersion: v1

kind: Pod

metadata:

  name: log-to-stdout-and-file

spec:

  # the init container creates the fifo in an empty dir mount

  initContainers:

  - image: bash:latest

    name: create-fifo

    command: 

    - bash

    - -c

    - mkfifo /var/log/myapp/log

    volumeMounts:

    - name: ed

      mountPath: /var/log/myapp


  # the actual app uses tee to write the log to stdout and to the fifo

  containers:

  - image: bash:latest

    name: log-to-stdout-and-fifo

    command: 

    - bash

    - -c

    - '(while true; do date; sleep 10; done) | tee /var/log/myapp/log'

    volumeMounts:

    - name: ed

      mountPath: /var/log/myapp


  # this sidecar container is only for testing purposes, it reads the

  # content written to the fifo (this is usually done by the app itself)

  #- image: bash:latest

  #  name: log-reader

  #  command: 

  #  - bash

  #  - -c

  #  - cat /var/log/myapp/log

  #  volumeMounts:

  #  - name: ed

  #    mountPath: /var/log/myapp


  volumes:

  - name: ed

    emptyDir: {}


查看完整回答
反对 回复 2023-03-07
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

您应该将具有主/应用容器和日志容器的多容器 pod 视为从主/应用容器读取日志的边车容器。考虑以下链接中的示例,该示例显示了如何从主容器中跟踪日志

https://learnk8s.io/sidecar-containers-patterns


查看完整回答
反对 回复 2023-03-07
  • 2 回答
  • 0 关注
  • 352 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号