「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 space 和 docker 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
修改这个前缀。