如果发生容器崩溃,pod 被驱逐,或 node 宕机,此时您仍然想访问到应用日志。这种情形下,日志应该具有独立的存储和生命周期,不依赖于 node, pods,或容器。
集群级日志方案需要一个独立的后台来存储,分析和查询日志。
节点级日志记录
会被container engine 捕获并且重定向到log driver. Log driver在k8s中配置以json格式写入文件。但是pod被驱逐,容器日志也会消失。
这个级别的日志,需要考虑日志的轮转,来保证日志不会消耗节点上所有的可用空间。k8s不负责轮转日志,而是通过部署工具来解决。比如,在k8s集群中,用kube-up.sh
部署一个每小时运行的工具logrotate
. 也可以设置容器runtime来自动地rotate log, 比如Docker的log-opt
选项. 后一种方式适用于 GCP 的 COS 镜像,而前一种方式适用于任何环境。这两种方式,默认日志超过 10MB 大小时触发日志轮转。
系统组件日志
有两种类型的系统组件,运行在容器中的和未运行在容器中的。例如:
- 运行在容器中的 Kubernetes scheduler 和 kube-proxy。
- 未运行在容器中的 kubelet 和容器 runtime,比如 Docker。
在使用 systemd 机制的服务器上,kubelet 和容器 runtime 写入日志到 journald。如果没有 systemd,他们写入日志到 /var/log 目录的 .log 文件。容器中的系统组件通常将日志写到 /var/log 目录,绕过了默认的日志机制。他们使用 glog 日志库。您可以在 development docs on logging 找到这些组件的日志告警级别协议。
和容器日志类似,/var/log 目录中的系统组件日志也应该被轮转,通过脚本 kube-up.sh 启动的 Kubernetes 集群,他们的日志被工具 logrotate 执行每日轮转,或者日志大小超过 100MB 时触发轮转。
集群级别日志架构
Kubernetes 并未提供原生的集群级记录日志方案,下列是常见的解决方案:
- 使用运行在每个节点上的节点级的日志代理。
- 在应用程序的 pod 中,包含专门记录日志的伴生容器。
- 在应用程序中将日志直接推送到后台。
节点级
日志代理是专门的工具,它会暴露出日志或将日志推送到后台。通常来说,日志代理是一个容器,这个容器可以访问这个节点上所有应用容器的日志目录。
因为日志代理必须在每个节点上运行,所以通常的实现方式为,DaemonSet 副本,manifest pod,或者专用于本地的进程。但是后两种方式已被弃用并且不被推荐。
对于 Kubernetes 集群来说,使用节点级的日志代理是最常用和被推荐的方式,因为在每个节点上仅创建一个代理,并且不需要对节点上的应用做修改。但是,节点级的日志 仅适用于应用程序的标准输出和标准错误输出。
使用伴生容器和日志代理
- 伴生容器将应用程序日志传送到自己的标准输出。
- 伴生容器运行一个日志代理,配置该日志代理以便从应用容器收集日志。