Docker cgroup进程间歇性故障排查:kmem内存分配失败问题
故障核心特征总结
- 触发条件:Azure云虚拟机上的Docker集群连续运行≥5天偶发
- 核心报错:容器启动时写入
memory.kmem.limit_in_bytes失败,提示无法分配内存 - 伴随现象:域名解析失败、所有HTTPS请求被拒绝
优先级最高的排查步骤
- 首先确认内核与Docker版本:执行
uname -r和docker version输出版本信息,该问题是Linux 3.10.x版本内核的经典缺陷,CentOS 7、RHEL 7默认搭载的3.10内核普遍存在kmem cgroup泄漏问题,搭配19.03及更早版本的Docker时会默认开启kmem accounting,触发资源持续泄漏 - 故障发生时检查宿主机内核内存占用:执行
cat /sys/fs/cgroup/memory/memory.kmem.usage_in_bytes查看全局内核内存占用,再执行grep Slab /proc/meminfo查看SUnreclaim指标,如果该指标持续上涨且无法回收,即可确认是内核内存泄漏 - 检查Docker残留cgroup目录:执行
ls -l /sys/fs/cgroup/memory/docker/ | wc -l统计目录数量,如果数值远大于当前运行的容器数量,说明容器销毁时对应的cgroup目录未被正常清理,残留目录持续占用内核内存,最终耗尽资源导致新容器无法创建
修复方案
临时缓解方案(快速恢复业务)
- 故障发生后直接重启宿主机即可释放所有泄漏的内核内存,恢复容器创建能力
- 业务低峰期可设置定时任务每周重启一次Docker服务或宿主机,避免内核内存累积到阈值触发故障
永久修复方案
- 方案1:将宿主机Linux内核升级到4.4及以上版本,该版本及更高版本内核已经修复了kmem cgroup的泄漏缺陷
- 方案2:如果暂时无法升级内核,可修改Docker启动参数关闭kmem accounting:
- 编辑Docker配置文件
/etc/docker/daemon.json,添加配置项"kernel-memory": -1 - 执行
systemctl daemon-reload && systemctl restart docker即可生效
- 编辑Docker配置文件
- 方案3:将Docker升级到20.10及以上版本,该版本默认关闭了旧内核的kmem accounting特性,不会触发泄漏问题
域名解析失败补充说明
域名解析失败是容器无法启动的连锁反应:核心DNS服务容器无法正常启动后,集群内所有服务的域名解析请求都会失败,进而导致HTTPS请求被拒绝,修复内核内存泄漏问题后该现象会同步恢复。
内容的提问来源于stack exchange,提问作者Pradip
相关产品推荐
相关产品推荐

