3 点 17 分,手机在床头柜上震。我迷迷糊糊摸过来看了一眼,是机房监控的短信:「10.0.3.21 / 分区使用率 97%」。
第一反应是骂了一句。昨天下午刚清过一次,怎么又满了?
爬起来开电脑,连上那台机器,df 一看:
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 40G 39G 1.1G 97% /
确实快满了。关键是——这台机器是台 NFS 存储网关,根分区才给了 40G,平时用个 10G 出头,怎么会突然到 39G?
先找大文件。du -sh /* 一层层往下钻,最后锁定 /var/log:
1.9G /var/log
1.9G 说大不大,但配合 inode 一看就明白了:
df -i /var/log
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda2 2621440 2601100 20340 99% /
inode 用了 99%。40G 的盘塞满了 260 万个小文件,全是日志。空间还剩 1.1G 看着没满,但 inode 一旦耗尽,新文件根本创建不了,业务随时可能报 No space left on device。
ls /var/log 一拉,满屏的 .log.1、.log.2……一直排到 .log.1000+。数了一下,光一个文件就 30 多万行。罪魁祸首是我们内部一个同步 agent:debug 日志默认全开,一天能写 2G 左右。logrotate 配置里写的 daily + size 100M + rotate 5,看着挺正常——但仔细一看,路径写错了,logrotate 一直在静默失败,日志就这么一路滚到了上千份。
处理分三步:
先止血。老日志直接删,保留最近两天的:
find /var/log -name ".log." -mtime +2 -delete
删完磁盘回到 18%,inode 使用率掉到 8%。然后改 logrotate 配置:size 100M 改成 50M,rotate 提到 20,加上 compress 压缩老日志,再加 copytruncate——这个 agent 一直持有文件句柄,不 copytruncate 的话你删了文件它照样往原 inode 上写,白删。最后去 agent 的配置文件把 debug 关掉,重启 agent。
改完 logrotate 记得先试跑一遍:
logrotate -d /etc/logrotate.d/agent.conf
-d 是 dry run,会告诉你配置有没有语法错误、哪些文件会被轮转。这次要是早跑这一下,也不至于等到报警。
第二天早上看,/ 分区稳定在 12%,inode 使用率 8%。报警短信当晚终于消停了。
几点教训:
一是监控别只盯空间不盯 inode。这次差点翻车就是因为 df 看着还剩 1G 多,真正要命的是 inode 99%。二是 logrotate 配了不等于生效,配完 -d 试跑是基本操作。三是服务日志必须上线前定好策略,能写 2G/天的服务还开全量 debug,出事是早晚的事。
写完收工,睡觉。希望下次报警短信来的时候,至少别在凌晨三点。
评论