测试 Worker 节点日志与结果清理问题分析报告
背景
测试环境由 200 多个相互独立的 Worker 节点组成,每个节点通过统一镜像构建后部署在云平台上。每个 Worker:
- 拥有独立的 20G 根分区
- 在本地生成各自的测试执行结果(存放于
/nas/results/executions) - 各自运行一份同步进程,将结果同步到结果展示服务
- 各自运行一份定时清理程序,清理本地旧数据
本报告针对排查过程中发现的多个问题进行汇总分析。
问题一:Metricbeat 持续产生无效日志
现象
系统日志中持续出现 Metricbeat 连接失败的错误,表现为 DNS 解析失败,重连尝试次数持续累积(从 1500 多次增长到 5300 多次)。
原因
Metricbeat 是旧监控方案(基于 Elasticsearch + Kibana)中的指标采集器,用于采集节点的 CPU、内存、磁盘、网络等性能数据并上报。
由于监控方案已迁移到新的搜索引擎平台,旧的 Elasticsearch 代理地址已被下线,对应的 DNS 记录也已删除。Metricbeat 仍在按旧配置尝试连接一个不存在的地址,因此不断失败并刷日志。
影响
- Metricbeat 进程仍在运行并采集数据,但无法投递,事件队列积压
- 不影响节点业务功能,但监控数据丢失,且持续污染系统日志
解决方案
由于旧监控方案已废弃,应从镜像构建源头移除/禁用 Metricbeat:
systemctl disable metricbeat
# 或彻底卸载
# yum remove metricbeat -y
# rm -rf /etc/metricbeat
问题二:同步进程日志灌入系统日志
现象
系统日志中持续大量出现文件同步进程打印的文件路径列表,即使其配置文件中已将日志输出设置为丢弃(logfile = "/dev/null")。
原因
同步进程存在两条独立的日志通道:
- 自身日志文件 —— 被
logfile = "/dev/null"丢弃 - 系统日志(syslog) —— 作为系统托管服务运行时,其标准输出/错误被日志系统捕获并转发到系统日志
设置 logfile = /dev/null 只关闭了第一条通道,第二条通道仍然生效。系统日志的写入由 rsyslog(系统日志中枢)负责。
解决方案
关键认识:产生日志的是同步进程,但决定是否写入系统日志的是 rsyslog。因此应在 rsyslog 层面过滤,而非改动同步进程本身(其同步功能仍需保留)。
在 rsyslog 配置目录下新增一条过滤规则:
echo ':programname, isequal, "<同步进程名>" stop' > /etc/rsyslog.d/22-ignore-sync.conf
systemctl restart rsyslog
该规则含义:程序名匹配时,日志处理到此停止(不写入文件)。文件权限使用默认的 644 即可,无需特殊权限。重启 rsyslog 使规则生效,同步进程无需重启。
问题三:结果清理规则的缺陷(核心问题)
清理程序的现有规则
清理程序以普通服务账号身份、通过定时器每小时运行一次,参数如下:
- 清理目录:测试结果目录
- 磁盘最小保留空间:5GB
- 保留时长:36 小时
删除判断逻辑(对每个子目录独立判断,满足任一条件即删除):
- 目录「最后修改时间」距今超过 36 小时,或
- 磁盘剩余空间低于 5GB,或
- 磁盘剩余百分比不足(当前未配置,不生效)
遍历顺序:按「最后修改时间」从旧到新排序,优先处理最旧的。
磁盘现状
- 根分区总计 20G,测试结果目录单独占用约 13G(约占整个分区 65%)
- 剩余空间约 4.8G,已低于 5GB 阈值
- 但最近一次清理「未删除任何目录」
未删除的原因:现存目录全部在 36 小时内,不满足年龄条件;而清理程序为每小时定时运行,运行那一刻磁盘空间可能恰好还在阈值以上,之后新数据写入才把空间压低。清理无法实时响应突发写入。
缺陷 A:排序依据是「修改时间」而非「创建时间」
程序按「最后修改时间」排序和判断年龄。这带来两面性:
- 有利的一面:正在活跃写入的目录(修改时间新)代表测试进行中,不会被误删;无新写入的目录(修改时间旧)代表测试已完成,可安全删除。从这个角度看,用修改时间比用创建时间更安全。
- 有害的一面:见缺陷 B。
缺陷 B:排队中的测试会被误删(已确认会发生)
测试执行存在以下流程:
多个测试排队 → prepare 阶段先统一完成(每个测试先复制 600MB~1GB 的输入文件到目录)→ 然后逐个真正执行
问题链条:
- 某测试在 prepare 阶段创建目录并复制大文件
- 该测试进入排队,长时间无新文件写入,修改时间停留在 prepare 时刻
- 排队超过 36 小时后,清理程序判定其「太旧」并删除
- 该测试终于轮到执行时,发现输入数据已丢失,执行失败
根本原因:清理程序仅凭修改时间判断,无法区分「测试已完成」与「测试正在排队等待执行」两种状态。
缺陷 C:磁盘容量与突发写入的矛盾
prepare 阶段可能瞬间创建多个目录。若有约 10 个测试同时 prepare,每个占 600MB1GB,合计 610GB,足以逼近甚至占满 20G 分区的可用空间。而这些目录都是刚创建的,不满足年龄条件,且清理程序每小时才运行一次,来不及响应,最坏情况下可能在清理前就把磁盘写满导致节点异常。
建议的解决方向
短期(调整配置)
- 缩短保留时长(例如从 36 小时改为 6~12 小时)以增加可删候选,缓解磁盘压力
- 提高清理运行频率(例如改为每 15 分钟一次),更快响应突发写入
注意:缩短固定保留时长不能根治缺陷 B,因为排队时间可能超过任何固定阈值。
中期(改进清理逻辑与调度)
- 基于状态而非时间判断:测试完成后写入一个完成标记文件,清理程序只删除带标记的目录,从根本上避免误删排队中的测试。
- 或让清理程序对接调度系统状态,仅清理「已完成/已失败」的测试。
- 调度器在 prepare 之前检查目标节点的可用空间与排队深度,空间不足或积压过多时暂不分配任务。
长期(架构层面)
- 加大根分区容量(例如 40G 以上)
- 或将测试结果目录挂载到独立的可扩容存储卷上,与系统盘隔离
系统性修复说明
由于 200 多个 Worker 共享同一套镜像配置,上述问题是系统性的。根本修复应落在镜像构建源头(如镜像构建模板 / 配置管理脚本),改动后新建或重建的节点自动生效;存量节点可在下次重建时更新,或通过批量推送临时修复。
镜像层面需固化的改动示例:
# 1. 禁用旧监控采集器
systemctl disable metricbeat
# 2. 过滤同步进程的 syslog 输出
echo ':programname, isequal, "<同步进程名>" stop' > /etc/rsyslog.d/22-ignore-sync.conf
# 3. 调整清理保留时长(示例)
# 修改清理程序的环境配置文件中的保留时长参数
通俗版复述(给非技术同学看)
想象我们有 200 多台一模一样的「干活机器人」(Worker),每台都用同一个模具(镜像)造出来,各干各的活,互不干扰。每台机器人身上有一块不大的硬盘(20G),专门用来放测试跑出来的结果。排查下来发现三件麻烦事。
第一件:一个没用的「上报员」还在瞎忙。
每台机器人身上原来有个「上报员」(Metricbeat),负责把机器人的健康状况(CPU、内存等)报告给总部的老系统。后来总部搬家换了新系统,老地址作废了,但这个上报员没被通知到,还在一遍又一遍地往一个不存在的地址打电话,打不通就记一笔,账本(系统日志)越记越厚。解决办法很简单:这个上报员已经没用了,直接让它退休(禁用)就行。
第二件:一个「搬运工」话太多,吵到了记事本。
每台机器人有个「搬运工」(同步进程),负责把测试结果搬到展示服务器。它每搬一个文件就大喊一声「我搬了这个!」。我们本来让它「写日记时别出声」,结果它换了个嗓门,直接朝公共广播(系统日志)喊,还是很吵。关键在于:喊话的是搬运工,但决定「要不要把喊话记进公共广播」的是广播室管理员(rsyslog)。所以我们不动搬运工(它还要干活),而是告诉广播室管理员:「以后听到这个搬运工喊话,别记,直接忽略。」世界就清净了。
第三件(最重要):打扫卫生的「清洁工」有个判断失误,可能误扔还没用的东西。
每台机器人有个「清洁工」(清理程序),每小时来一次,负责扔掉旧的测试结果,给硬盘腾地方。它的规矩是:东西放超过 36 小时,或者硬盘快满了,就扔掉最旧的。
这里有个大坑。测试开工前有个「备料」环节:会先往箱子里放两份很大的原料(加起来约 1G)。如果很多测试在排队,大家会先一起把料备好,再一个一个慢慢开工。于是就出现这种情况:某个箱子料备好了,但一直排队排不上,箱子里没有任何新动静。清洁工只看「这个箱子多久没动过」,一看超过 36 小时没动静,就当成垃圾扔了。可实际上这个测试还没开始跑呢!等它终于排到队,一看——原料没了,测试直接失败。这是一个已经确认会发生的真实问题。
除此之外还有个隐患:备料时好几个测试一起备,一下子就能塞进去 6~10G 的东西,而硬盘总共才 20G,清洁工又一小时才来一次,可能还没等它来打扫,硬盘就先被塞爆了,机器人直接罢工。
怎么根治这三件事?
因为 200 多台机器人都是一个模具造的,所以最省事的办法是直接改模具(镜像):让新造出来的机器人天生就没有那个没用的上报员、搬运工的喊话被自动忽略、清洁工的规矩也更合理。对清洁工最关键的改进是——别再只看「多久没动过」来扔东西,而是让测试「干完活」时主动贴个「已完成」的标签,清洁工只扔贴了标签的箱子,这样就绝不会误扔还在排队的测试了。另外,硬盘也该考虑换大一点,或者单独加一块盘专门放结果,别和系统挤在一起。