容器日志失控主因是max-size与max-file未成对配置,必须同时设置才能触发轮转,否则单容器日志数小时内可达20gb;推荐组合为"max-size":"50m","max-file":"3",全局生效需修改/etc/docker/daemon.json并重启docker daemon。

万级微服务集群里,日志不是“慢慢长胖”,而是“瞬间爆体”——一个配置失误,可能在几小时内让数百台节点磁盘 100%。这不是容量预估问题,是滚动策略没卡住关键控制点。核心在于:**时间、空间、触发时机、清理兜底** 四层必须同时生效,缺一不可。
Logback(Spring Boot / Nacos / RocketMQ):maxHistory 和 totalSizeCap 必须配对使用
只设 maxHistory=30 不够,它只按日期删文件,但若某天突发流量打满日志,单日就生成 50GB,30 天就是 1.5TB;只设 totalSizeCap=10GB 也不行——该参数默认不生效,必须满足两个前提:
- maxHistory > 0(哪怕设成 1)
- fileNamePattern 中含时间占位符(如 %d{yyyy-MM-dd})
推荐组合(生产实测稳定):
-
按天滚动 + 保留 15 天 + 总量封顶 8GB:
15 8GB - 避免用 %d{yyyy-MM} 按月滚动:maxHistory=7 实际保留 7 个月,极易失控
- 容器内务必检查 JVM 时区(-Duser.timezone=Asia/Shanghai),否则 maxHistory 计算错位
MySQL:binlog 和 error.log 必须分策治理
binlog 和 error.log 是两类完全不同的机制,混用轮转会直接导致主从断裂或进程静默退出:
-
binlog:禁用 logrotate,改用 MySQL 原生过期策略
SET PERSIST binlog_expire_logs_seconds = 604800;(保留 7 天)
必须确保binlog_expire_logs_auto_purge = ON -
error.log:必须用 logrotate + FLUSH LOGS
配置中必须含postrotate ... mysql -e "FLUSH LOGS;" ... endscript
否则切割后日志仍写入旧文件句柄,等于白切 - slow_log / general_log:优先关闭文件模式,启用表存储:
slow_query_log=ON+log_output='TABLE'
Docker 容器:json-file 驱动的 max-size 和 max-file 必须成对硬限制
默认 json-file 驱动不轮转,单个容器日志可 24 小时突破 20GB。关键规则:
- max-size 和 max-file 必须同时设置才生效,只设一个等于没设
- 全局生效:修改
/etc/docker/daemon.json并重启 docker daemon"max-size": "50m", "max-file": "3"→ 单容器日志上限 150MB - 已有容器需重建才生效(
docker commit+docker run或docker-compose up --force-recreate) - K8s 场景下,在 container spec 中显式声明:
logOptions: { "max-size": "30m", "max-file": "2" }
兜底与监控:不能只靠配置,要能自动发现和干预
再严的配置也防不住代码级日志爆炸(比如循环打印 DEBUG 日志)。必须加两道保险:
- 部署定时脚本,每 15 分钟扫描:
find /var/log -name "*.log" -size +1G -exec ls -lh {} \;
发现超限立即告警并 truncate(truncate -s 0 $file) - 所有节点统一部署 logrotate,并开启 compress(压缩节省 70%+ 空间)
配置中必须含compress和delaycompress(避免正在写的日志被压缩) - 监控指标不止看磁盘使用率,还要采集:
•inode 使用率(df -i)—— 微服务日志碎片化易耗尽 inode
•单容器日志文件数量 & 最大尺寸(通过docker inspect提取 LogPath 后 du)











