k8s最佳实践:cgroup kmem的内存泄露问题
1.前言
这篇文章的全称应该叫:[在某些内核版本上,cgroup 的 kmem account 特性有内存泄露问题],如果你遇到过 pod 的 "cannot allocated memory"
报错,node 内核日志的“SLUB: Unable to allocate memory on node -1”
报错,那么恭喜你中招了。
2.现象
我们的环境:
- K8S 版本: 1.11、1.13、1.16
- docker 版本:18.09
- 机器操作系统:centos7、centos6
- 机器内核版本:3.10
可能会出现以下几种现象:
1.pod 状态异常,describe pod 显示原因为: no allocated memory
2.节点上执行 dmesg 有日志显示:slub无法分配内存:SLUB: Unable to allocate memory on node -1
3.节点 oom开始按优先级杀进程,有可能会导致有些正常 pod 被杀掉
4.机器free 查看可用内存还有很多,却无法分配,怀疑是内存泄露。
3.原因
一句话总结:
cgroup 的 kmem account 特性在 3.x 内核上有内存泄露问题,如果开启了 kmem account 特性 会导致可分配内存越来越少,直到无法创建新 pod 或节点异常。
几点解释:
- kmem account 是cgroup 的一个扩展,全称CONFIG_MEMCG_KMEM,属于机器默认配置,本身没啥问题,只是该特性在 3.10 的内核上存在漏洞有内存泄露问题,4.x的内核修复了这个问题。
- 因为 kmem account 是 cgroup 的扩展能力,因此runc、docker、k8s 层面也进行了该功能的支持,即默认都打开了kmem 属性
- 因为3.10 的内核已经明确提示 kmem 是实验性质,我们仍然使用该特性,所以这其实不算内核的问题,是 k8s 兼容问题。
4.解决方案
方案1:升级内核
既然是 3.x 的问题,直接升级内核到 4.x 及以上即可,内核问题解释:
- https://github.com/torvalds/linux/commit/d6e0b7fa11862433773d986b5f995ffdf47ce672
- https://support.mesosphere.com/s/article/Critical-Issue-KMEM-MSPH-2018-0006
这种方式的缺点是:
- 需要升级所有节点,节点重启的话已有 pod 肯定要漂移,如果节点规模很大,这个升级操作会很繁琐,业务部门也会有意见,要事先沟通。
- 这个问题归根结底是软件兼容问题,3.x 自己都说了不成熟,不建议你使用该特性,k8s、docker却 还要开启这个属性,那就不是内核的责任,因为我们是云上机器,想替换4.x 内核需要虚机团队做足够的