1. 当rsyslogd变成"内存怪兽"时发生了什么
那天凌晨三点,我的手机突然被报警短信轰炸——服务器内存使用率突破95%。连滚带爬爬起来SSH连上去,top命令一看,好家伙,rsyslogd这个平时温顺的日志服务竟然吃掉了8G内存!这场景就像小区里突然闯进一头哥斯拉,把整个内存街区踩得稀烂。
细看日志目录更吓人,/var/log/messages已经膨胀到20GB,打开一看全是容器疯狂输出的调试日志。这让我想起老家发洪水时的场景:上游(容器)暴雨倾盆,中游(journald)的蓄水池决堤,下游(rsyslogd)的河道根本来不及泄洪,最终淹没整个村庄(服务器内存)。
典型症状其实很有规律:
- 内存使用曲线呈阶梯式增长,最终卡死系统
- /var/log/journal/目录下有损坏的日志文件
- dmesg里能看到journal校验失败提示
- 容器越多问题爆发越快
后来我发现,这其实是现代日志系统的"三体问题":systemd-journald负责采集,rsyslogd负责转发,容器应用疯狂生产日志。当三者平衡被打破,就会引发链式反应。就像洪水暴发要同时治理上游水土流失、中游水库调度和下游河道疏通,我们也需要一套组合拳。
2. 诊断工具:揪出日志系统的"病灶"
2.1 第一现场勘查
先用这组命令快速定位问题源:
# 查看内存占用排行榜 top -o %MEM # 检查rsyslog进程实际内存(注意VSZ和RSS的区别) ps aux | grep rsyslog | grep -v grep # 查看journal日志完整性 journalctl --verify | grep corrupt最近一次事故中,我发现有3个journal文件报"Invalid object header"错误。这就像水库出现了管涌,必须立即处理。
2.2 日志洪水溯源
重点检查这些位置:
# 查看各日志文件大小 ls -lh /var/log/{messages,secure,maillog} # 实时监控日志写入速度(每秒刷新) watch -n 1 'du -sh /var/log/messages' # 统计日志来源(容器日志通常带k8s标签) journalctl -o json-pretty | grep k8s_pod | wc -l有次发现某台机器上单个Pod每秒产生2000条调试日志,这相当于在市政排水管上接了消防栓!
3. 紧急抢险:给rsyslogd戴上"紧箍咒"
3.1 内存限制三板斧
修改/etc/systemd/system/rsyslog.service.d/memlimit.conf(没有就新建):
[Service] MemoryAccounting=yes MemoryHigh=8M # 软限制,类似"水位警戒线" MemoryMax=80M # 硬限制,相当于"防洪堤高度"这组参数效果就像给长江分段设置汛限水位:
- 当内存使用超过8M,系统会温和限流
- 达到80M直接触发OOM killer
重启服务时记得:
systemctl daemon-reload systemctl restart rsyslog3.2 日志分级过滤
在/etc/rsyslog.conf中添加:
# 限制journal转发速率(单位:秒) $imjournalRatelimitInterval 0 $imjournalRatelimitBurst 0 # 只记录错误级别日志 *.err;mail.none;authpriv.none;cron.none /var/log/messages这相当于在日志管道上加装过滤器:原本的消防水带变成了滴灌系统。实测能将日志量减少90%以上。
4. 治本之策:重建日志生态系统
4.1 journald存储优化
编辑/etc/systemd/journald.conf:
[Journal] Storage=persistent # 改内存存储为磁盘存储 Compress=no # 关闭压缩避免bug SystemMaxUse=1G # 磁盘配额1GB这就像把临时蓄水池(内存)改建成永久水库(磁盘)。记得同步操作:
mkdir -p /var/log/journal systemctl restart systemd-journald4.2 容器日志分流
对于Kubernetes环境,在docker配置中增加:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }相当于给每个容器安装独立下水道,避免都挤到主排水管。
5. 长效防护机制
5.1 监控预警配置
Prometheus中添加这些监控项:
- name: rsyslog_memory rules: - alert: RsyslogMemoryHigh expr: process_resident_memory_bytes{job="rsyslog"} > 8 * 1024 * 1024 for: 5m labels: severity: warning5.2 定期维护脚本
创建/etc/cron.weekly/log-maintenance:
#!/bin/bash # 清理30天前日志 find /var/log/journal -type f -mtime +30 -delete # 校验journal完整性 journalctl --verify记得给执行权限:
chmod +x /etc/cron.weekly/log-maintenance经过这套组合拳治理后,我们的服务器再没出现过日志洪水。现在rsyslogd的内存占用稳定在5-6MB,就像驯服的野兽回到了笼子里。关键是要理解:日志系统是个有机整体,不能头痛医头脚痛医脚。就像治水需要全流域统筹,日志治理也需要端到端的视角。