有天,接到用戶請求, 幫助排查生產環境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