Linux kernel memory 导致的POD OOM killed
有天,接到用户请求, 帮助排查生产环境POD反复自动重启的原因,于是登录主机,执行"kubectl describe pod <pod name> -n <namespaces>"查看,发现POD是因为OOM被杀了,然后kubelet又自动重新拉起。
State: Running
Started: Mon,23 Jun 2020 15:20:20 +0800
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
但是用户反映,POD内存limit设置了6G,实际使用并没有达到6G。一开始以为用户可能对监控项memory_rss_bytes, memory_usage_bytes可能会有误解,因为POD的内存其实是memory_usage_bytes, 它的值等于memory_rss_bytes + memory_cache_bytes。于是打开监控页面查看。
之前在另一篇文章中有介绍过POD为什么会OOM,如有兴趣可参考:
https://www.cnblogs.com/yannwang/p/13287316.html
查看监控之后,发现不管是POD的memory_usage_bytes,还是memory_working_set都远小于6G,这就很奇怪了。有点怀疑会不会是宿主机OOM了。
于是登录主机查看系统日志/var/log/messages,搜索关键字"oom",发现POD被杀时,memory usage确实是已经接近6G了。并且很明显是cgroup OOM,而不是宿主机OOM了。
Jun 23 11:24:34 hostnamexxx kernel: Task in /kubepods/burstable/podxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxxx killed as a result of limit of /kubepods/burstable/podxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxxx Jun 23 11:24:34 hostnamexxx kernel: memory: usage 5859473kB, limit 5859473kB, failcnt 34555027
这就有点颠覆我的认知了,难到是监控数据有问题??我觉得不太可能。
于是进POD的cgroup目录/sys/fs/cgroup/memory/kubepods/burstable/pod<pod name>下查看memory.stat, 发现total_cache + total_rss = 2552074240, 跟监控数据是对得上的。但是,memory.usage_in_bytes的值却接近6G。
# cat memory.stat | grep total total_cache 43487232 total_rss 2508587008 # cat memory.usage_in_bytes 5999837184
难道Linux内核计数器统计有问题,这也是基本不可能的事情。于是上网搜索,也没搜到有什么相同的case,但是看到了有个帖子提到了memory.kmem.usage_in_bytes会被统计到memory.usage_in_bytes中。
灵机一动,用户的工作节点操作系统是centos 7.x,这个版本的kernel memory特性不稳定,已经有过几个已知的问题了。于是查看memory.kmem.usage_in_bytes的值。
#cat memory.kmem.usage_in_bytes 3446837248
计算发现total_cache + total_rss + memory.kmem.usage_in_bytes = memory.usage_in_bytes
所以这个问题是因为应用进程使用了kmem,cgroup OOM控制器依据的是memory.usage_in_bytes的值,当这个值超过limit时POD就会被杀了,但是普罗米修斯监控采集的数据却是memory.stat中的totoal_cache和total_cache,所以监控上看到的内存使用量并没有达到限制。
因为centos 7.x的kernerl memory不稳定,于是决定替换kubelet为禁用了kmem特性的重编译二进制,如何重编译及替换在网上有很多资料介绍。替换完后立竿见影,kmem立马将到0了,memory.usage_in_bytes值暴降,POD自动重启的问题也没在出现。
#cat memory.kmem.usage_in_bytes 0 #cat memory.usage_in_bytes 2542301184