【发布时间】:2018-06-03 13:26:12
【问题描述】:
当我跑步时
$ kubectl logs <container>
我得到了我的 pod 的日志。
但是这些日志的文件在哪里?
一些消息来源说 /var/log/containers/ 其他人说 /var/lib/docker/containers/ 但我找不到我的实际应用程序或 pod 的日志。
【问题讨论】:
标签: logging kubernetes kubectl kubelet
当我跑步时
$ kubectl logs <container>
我得到了我的 pod 的日志。
但是这些日志的文件在哪里?
一些消息来源说 /var/log/containers/ 其他人说 /var/lib/docker/containers/ 但我找不到我的实际应用程序或 pod 的日志。
【问题讨论】:
标签: logging kubernetes kubectl kubelet
简答:
如果您使用 Docker,则每个容器中的 stdout 存储在 /var/lib/docker/containers 中。但是 Kubernetes 也创建了一个目录结构来帮助你找到基于 Pod 的日志,所以你可以在 /var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/ 的一个节点上找到每个 Pod 的容器日志。
更长的答案:
Docker 从每个容器中捕获stdout 日志并将它们存储在主机上的/var/lib/docker/containers 中。如果 Kubernetes 使用 Docker 作为容器运行时,Docker 也会将容器日志存储在 Kubernetes 节点上的那个位置。但由于我们不直接在 Kubernetes 中运行容器(我们运行 Pods),因此 Kubernetes 还创建了 /var/log/pods/ 和 /var/log/containers 目录来帮助我们更好地基于 Pods 组织日志文件。
/var/log/pods/ 中的每个目录都存储单个 Pod 的日志,每个目录都使用 <namespace>_<pod_name>_<pod_id> 结构命名。
您可以通过运行
kubectl get pod -n core gloo-76dffbd956-rmvdz -o jsonpath='{.metadata.uid}'来获取 Pod 的 ID。如果您习惯使用yq,您可能会发现运行kubectl get pod <pod_name> -o yaml | yq r - metadata.uid更直接。
在每个/var/log/pods/<namespace>_<pod_name>_<pod_id>/ 目录中都有多个目录,每个目录代表 Pod 中的一个容器。这些目录的名称与容器的名称相同。最后,当我们查看/var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/ 目录时,我们会在/var/lib/docker/containers 中找到指向Docker 存储的日志文件的符号链接。
同样,/var/log/containers/ 目录中包含指向/var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/ 目录的符号链接。这些符号链接使用<pod_name>_<namespace>_<container_id> 结构命名。
【讨论】:
你在这些目录中看到什么了吗?
在我的集群中,来自每个 pod 的 stdout/stderr 日志位于 /var/log/containers,但是有一些链接/重定向:
/var/log/containers/<pod-name>_<namespace>_<container-name-container-id>.log -> /var/log/pods/<some-uuid>/<container-name>_0.log
该日志实际上链接到/var/lib/docker:
<container-name>_0.log -> /var/lib/docker/containers/<container-id>/<container-id>-json.log
【讨论】:
磁盘文件名来自
docker inspect $pod_name_or_sha | jq -r '.[0].LogPath'
假设 docker daemon 的配置是默认的 {"log-driver": "json-file"},如果 kubectl logs 行为正确,则几乎可以保证为真。
这也是不言而喻的,但是您必须在为 docker inspect 安排 Pod 的节点上,或者在磁盘上四处寻找日志文件的存在,以做任何有用的事情。 kubectl describe pod $pod_name 将呈现节点名称,或者您可能怀疑它会在 kubectl get -o json pod $pod_name 中,如果您希望以编程方式获取它。
【讨论】:
LogPath 是空的。你知道我是否缺少一些配置吗?如何正确设置LogPath?
docker inspect pod-or-sha | jq '.[0].HostConfig.LogConfig';另外,知道那个是否与其他的不同甚至可能会很有趣,所以:docker inspect $(docker ps -aq) | jq '.[].HostConfig.LogConfig'
.[0].HostConfig.LogConfig 设置为 {"Type": "journald","Config": {}}
/var/log/journal/$(cat /etc/machine-id) 中,但这只是迂腐的答案,因为这些文件是二进制文件;日志内容可通过journalctl -u ${container_unit} 访问,但我没有经验知道${container_unit} 是什么。 systemctl list-units 应提供容器单元名称。
这取决于k8s版本:
/var/log/pods/<pod_id>/<name>/<num>.log
/var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/<num>.log(请参阅此PR)上面两个符号链接到 docker 文件的文件,例如/var/lib/docker/containers/<container-id>/<container-id>-json.log.
例如:
【讨论】:
日志由每个节点上的 kubelet 管理。当您运行 kubectl logs <pod> 时,它会将请求传递给您的 pod 正在运行的节点上的 kubelet,并读取关联的日志文件。
可以看到架构here
【讨论】: