文章目录
前段时间线上业务在排查监控时,发现监控显示容器的内存使用率很高,已经到了 90%,便反馈到我们这边,同时他们说通过 top 看实际使用的内存使用率很低,觉得监控图有问题,进行查看之后,发现监控问题不大,不过确实有些细节需要注意。
workingset 不是实际使用内存
经过一番查看,业务说的没问题,通过 top 看内存使用时,RES 显示只有 1.7G,但是监控显示使用了接近 8G。我们监控使用的指标是container_memory_working_set_bytes
,在监控图中,内存使用率的计算方式是 container_memory_working_set_bytes / container_spec_memory_limit_bytes *100%
,其中:
- container_memory_working_set_bytes:cgroup 中 memory.usage_in_bytes 的值减去 inactive file 的内存使用,但是包含了 PageCache 的使用量。具体计算方式可以参考:《Pod 被驱逐了?看看这篇文章》里面有一个计算 workingset 的脚本。同时需要注意,cgroup 中的 memory.usage_in_bytes 包含了两部分的值,一个是 RES,另一个就是 PageCache。这个可以参考《Page Cache:为什么我的容器内存使用量总是在临界点?》
- container_spec_memory_limit_bytes:容器被限制的总内存大小,即 cgroup 中的 memory.limit_in_bytes。
通过对指标的解释,我们知道了监控图没错,业务说的也没错,其实在 grafana 的监控图中,还有个 RSS 的指标,业务方其实更多的关注的是这个(也就是图中黄色的线,而不是蓝色的线)。
那这个监控指标重要吗? 在 K8s 中,当 container_memory_working_set_bytes 接近 container_spec_memory_limit_bytes 时,就可能会触发 OOM(out-of-memory),导致进程被 kill。也就是说系统还是基本根据 workingset 来杀 Pod,那岂不是很危险,也未必,为啥呢?因为 PageCache 作为系统对磁盘读写的缓存,在进程需要申请内存时,是可以被释放的。所以文章《Page Cache:为什么我的容器内存使用量总是在临界点?》说内存使用量总是在临界点,这里的临界点基本可以看成 limit 值。
为什么会有这么高的 PageCache 使用?
因为 PageCache 是对磁盘文件读写的缓存,看到这么高的PageCache 使用时,首先猜测业务是个高IO的应用,问下来其实不是,IO基本只有写日志。同时我们在查看 /proc/meminfo
时发现,Cache
的值(也就是pagecache)基本等于 active(file)
的值,我们知道 active(file)
是系统对磁盘文件的缓存,相对于匿名内存。同时我们观察到一个现象,这两者的值基本等于业务在磁盘上的日志文件的大小,业务把日志文件切割了,但是没有回收,导致日志文件非常多。
那有没有可能 PageCache 缓存了这些日志文件一直没有释放呢?我们先用 lsof 和 fuser 来查看进程有没有使用这些文件,发现没有。后来决定直接删除一个日志文件试一试,发现果然如此:删除一个日志文件,pagecache 使用量下降了,并且下降的量基本等于日志文件的大小,其中 active(file)
内存也有对应的下降量。关于 /proc/meminfo
文件的说明,可以参考《The /proc/meminfo File in Linux》,系统一直持有这些日志文件的缓存,可能是系统闲置内存够用,没有触发对PageCache 的回收。meminfo的输出示例如下,包含了系统使用内存情况的一个概览。
[decent@ubuntu ~]$ cat /proc/meminfo
MemTotal: 16249468 kB
MemFree: 335616 kB
MemAvailable: 11232216 kB
Buffers: 755932 kB
Cached: 9903440 kB
SwapCached: 0 kB
Active: 9907088 kB
Inactive: 4180388 kB
Active(anon): 3718164 kB
Inactive(anon): 481436 kB
Active(file): 6188924 kB
Inactive(file): 3698952 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 896 kB
Writeback: 0 kB
AnonPages: 3428004 kB
Mapped: 525832 kB
Shmem: 771496 kB
Slab: 1516532 kB
SReclaimable: 1346936 kB
SUnreclaim: 169596 kB
KernelStack: 34960 kB
PageTables: 29540 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 8124732 kB
Committed_AS: 20430316 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 119456 kB
VmallocChunk: 34359493092 kB
HardwareCorrupted: 0 kB
AnonHugePages: 688128 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 292704 kB
DirectMap2M: 16484352 kB
乐观来说,pagecache 使用高并不会导致 oom,但保险起见还是让业务方清理一下日志吧。