「Bug」Fluentd 的 Buffer 占用超过 13G 存储,导致 K8s 节点 DiskPressure

问题

某天,突然发现 k8s 集群有大量的 evicted 记录,排查发现某节点 Fluentd 的 Buffer 占用超过 13G 存储,导致 K8s 节点 DiskPressure.

排查

K8s 默认在 Node 的可用存储空间低于 85% 时触发 DiskPressure,尝试清理空间,驱逐 Pod。

查找 Fluentd 官方文档:Fluentd - Config: Buffering parameters 发现,File 模式下 Buffer 的 total_limit_size 默认值为 64GB,而我的 Node 节点总存储才 30G。

很可能是因为做为存储的 ElasticSearch 出问题下线了,导致日志堆积在 Buffer 中,存储被 Buffer 侵占。

因此需要根据机器存储的大小修改 total_limit_size,查看 fluentd-kubernetes-daemonset 的 fluent.conf 发现它有将各参数以环境变量的方式暴露出容器。
但是没有 total_limit_size 这个参数,只有旧的 queue_limit_length,对应的环境变量为 FLUENT_ELASTICSEARCH_BUFFER_QUEUE_LIMIT_LENGTH,可以通过设置这个环境变量来修改 buffer 上限。

fluentd 的官方 k8s 配置文件:fluentd-daemonset-elasticsearch.yaml,按照前面给的 fluent.conf 中的配置设置环境变量, 就可以修改 fluentd 的各项参数,比如 es 索引的前缀 FLUENT_ELASTICSEARCH_LOGSTASH_PREFIX.

画外:Fluentd 的日志抓取策略

我们开发集群的日志被抓取到 ElasticSearch 后,每晚会执行一次数据清理(通过 ES API 删除索引),只保留最近三天的日志,以保证日志服务器(ES)一直可用。

但是有一个现象,日志清理脚本刚刚跑完,这时只剩三个 ES 索引(以日期为索引),可刚过一会儿,往期的日志立马又被 Fluentd 抓了进来。前面七八天的日志索引又回来了。
这让我们有点摸不清 Fluentd 的抓取策略和 Kubernetes Pod 的日志输出策略。

几个问题:

1. Kubernetes 的容器日志有没有 rotate 上限?这个上限是多少?

查询发现 Kubernetes 目前没有任何容器日志大小限制,相关 issue 包括 Docker daemon logs filled node disk spacedocker container log does not get rotate on k8s master node causes host to run out of space quickly

目前的建议是修改 /etc/docker/daemon.json,设置节点层级的 log size limit。

2. Fluentd 的日志抓取策略是怎样的?它会监控后端 ES 索引的内容么?还是说它每次都在全量扫描所有容器日志?

查看 fluentd-kubernetes-daemonset 的 kubernetes.conf 发现,它使用 type: tail 进行日志的抓取。

这种抓取方式只抓取最新的行,并且会记录下当前的位置(记录在文件 /fluentd/log/xxx.pos 中)。如果日志被 rotated 了,fluentd 会从头开始读取日志。

至于为何手动删除掉所有已经同步好的 ES 数据后,Fluend 新同步的数据里,为何还存在旧数据(七八天前的日志都可能被同步过来)?这个我也还没搞清楚。。。待研究。

设置 Fluend 的 ES 索引名称

查看 fluentd+elasticsearch 的官方 k8s 配置文件:fluentd-daemonset-elasticsearch.yaml,发现它默认启用 logstash_format,以方便地和 ES+Kibana 协作。

Fluentd 默认使用 logstash 为 ES 索引的前缀,可以通过设定环境变量 FLUENT_ELASTICSEARCH_LOGSTASH_PREFIX 修改这个前缀。

posted @ 2020-03-09 13:50  於清樂  阅读(2203)  评论(2编辑  收藏  举报