cgroup根节点残留引发soft lockup或内存分配失败,表现为节点notready、pod无法启动;需通过ls统计目录数、dmesg查报错、cat usage_in_bytes验证内存未释放,再安全重启kubelet或手动rmdir空残留目录,并禁用kmem account及升级kubelet加固。

这个问题核心在于:Cgroup根节点(如 /sys/fs/cgroup/memory/)下存在未清理的残留控制组,尤其在频繁创建/销毁容器或异常中断后,可能造成内核内存子系统状态混乱,触发 soft lockup 或内存分配失败(如 SLUB: Unable to allocate memory on node -1),表现为节点 NotReady、Pod 无法启动、dmesg 出现 watchdog 超时等。
确认是否为 cgroup 根节点残留引发
先验证问题根源,避免误判:
- 执行
ls /sys/fs/cgroup/memory/ | wc -l,若数量异常高(数百甚至上千),尤其含大量类似kubepods-burstable-podxxxx或已删除 Pod 的残留目录,说明存在积压 - 检查
dmesg -T | grep -i "soft lockup\|watchdog\|slub\|out of memory",重点关注带cgroup或memcg字样的报错 - 运行
cat /sys/fs/cgroup/memory/memory.usage_in_bytes,若数值持续增长且远高于实际进程 RSS 总和,提示 cgroup 内存未释放
清理 cgroup 根节点残留条目
残留通常来自 kubelet 异常退出、容器运行时崩溃或强制 kill 进程。手动清理需谨慎:
- 优先尝试安全方式:
systemctl restart kubelet—— 正常情况下 kubelet 重启会自动回收其管理的 cgroup 子树 - 若重启无效,进入
/sys/fs/cgroup/memory/目录,逐个检查疑似残留目录(如名称含已删除 Pod UID、无对应进程的docker-前缀目录),确认其内cgroup.procs为空:cat cgroup.procs | wc -l - 对空目录执行:
rmdir <dirname></dirname>;若提示Device or resource busy,用lsof +D /sys/fs/cgroup/memory/<dirname></dirname>查找占用进程并处理 - 切勿直接
rm -rf整个 cgroup 目录,可能引发系统级故障
关闭 kmem account 防止内存泄露恶化
Linux 3.10 内核(CentOS 7 默认)的 CONFIG_MEMCG_KMEM 存在已知内存泄露,开启后残留会加速耗尽 slab 内存:
- 临时禁用:
echo 0 > /sys/fs/cgroup/memory/memory.kmem.limit_in_bytes - 永久禁用:在
/etc/default/grub中的GRUB_CMDLINE_LINUX行末添加cgroup_enable=memory swapaccount=1 systemd.unified_cgroup_hierarchy=0,再执行grub2-mkconfig -o /boot/grub2/grub.cfg && reboot - 验证是否生效:
zgrep CONFIG_MEMCG_KMEM /proc/config.gz应返回CONFIG_MEMCG_KMEM is not set
加固 kubelet 与运行时行为
从源头减少残留生成:
- 升级 kubelet 至 v1.19+,启用
--cgroups-per-qos=true(默认开启),确保 QoS 分层 cgroup 结构更健壮 - 设置 kubelet
--cgroup-driver=systemd(与容器运行时一致),避免 cgroup 混用导致清理失效 - 在 Docker daemon.json 中添加:
"default-runtime": "runc", "runtimes": { "runc": { "path": "runc" } },禁用非标准运行时干扰 - 定期巡检:用脚本统计
/sys/fs/cgroup/memory/下子目录数,超阈值(如 >200)自动告警











