日志管理与轮转实战:让日志不撑爆盘、找得到、留得住


自托管服务一多,日志就成了"知道它重要、却总被拖到最后"的东西:每个应用往自己的文件里写、docker logs 各自独立、没人定期清理,等到磁盘被日志撑爆、或出问题时想翻日志却找不到"那个时刻"的记录,才后悔没管。日志管理(收集、轮转、保留、检索)就是把这摊子收起来的系统做法:日志不是"写到文件就完事",而是"按时轮转防撑爆、统一收集可检索、按策略保留可回溯"。这篇讲清日志管理解决什么、logrotate 轮转怎么配、docker 日志与容器怎么管、统一收集的取舍,以及常见坑与边界。

一、日志管理解决什么:让日志"不撑爆盘、找得到、留得住"

日志的三重价值:排障(出事能翻现场)、审计(谁在何时干了什么)、趋势(量、错误率的长期信号)。但裸放不管的日志会带来三个麻烦:一是"撑爆磁盘"——高并发应用的日志按 GB 级增长,不清就写满盘,服务直接挂;二是"找不到"——散在各文件、各自格式,出问题时不知道去哪翻;三是"留不住"——要么全删了没历史,要么全留了吃满盘,没有"留多久"的规划。日志管理就是把"生成日志"这件必然发生的事,变成"轮转不爆盘、统一可检索、按需留历史"的闭环:先解决不撑爆(轮转),再解决找得到(统一收集),最后解决留得住(保留策略)。

它在可观测性里的位置:日志(logs)、指标(metrics)、链路(traces)三件套里,日志是最"原始现场"的一类——指标告诉"发生了什么",日志告诉"到底什么内容、什么上下文"。自托管里"先会轮转、再谈集中",是成本最低、收益最直接的顺序。

二、logrotate 轮转:让系统日志"按大小/按时间滚动、保留 N 份"

Linux 上管"文件日志"最经典的工具是 logrotate:按大小(如 100M)或按时间(如每天)把当前日志"滚动"成带序号的旧文件,并保留指定份数,过期即删(或压缩归档)。配置在 /etc/logrotate.d/ 下,一个应用一个文件,配"触发条件 + 保留份数 + 是否压缩 + 轮转后信号"(很多服务要 SIGHUP 让它重新开日志文件)。配好它,最基础的"日志不撑爆盘"就解决了,而且对几乎所有写到文件的程序都适用,零侵入。

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
  daily                      # 每天轮转一次(也可 size 100M 按大小)
  rotate 14                  # 保留 14 份(14 天)
  compress                   # 旧日志压缩节省空间
  delaycompress              # 轮转后延迟一天压缩,避免程序还没写完
  missingok                  # 文件不存在不报错
  notifempty                 # 空文件不轮转
  sharedscripts
  postrotate
    # 通知应用重新打开日志文件(按应用而定)
    /usr/bin/systemctl reload myapp >/dev/null 2>&1 || true
  endscript
}
# 手动测试:logrotate -d -f /etc/logrotate.d/myapp   (-d 试跑不真转)

logrotate 的坑多在"程序持有旧文件句柄"与"轮转频率不匹配":程序不重新打开日志,日志就会继续写进已被改名的旧文件里(文件还在涨)——postrotate 里 reload/发信号很重要;而"按天轮转但某天量巨大"会一天爆满,关键服务可改成按 size 轮转。配完用 `-d` 试跑确认逻辑,再让它进 cron 按时执行。

三、docker 日志与容器怎么管:驱动、上限与集中

容器的日志是另一个大头:docker 默认 json-file 驱动,日志写在 /var/lib/docker/containers 下,不设上限就会无限涨,最终吃满宿主盘。管法分两段:第一段"本地设上限"——配置 log driver 的 max-size / max-file(如每个容器日志 10M × 5 份),从源头不让它无限长;第二段"集中收集"——用 Loki + Promtail(或 Elasticsearch + Filebeat)这类采集器,把各容器日志统一收进一个可检索的日志库,前端用 Grafana/Kibana 查。对自托管,先"设上限防爆盘",再按需上"统一收集",顺序别反。

# Docker daemon.json:给容器日志统一设上限(防撑爆宿主盘)
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "5" }
}
#   也可在单个容器上加:--log-opt max-size=10m --log-opt max-file=5

# 集中收集(Loki 方案示意)
#   Promtail 配置里把 docker 容器日志抓给 Loki:
#   clients: [ { url: http://loki:3100/loki/api/v1/push } ]
#   scrape_configs:
#     - job_name: docker
#       docker_sd_configs: [ { host: unix:///var/run/docker.sock } ]
#       relabel_configs: [ ... 把容器名做成 label ... ]

容器日志的坑:"重启容器丢失历史"(容器删除日志文件跟着没)、"磁盘被 /var/lib/docker 撑满"(没设上限)、以及"采集器本身与 docker socket 的权限风险"(能读 socket ≈ 能控容器,采集器要用最小权限/专用账号)。先设上限、再做收集、采集器权限最小化,三步缺一不可。

四、统一收集的取舍:Loki+Promtail vs ELK,以及该不该上

要不要"统一收集",取决于"日志散到找不着的程度":两三个服务、docker logs 够用,先别上;服务一多、要跨服务串上下文、要历史检索时,才值得集中。选型上两条主流路线:Loki + Promtail(+ Grafana)——日志按标签索引、成本低、与 Prometheus/Grafana 生态一体,自托管首选;ELK(Elasticsearch + Logstash/Filebeat + Kibana)——全文检索能力更强、适合复杂查询与分析,但资源占用大得多(前面聊过 ELK 的取舍)。选型判断:自托管多数场景 Loki 足够且轻;只有当你要"复杂全文检索/分析"才上 ELK。集中收集要考虑"日志就是数据":保留策略、备份与权限也要规划,别把日志库也搞成无人管理的垃圾场。

# 保留策略示例(Loki):按租户/标签设置日志保留时长
#   loki-config.yaml:
#     limits_config:
#       retention_period: 720h     # 默认保留 30 天(按需设)
#     schema_config: ...          # 索引与存储配置
# 查询示例(Grafana Explore / LogQL):
#   {app="myapp"} |= "error" |= "user_id=123"      # 过滤某应用的错误日志

集中收集的坑:采集器把日志推慢了/推断了(客户端积压、Loki 写压)、保留策略没设导致日志库无限长胖、以及"日志里带敏感信息"(密码/token 被收进日志库,权限就要更严)。把"推得动、留得住、权限严"三条守住,集中日志才真正可依赖。

五、常见坑与边界:轮转没信号、采集断点、日志即数据、别过度

日志管理四个坑要尤其防。一是"轮转后程序还写旧文件":不 reload/发信号,日志继续写进已改名文件,等于没轮转——postrotate 里动作别省。二是"采集断点与积压":集中采集时服务重启/采集器挂,会丢段或积压,要有断点续传与积压告警意识。三是"日志即数据":日志里可能有敏感信息与长历史,保留策略、备份与访问权限都要按"数据"对待,别把日志库当临时垃圾。四是"别过度":不是每个服务的每条日志都值得集中收集与永久保留——按服务重要性分级(关键服务全量、边角服务只留错误),控制成本与噪音。

# 排障 SOP:日志相关问题的快速定位
#   磁盘被日志撑满 → 看 /var/log 与 /var/lib/docker/containers 占用,检查轮转/上限
#   某应用没日志 → 先看它写哪个文件/驱动,再看轮转是否把它改名没重开
#   集中库查不到 → 看采集器是否在跑、目标时间是否在保留期内

把它当排障 SOP:先"哪条路径在涨(盘/文件)",再"轮转有没有生效(文件名/时间戳)",后"采集有没有断(采集器状态)"。日志管理是"先不爆盘、再找得到、后留得住"的三级工程,逐级建好才不会让日志成为"沉默的灾难"。

把日志管理放回自托管整体:它是"让日志不撑爆盘、找得到、留得住"的底层保障,也是可观测性的原始现场。落地要点:用 logrotate 把文件日志按大小/时间轮转并保留 N 份(配 postrotate 通知程序重开);给 docker 容器日志设 max-size/max-file 防撑爆宿主盘,服务多了再用 Loki+Promtail(或 ELK)统一收集检索;防住轮转没信号、采集断点、日志即数据、过度收集四坑;并认清日志管的是"现场记录",不替代指标与链路、也不保证应用自身正确。当你把"轮转、上限、收集、保留、权限"这条链做成闭环,自托管的日志才会从"盘满才想起"变成"随时可查、留得住、也丢得起该丢的"。

结语

日志管理与轮转的价值,是把"应用写日志"这件必然发生的事,变成"轮转不爆盘、统一可检索、按策略保留"的闭环,让日志从"盘满才想起"变成可靠的排障与审计现场。落地要点:用 logrotate 按大小/时间轮转文件日志并保留 N 份,postrotate 里通知程序重新打开日志;给 docker 容器配 max-size/max-file 防撑爆宿主盘,服务多了用 Loki+Promtail(轻量)或 ELK(重检索)统一收集;防住轮转后程序写旧文件、采集断点积压、日志即数据(敏感信息与备份)、过度收集四坑,并按服务重要性分级保留;认清日志管"现场记录"、不替代指标与链路。把轮转、上限、收集、保留、权限这五件事做成日常习惯,自托管的日志才真正称得上"可靠的历史资产"。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

系统安全基线实战:把 SSH、暴露面与补丁做成常态化清单

Helm Chart 实战:把 K8s 应用部署从一堆 YAML 变成包管理

评 论
更换验证码