记一次EFK采集不到k8s日志数据的解决过程

960 阅读2分钟

趁热记录下,给未来的自己

背景

本地部署了两套 k8s 环境:开发和预生产。为了方便开发同学调试,需要将 k8s 的业务日志通过 EFK 框架输出到 WEB 端查看。

部署架构:

  • elastic search 和 kibana 是部署在 k8s 集群外,
  • filebeat 以 daemonset 的方式部署在 k8s 的 node 节点上。

现象

同一份 filebeat-k8s.yml 文件,在开发集群上可以成功部署且在 Kibana 上能采集到对应的日志。但是在预生产集群上部署成功后,无法在 Kibana 上看到日志。

解决过程

首先,对比了 filebeat 在开发和预生产 node 节点上的日志,发现前者含有 [input.harvester] Collection to backoff established 日志,而后者没有。这说明,后者没有采集到数据,所以没有向 elastic search 发送数据。

定位到了具体问题,那么接下来要解决的是,为什么预生产 node 节点上的 filebeat 无法采集 docker 日志呢?

到这里,我突然想起来,预生产和开发集群最大的区别在于: docker 安装目录不同

  • 开发集群的 docker 安装在默认位置: /var/lib/docker;
  • 预生产的 docker 安装在了 /home/ops/docker 。

这么做的目的是,将 docker 从较小的系统盘移到了较大的数据盘上,以便放更多的日志。没想到给自己埋下了一个大坑。。。

为了验证猜测,进入预生产的 filebeat 容器, 查看 /var/log/container 目录下的内容,发现全是红色的,表示挂载失败:

用 ls -la 命令查看了下,发现这些文件软链接于 /var/log/pods

于是,又进入 /var/log/pods,ls -la 发现,该目录下的log文件又软链接于 /home/ops/docker 目录

而 /home/ops/docker 目录在容器中并不存在!至此,找到了根本原因。那么可以修改 filebeat-k8s.yml 里 DeamonSet 资源的 volume 和 volumeMounts 如下:

volumeMounts:
- name: varlibdockercontainers
  # 容器内的目录
  mountPath: /home/ops/docker/containers
  readOnly: true
volumes:
- name: varlibdockercontainers
  # 宿主机上的目录
  hostPath:
   path: /home/ops/docker/containers

总结

k8s里 docker 的日志链路关系:

  • 默认docker安装目录: /var/log/container/.log --> /var/log/pods//.log --> /var/lib/docker/containers//*.log
  • 本文预生产docker安装目录: /var/log/container/.log --> /var/log/pods//.log --> /home/ops/docker/containers//*.log

Done