0
点赞
收藏
分享

微信扫一扫

EFK中filebeat读k8s容器日志丢失数据

天行五煞 2022-04-19 阅读 71

问题: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,最小不能小于1s

举报

相关推荐

0 条评论