Kubernetes Pod Container Memory high问题排查
1. 现象
线上k8s集群报警,告警群里突然告警某容器
内存使用率高于90%
,并且后续一直有告警出现。随即登入指标监控系统查看该告警指标,如下:
该指标是通过 container_memory_working_set_bytes / container_spec_memory_limit_bytes
相除得到的。
2. 容器内内存统计
container_memory_working_set_bytes
= container_memory_usage_bytes - total_inactive_file
= container_memory_rss + container_memory_cache + kernel memory - total_inactive_file
= container_memory_rss + total_active_file + container_memory_cache + kernel memory - total_inactive_file
-
total_rss
为应用真实使用内存量,正常情况下该指标数值稳定,那为何该指标会持续上升而且一直维持很高呢?其实问题就出现在total_active_file
上。 -
Linux
系统为了提高文件读取速率,会划分出来一部分缓存内存,即 cache 内存,这部分内存有个特点,当应用需要进行 io 操作时,会向 Linux 申请一部分内存,这部分内存归属于操作系统,当应用io操作完毕后,操作系统不会立即回收,当操作系统认为系统剩余内存不足时,才会主动回收这部分内存。 -
container_memory_working_set_bytes
指标升高一部分是应用本身内存使用量增加,另一部分就是进行了 io 操作,total_active_file
升高,该指标异常一般都是应用进行了io相关操作。
3. 排查思路
猜测出大致有 2
种导致这种情况的场景。
- 内存泄露
- io 缓存
3.1 内存泄露排查
$ cat /sys/fs/cgroup/memory/memory.usage_in_bytes
4192539621
# bytes转GB,结果是 3.9GB
查看 pod
容器内内存记录:
$ cat /sys/fs/cgroup/memory/memory.stat
cache 36900864
rss 4205309952
rss_huge 2837446656
shmem 0
mapped_file 1351680
dirty 1081344
writeback 0
swap 0
workingset_refault_anon 0
workingset_refault_file 20815872
workingset_activate_anon 0
workingset_activate_file 12029952
workingset_restore_anon 0
workingset_restore_file 8785920
workingset_nodereclaim 0
pgpgin 5688606
pgpgout 5778093
pgfault 2878062
pgmajfault 0
inactive_anon 4224827392
active_anon 0
inactive_file 9543680
active_file 25153536
unevictable 0
hierarchical_memory_limit 4294967296
hierarchical_memsw_limit 4294967296
total_cache 36900864
total_rss 4205309952
total_rss_huge 2837446656
total_shmem 0
total_mapped_file 1351680
total_dirty 1081344
total_writeback 0
total_swap 0
total_workingset_refault_anon 0
total_workingset_refault_file 20815872
total_workingset_activate_anon 0
total_workingset_activate_file 12029952
total_workingset_restore_anon 0
total_workingset_restore_file 8785920
total_workingset_nodereclaim 0
total_pgpgin 5688606
total_pgpgout 5778093
total_pgfault 2878062
total_pgmajfault 0
total_inactive_anon 4224827392
total_active_anon 0
total_inactive_file 9543680
total_active_file 25153536
total_unevictable 0
rss
确实是使用了 3.9GB
的量,确实是 pod 容器的真实使用,那么基本就验证了要么程序确实内存不够,要么就是内存泄露了。
3.2 io 缓存
第二次查看内存:
$ cat /sys/fs/cgroup/memory/memory.stat
cache 36900864
rss 4205309952
rss_huge 2837446656
shmem 0
mapped_file 1351680
dirty 1081344
writeback 0
swap 0
workingset_refault_anon 0
workingset_refault_file 20815872
workingset_activate_anon 0
workingset_activate_file 12029952
workingset_restore_anon 0
workingset_restore_file 8785920
workingset_nodereclaim 0
pgpgin 5688606
pgpgout 5778093
pgfault 2878062
pgmajfault 0
inactive_anon 4224827392
active_anon 0
inactive_file 9543680
active_file 25153536
unevictable 0
hierarchical_memory_limit 4294967296
hierarchical_memsw_limit 4294967296
total_cache 36900864
total_rss 4205309952
total_rss_huge 2837446656
total_shmem 0
total_mapped_file 1351680
total_dirty 1081344
total_writeback 0
total_swap 0
total_workingset_refault_anon 0
total_workingset_refault_file 20815872
total_workingset_activate_anon 0
total_workingset_activate_file 12029952
total_workingset_restore_anon 0
total_workingset_restore_file 8785920
total_workingset_nodereclaim 0
total_pgpgin 5688606
total_pgpgout 5778093
total_pgfault 2878062
total_pgmajfault 0
total_inactive_anon 4224827392
total_active_anon 0
total_inactive_file 9543680
total_active_file 29141449
total_unevictable 0
发现 total_active_file
字段一致再涨,导致 memory_cache
一直增长,导致计算中Pod内存一直增长!
4. 解决方案
k8s
判断OOM
的时候之所以会把文件缓存(total_active_file
)也计算进去,是基于这个考虑, 并不是所有的底层文件系统都能支持Dirty文件缓存写回
的. 如果内存不够时,缓存不肯让座,那就会出问题了
.
系统统计方法是没有问题的,但是Kubernetes
未对此类特殊Pod
做针对的处理。 主要不知道是不是底层文件系统是否支持此回收,并且系统回收机制和策略是否及时(在OOM之前释放出内存出来)
。
目前比较好的解决方式:
- 应用对
active_file
的打开做一个句柄池,设置max_active_fd将长期不用的fd关闭; - 增加Pod内存;
4.1 社区讨论
过程中去kubernetes 的issue 中逛了一圈,发现了几个相关问题的讨论:
- https://github.com/kubernetes/kubernetes/issues/43916
- https://github.com/kubernetes/kubernetes/issues/104533
kubernetes should not count active_file as used memory, I have been waiting for 4 years!
5. 其他
「如果这篇文章对你有用,请随意打赏」
如果这篇文章对你有用,请随意打赏
使用微信扫描二维码完成支付