一、问题表现
某节点很多pod无法启动
1.查看docker日志:
applying cgroup configuration for process caused \\\"mkdir /sys/fs/cgroup/memory/kubepods/xxxx: cannot allocate memory\\\"\": unknown”
2执行dmesg查看日志:
SLUB: Unable to allocate memory on node -1 (gfp=0x20)
3.free -h 查看内存还有很多,但无法分配
二、问题原因
cgroup 的 kmem account 特性在 3.x 内核上有内存泄露问题,如果开启了 kmem account 特性 会导致可分配内存越来越少,直到无法创建新 pod 或节点异常。
几点解释:
1、kmem account 是cgroup 的一个扩展,全称CONFIG_MEMCG_KMEM,属于机器默认配置,本身没啥问题,只是该特性在 3.10 的内核上存在漏洞有内存泄露问题,4.x的内核修复了这个问题。
2、因为 kmem account 是 cgroup 的扩展能力,因此runc、docker、k8s 层面也进行了该功能的支持,即默认都打开了kmem 属性。
3、因为3.10 的内核已经明确提示 kmem 是实验性质,我们仍然使用该特性,所以这其实不算内核的问题,是 k8s 兼容问题。
三、解决方案
方案一:升级内核到4.x
缺点1.需要重启机器 2.需要充分测试当前业务和4.x内核是否兼容
方案二:修改虚机启动的引导项 grub 中的cgroup.memory=nokmem,让机器启动时直接禁用 cgroup的 kmem 属性
# 修改/etc/default/grub 为:
GRUB_CMDLINE_LINUX="crashkernel=auto net.ifnames=0 biosdevname=0 intel_pstate=disable cgroup.memory=nokmem"
# 生成配置:
/usr/sbin/grub2-mkconfig -o /boot/grub2/grub.cfg
# 重启机器:
reboot
# 验证:
cat /sys/fs/cgroup/memory/kubepods/burstable/pod*/*/memory.kmem.slabinfo 无输出即可。
缺点
1.需要重启机器
2. 这个方式对一些机器生效,但有些机器替换后没生效
方案三:重新编译kubelet,禁用kmem account属性