![GKE 的容器优化操作系统内存不足导致冻结](https://linux22.com/image/709648/GKE%20%E7%9A%84%E5%AE%B9%E5%99%A8%E4%BC%98%E5%8C%96%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%86%85%E5%AD%98%E4%B8%8D%E8%B6%B3%E5%AF%BC%E8%87%B4%E5%86%BB%E7%BB%93.png)
我在 GKE 上使用 Container-Optimized OS 时遇到问题。如果我运行这个简单的命令https://pastebin.com/raw/0WPAnAzn消耗所有 RAM,主机在某个时候会冻结并且不响应任何操作。预期行为:进程应该被 OOM 终止程序终止。我在原版 Ubuntu 和 CentOS 镜像上尝试过,效果很好:进程被终止,没有冻结。
串行控制台中有三种可能的 kmsg 输出:
- 在某些情况下,日志不包含与冻结相关的任何内容
- 有时,其他进程会连续被 OOM 终止,然后冻结,没有任何相关消息
- 最有趣的是:OOM 终止,随后出现内核恐慌(https://pastebin.com/raw/gtdsg6vQ)
冻结伴随接近 100% 的 CPU 负载。
那么这是预期的行为还是有什么问题?
答案1
经过一些实验,我发现它与 GKE 或 GCP 无关。甚至与 COS 映像也无关。
实际上,这是 Linux 内核处理 OOM 的方式。OOM 终止程序启动得太晚,并且是在内存受限的环境中运行。它使用进程的 来决定终止哪个进程oom_score
。
在主机上运行 Kubernetes 时,有许多高oom_score_adjust
价值的进程(这些是 pod其规格中没有内存限制)。如果您的 RAM 消耗器 pod 设置了限制,其结果oom_score
可能会低于许多其他进程。
在这种情况下,OOM 终止程序将首先终止那些具有最高优先级的进程,oom_score
然后才有机会终止真正贪婪的进程。我不知道为什么,但是在这种情况下 Linux 完全冻结了。
我发现一个解决方法此工具将其安装为 DaemonSet 解决了这个问题。它会毫不留情地杀死贪婪的进程。