dockerd 进程 RSS 持续上涨而容器内存稳定是 dockerd 自身内存泄漏的典型表现,需通过 pstack、pprof、debug 日志及监控指标综合定位。

dockerd 进程 RSS 持续上涨但容器内存稳定
这是典型的 dockerd 自身内存泄露信号,不是容器问题。Linux 的 ps aux --sort=-rss 或 top -o %MEM 能快速确认:如果 dockerd 的 RSS 占用从几百 MB 涨到 2GB+,而所有容器的 docker stats 显示内存使用平稳,基本可排除业务或镜像层缓存误判。
常见诱因是长期运行的守护进程未正确释放资源句柄,比如持续创建/销毁网络 endpoint、反复挂载/卸载 volume、或插件(如 CNI、logging driver)存在引用泄漏。
- 先用
sudo pstack $(pgrep dockerd)抓一次线程栈,重点看是否有大量重复的netlink、inotify或openat调用堆栈 - 检查
/var/run/docker/netns/下 namespace 文件数量是否异常增长(正常应与运行中容器数大致一致) - 临时禁用非必需插件(如
log-driver=fluentd或自定义 CNI),观察 RSS 是否停止上涨
启用 dockerd 的 debug 日志并过滤内存相关事件
默认日志级别不输出内存分配路径,必须显式开启 debug 并配合 grep 筛选关键行为。修改 /etc/docker/daemon.json 加入:
{"debug": true, "log-level": "debug"},然后 sudo systemctl reload docker。
注意:debug 日志量极大,仅用于短时定位;线上环境切勿长期开启。
- 实时跟踪内存操作:
sudo journalctl -u docker -f | grep -E "(malloc|free|mem|oom|gc)" - 重点关注
graphdriver和libcontainerd模块日志,例如出现高频layer store: get layer by diffID但无对应 release,可能指向镜像层引用计数泄漏 - 若日志中反复出现
failed to unmount /var/lib/docker/overlay2/xxx: device or resource busy,说明 mount ref 未清理,会间接拖慢内存回收
用 pprof 分析 dockerd 堆内存快照
dockerd 内置了 pprof 接口(默认监听 127.0.0.1:2376/debug/pprof/),无需重启即可抓取堆内存分布。前提是启动时加了 --debug 参数(systemd 服务需改 ExecStart)。
执行 curl -s 'http://localhost:2376/debug/pprof/heap?debug=1' | grep -A10 'inuse_objects' 可看到当前活跃对象数最多的类型,比单纯看 RSS 更准。
- 导出 svg 图谱分析:
curl -s 'http://localhost:2376/debug/pprof/heap' | go tool pprof -http=:8080 - - 重点关注
*sync.Map、*net.Interface、*os.File实例数是否随时间线性增长 - 若
runtime.mallocgc调用频次远高于runtime.gc,说明 GC 压力大但未及时触发,可能是对象生命周期管理逻辑有缺陷
监控项设置与告警阈值建议
靠人工查日志或 pprof 不可持续,必须固化为监控指标。Prometheus + cAdvisor 是最轻量方案,但要注意 cAdvisor 默认不暴露 dockerd 自身指标,需额外采集。
关键指标不是容器内存,而是 process_resident_memory_bytes{process="dockerd"} 和 process_open_fds{process="dockerd"} —— 后者常被忽略,但 fd 泄漏往往早于内存泄漏发生。
- 告警阈值建议:
process_resident_memory_bytes > 1.5e9(1.5GB)且 1h 内上涨 >300MB - 搭配
rate(process_cpu_seconds_total{process="dockerd"}[5m]) > 0.8,高 CPU + 高内存 = 典型泄漏组合 - 务必加
absent(process_resident_memory_bytes{process="dockerd"})告警,避免 dockerd 崩溃后监控静默失联
真正难的是区分「缓慢增长」和「周期性尖峰」——有些场景下 dockerd 会在批量 pull 镜像后内存暂升,几小时才回落。得结合历史曲线和操作日志交叉验证,不能只看绝对值。











