【易迪森分享】一次K8s集群节点宕机问题引出的性能调优过程
发布时间:2022-03-17 浏览数:0
一位做运维的朋友反馈问题,他们的k8s集群节点突然宕机了,怀疑是内存溢出。但是仔细检查了应用日志,节点日志之后,均没有发现out of memory记录。思考深层次的原因,系统如果突然宕机,有可能是触发了内核的OOM-killer,最典型的就是swap空间满了,系统强杀进程。于是让他检查了swap,发现压根没有开启这里有一个奇怪的问题,377G的内存,cache就占了333G,并且这台机器刚刚重启。说明Cache可能回收不掉。于是再次检查内核设备日志,终于在kubepod上发现了异常内核日志:Memory cgroup out of memory kill process pid问题已经清晰了,这是一个典型的cgroup memory导致的内存泄漏问题cgroup memory内存泄漏
k8s集群随着pod增多,运行久了之后就会出现不能创建pod的情况。执行kubectl describe pod命令可以发现 cannot allocate memory异常。重启对应的服务器之后异常提示才会消失。但继续随着运行时间推移,该问题依然会出现,最终内存会耗尽,系统会强杀节点释放内存。使用cat/sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo 检查问题node,如下图则说明没有存在内存泄漏kmem导致的内存泄露
内核对每个cgroup 子系统的的内存地址页是有限制的,限制的大小定义在 kernel/cgroup.c #L139上。在 cgroup 创建一个内存地址之后,当开启了 kmem 功能,虽然 cgroup 的地址页删除了,但是内存不会回收。也就是说在3.1内核版本下,开启了 kmem 功能就会导致内存泄漏。该问题会导致可分配内存越来越少,直到无法创建新 pod 或节点宕机注:该内存泄漏问题在3.10 的内核上存在,4.x的内核已经修复和技术人员沟通之后,了解到该测试环境的一台机器上的pod转移到了其他pod,中间涉及大量的容器创建和销毁。通过内存分析。发现存在太多的 cgroup memory申请,slab占用过高,无法回收ls -al /sys/kernel/slab/| grep inode_cache |more节点创建时通过 cgroup memory申请了slab,但是节点关闭时,这些slab却释放不掉。导致越积越多,最终将内存耗尽
内存速度比较快,所以缓存了一部分磁盘数据,称之为高速缓存。这部分缓存数据被调用之后会打上标记,称之为内存脏页,或者slab。脏页达到一定比例之后,系统会调用sync函数进行回收,保证数据不会丢失。但是k8s节点在内核3.1下面是有bug的,这部分slab永远不会被回收掉,直到进程触发oomkiller1:内核参数文件 /boot/grub2/grub.cfg中添加 cgroup.memory=nokmem 让系统禁用 cgroup的 kmem2:内核参数文件 /boog/grub2/grub.cfg 中添加 cgroup_disable=memory 关掉整个cgroup memory直接关闭了cgroup memory。重启系统之后集群运行正常,之后没有再出现内存泄漏遇到这种突然宕机的现象不要慌,先捞日志。应用日志,server日志,堆栈日志,内核设备日志,总能找到蛛丝马迹,然后再顺藤摸瓜探索问题产生的根源