引言
在维护 ELK (Elasticsearch, Logstash, Kibana) 日志系统时,一个常见的线上事故是下游的 Elasticsearch 因磁盘空间耗尽而无法接收新的日志。这会导致上游的 Filebeat 和 Logstash 出现数据积压。当磁盘问题解决后,我们通常不希望重新处理这些积压的、可能已经失去时效性的日志,而是希望从当前时间点开始恢复日志采集。本文将详细介绍如何处理此类事故,核心在于让 Filebeat 跳过积压的日志。
事故场景:Elasticsearch 磁盘写满导致日志积压
问题描述: 日志系统链路为 Filebeat -> Logstash -> Elasticsearch。Elasticsearch 因磁盘满了,导致服务中断两小时。现在磁盘空间已清理,服务恢复,但 Filebeat 开始从两小时前中断的位置重新发送日志。我们希望丢弃这两个小时的积压日志,直接从当前时间开始采集。
核心解决方案:重置 Filebeat 的读取位置
问题的关键在于 Filebeat 会持久化记录每个日志文件的读取进度(offset)。即使下游服务中断,Filebeat 也会在原地等待,一旦连接恢复,它会从上次记录的位置继续发送。要跳过积压的日志,我们必须重置这个进度记录。
第一步:暂停日志采集服务
在进行任何修改之前,务必先停止 Filebeat 和 Logstash,防止在操作过程中产生新的状态文件或数据冲突。
1 | # 停止 Logstash |
第二步:清理 Filebeat 状态文件
Filebeat 将其状态(包括每个文件的读取偏移量)记录在一个名为 registry 的目录中。删除这个目录是让 Filebeat "忘记" 旧进度的最直接方法。
方法 1:删除状态文件(推荐)
定位
registry目录该目录通常位于 Filebeat 的数据路径下,例如
/var/lib/filebeat/registry或/usr/share/filebeat/data/registry。请根据你的实际安装情况确认路径。删除状态文件
1
2
3# 警告:此操作会使 Filebeat 丢失所有文件的读取记录
# 请确认路径正确后再执行
rm -rf /var/lib/filebeat/registry
效果:删除 registry 目录后,下次启动 Filebeat 时,它会认为所有日志文件都是第一次处理,并默认从文件的末尾开始读取新内容。这恰好满足了我们"跳过旧日志"的需求。
方法 2:手动修改状态文件
如果不想删除状态文件,可以手动修改文件中的偏移量,使 Filebeat 从日志文件末尾开始读取:
1 | # 路径需要根据实际情况确认 |
找到相关日志文件的偏移量,将其更新为文件的最后偏移值。
第三步:重启服务并验证
完成状态清理后,按顺序重启服务。
1 | # 先启动 Filebeat |
验证效果
检查 Filebeat 日志:观察 Filebeat 的日志,确认它是否已经开始监控文件的新增内容,而不是从头读取。
1
tail -f /var/log/filebeat/filebeat.log
检查 Elasticsearch 索引:在 Kibana 或通过 API 检查 Elasticsearch,确认只有最新的日志被写入,没有旧的积压日志。
1
curl -X GET "http://localhost:9200/_cat/indices?v"
其他可选方案与注意事项
方案二:在 Logstash 中过滤旧日志
如果不想或不能直接删除 Filebeat 的 registry 文件,也可以在 Logstash 层面添加一个过滤器,丢弃时间戳早于某个时间点的日志。
在 Logstash 的 filter 配置中添加以下 Ruby 过滤器:
1 | filter { |
缺点:这种方法会增加 Logstash 的处理负担,因为它需要接收并判断每一条积压的日志,然后才能丢弃。相比之下,直接在 Filebeat 层面解决效率更高。
注意事项
备份:在执行
rm等破坏性操作前,最好先备份registry目录,以防操作失误需要回滚。测试日志:如果 Filebeat 重启后没有立即发送新日志,可能是因为被监控的日志文件没有新内容写入。你可以手动追加一行测试日志来触发采集。
1
2# /path/to/logfile.log 为具体抓取日志路径
echo "Dummy log for testing" >> /path/to/logfile.log磁盘监控与 ILM:为避免类似事故再次发生,务必为 Elasticsearch 配置磁盘使用率告警,并设置索引生命周期管理(ILM)策略来自动管理旧索引,防止磁盘被写满。
总结
处理因下游服务中断导致的 Filebeat 日志积压问题,最有效的方法是停止 Filebeat,删除其 registry 状态目录,然后重启服务。这能让 Filebeat 直接从日志文件的末尾开始采集,从而跳过所有积压的日志。虽然也可以在 Logstash 层面过滤,但从源头(Filebeat)解决是更推荐的最佳实践。
