本文简单整理 Kubernetes 里关于容器应用日志的四种收集方式。
首先解释下容器日志原则:
下面整理几种日志收集方案:
最直接的方式,在编写应用的时候,就直接指定好日志的存储后端,如下所示:
在这种方案下,Kubernetes 就完全不必操心容器日志的收集了。但这仅适用于本身已经有完善的日志处理系统的公司。
这个方案,在社区里是最常用的一种。
在 Node 上部署 logging agent(一般都会以 DaemonSet 的方式运行),将日志文件转发到后端存储里保存起来。
过程解释:
优点与不足:
最大的优点在于一个节点只需要部署一个 agent,并且不会对应用和 Pod 有任何侵入性。
不足之处就在于,它要求应用输出的日志,都必须是直接输出到容器的 stdout 和 stderr 里。因为 stdout 的数据会默认输出到容器之外的宿主机,但如果日志直接输出到了容器内的某个文件里,或者输出到了远程存储里,就不适用了。
这种方案针对容器应用产生的日志不输出到 stdout/stderr 上的特殊情况。但实际上存在两份相同的日志文件,浪费磁盘空间。
通过一个 sidecar 容器把日志文件重新输出到 sidecar 的 stdout 和 stderr 上,然后再利用 logging agent 将日志文件转发到后端。
过程解释:
分析:
此方案的额外性能损耗虽然并不高,也就是 sidecar 多占用一点 CPU 和内存罢了。但需要注意的是,这时候宿主机上实际上会存在两份相同的日志文件:一份是应用自己写入的;另一份则是 sidecar 的 stdout 和 stderr 对应的 JSON 文件。这对磁盘是很大的浪费。
所以,除非万不得已或者应用容器完全不可能被修改,其他不推荐使用此方案
通过一个 sidecar 容器,直接把应用的日志文件发送到后端远程存储里面去。
这种方案也可以处理容器应用产生的日志不输出到 stdout/stderr 上的特殊情况,但这个 sidecar 容器会消耗较多的资源,甚至拖垮应用容器。
综合对比以上几种方案,建议将应用日志输出到 stdout 和 stderr,然后通过在宿主机上部署 logging-agent 的方式来集中处理日志。这种方案不仅管理简单,kubectl logs 也可以用,而且可靠性高,并且宿主机本身,很可能就自带了 rsyslogd 等非常成熟的日志收集组件来供你使用。
图片均来自于张磊老师极客时间课程《深入剖析 Kubernetes》,也是本文的主要参考资料