我司有几台 Ubuntu 16.04 的 Kubernetes worker node,不时的发生个别容器 CPU 使用飙升但是服务性能很低的情况,之前发现 4.4.0-117-generic 发现有内核 bug 报告 “kernel: SLUB: Unable to allocate memory on node -1”,怀疑之下升级到了 Ubuntu 16.04 里自带的 4.15.0-76-generic, 好景不长,容器 CPU 突然飙升的情况还是偶有发生,还引发了一次严重的生产事故,堪称血泪。
用 perf top 看了下,有个可疑的内核函数 overhead 很高:
然后搜索了下,发现一点线索:
- https://forum.proxmox.com/threads/linux-kernel-list_lru_count_one-patch.52591/
- https://lkml.org/lkml/2018/7/9/181
- https://www.spinics.net/lists/linux-mm/msg158019.html
描述的问题跟我们观察到的很像:
- cpu 莫名飙高
- 内核函数 list_lru_count_one 的 overhead 很高
- free 命令显示 cache + buffer 很高,free 很少
我们部分服务用到了 slf4j 的 ch.qos.logback.classic.AsyncAppender ,这个东西好像从来不 flush,导致 memory cgroup 里的 memory.stat 里的 cache 一直增长没个头,可能是这个行为慢慢就触碰到了 linux 内存管理的这个 bug 激发的条件。
解决办法就是升级到 linux >= 4.19 内核了,真是为 Linux 内核代码质量捉急!
BTW,在 CentOS 7.4.1708 + linux 3.10.0-693.2.2.el7.x86_64 上试验了第二个链接的复现命令,在那个 for loop 执行到近 2000 时系统 load 到了 2000 左右,几乎不能响应,然后最后居然执行完了 for loop,立马 time echo 3 > /proc/sys/vm/drop_caches 居然非常快,要么是 linux 3.10 还没引入这个 bug,要么是 Redhat 牛逼打了自己补丁修正了。