TIPS之 Kubernetes Pod Container Memory high问题排查

Kubernetes Pod Container Memory high问题排查

Posted by 董江 on Monday, June 24, 2024

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之前释放出内存出来)

目前比较好的解决方式:

  1. 应用对active_file的打开做一个句柄池,设置max_active_fd将长期不用的fd关闭;
  2. 增加Pod内存;

4.1 社区讨论

过程中去kubernetes 的issue 中逛了一圈,发现了几个相关问题的讨论:

kubernetes should not count active_file as used memory, I have been waiting for 4 years!

5. 其他

「如果这篇文章对你有用,请随意打赏」

Kubeservice博客

如果这篇文章对你有用,请随意打赏

使用微信扫描二维码完成支付