filebeat采集日志存在日志丢失的情况
filebeat搜集的速度跟不上日志打印的速度
问题:filebeat读取k8s container日志,生产到kafka过程中,出现丢数据。如下图实际生产了1w+日志,但只生产了5746条
定位:
因为是EFK流程,首先,需要确定是生产还是消费出现了问题,直接kafka命令行使用另外的消费组消费同一topic的kafka数据,得出的数据与kibana查的数据一致,说明消费没问题。
其次,因日志映射到host-path,同时在stdout也有打印(默认存储到了/data/lib/docker/containers/${data.kubernetes.container.id}/*.log),故对比host-path存储的数据与/data/lib/docker/containers/${data.kubernetes.container.id}/*.log数据,发现二者数据量不一致,说明是在收集过程中input的问题。
于是通过谷歌【filebeat 丢数据】,联想到是否有文件句柄被打开和未及时释放的问题,可知原因主要如下:
1)当harvester不可用时,文件被删除
2)对于轮询文件,轮询速度的超过了处理的速度
3)inode重新利用,新文件起始位置继续使用旧文件的开始记录位置导致
1.模拟单个pod只打印日志,判断harvester是否有问题
如下图,echo了2w到stdout,kibana获取到了2w条,说明harvester没问题
2.继续排查第二个增加并行work数
修改filebeat.yml,貌似没用(压测过程磁盘写入20M/s左右,cpu 2000m基本用满,有数据丢失。明天扩容cpu再测试)
partition.round_robin:
reachable_only: true
work: 9
timeout: 30s
broker_timeout: 10s
bulk_max_size: 2048
required_acks: 0
compression: gzip
compression_level: 4
max_message_bytes: 1000000
keep_alive: 60
3.观察日志文件inode
在压测过程中,进一步观察/data/lib/docker/containers/${data.kubernetes.container.id}/*.log数据,可以看到(第一列为inode文件标识),日志到达50m左右后在不停的rotate,inode也在被操作系统复用循环使用。怀疑是新文件起始位置继续使用旧文件的开始记录位置导致漏读新文件起始位置前的内容
可能是这个原因:
所以需要在inode被操作系统循环使用到新文件前,让filebeat把文件内容读取完。
有两种方式:
1)方法一:修改docker rotate的文件大小,由原始的50m修改为500m,以降低日志rotate滚动频率
通过查看docker配置文件可知,默认设置了单文件最大50m,最多保存5个文件
cat /etc/docker/daemon.json
{
"insecure-registries": ["dke-registry:5000"],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "50m",
"max-file": "5"
},
"data-root": "/data/lib/docker",
"iptables": false,
"bip": "192.168.42.1/24"
}
2)方法二:修改filebeat的scan_frequency
scan_frequency默认为10s,按20m/s写入文件,上限50m,2.5s就写完了,而filebeat需要10s后才轮询到文件,导致出现文件不能被Filebeat的input模块扫描到,从而造成数据丢失。所以需要加大scan_frequency的执行频率,时间间隔由默认的10s减少到1s(有的博客说可以设置为0s,但实际启动不了)。
注意:增加扫描频率后,需要观察cpu的使用情况,根据情况适当增加pod cpu逻辑核
结论:
1)调整docker日志滚动策略,降低日志滚动频率
2)加大扫描频率,即减小scan_frequency,需要大于0s
20220419
5000qps压测3500w+数据,本地日志数量与kafka生产数量&ES落库数量完全一致。在20220418基础上做的主要操作如下:
1)改 /etc/docker/daemon.json max-size 到 500m max-file改为10, 重启docker: systemctl restart docker
2)filebeat pod CPU资源加到8c,config中scan_frequency改成0.01s
3)logstash input的consumer_threads改成30,启动命令加-w 64 ,即增加worker线程数为64个(用于output和filter)
4)kafka topic的partition由9增加到15,单个partition的传输速率由1M/s 增加到 3M/s
参考
FileBeat系列:数据丢失的情况:https://blog.51cto.com/NIO4444/3840849
filebeat数据重复和截断及丢失问题分析:http://niyanchun.com/filebeat-truncate-bug.html
filebeat工作原理:https://blog.csdn.net/zzl394935072/article/details/104629516
docker container如何支持日志rotate https://www.codeleading.com/article/78991029920/