【问题标题】:Kubernetes OOM pod killed because kernel memory grows to muchKubernetes OOM pod 被杀死,因为内核内存增长太多
【发布时间】:2019-05-14 02:22:11
【问题描述】:

我正在开发一个 java 服务,它基本上在网络文件系统中创建文件来存储数据。它在 Ubuntu 18.04 LTS 的 k8s 集群中运行。 当我们开始限制 kubernetes 中的内存(limits: memory: 3Gi)时,pods 开始被 kubernetes OOMKilled。

一开始我们以为是java进程的内存泄漏,但深入分析发现问题出在内核的内存上。 我们验证了查看文件 /sys/fs/cgroup/memory/memory.kmem.usage_in_bytes

我们将这种情况隔离为仅使用 DD 命令创建文件(没有 java),如下所示:

for i in {1..50000}; do dd if=/dev/urandom bs=4096 count=1 of=file$i; done

使用 dd 命令,我们看到同样的事情发生了(内核内存增长到 OOM)。 k8s重启pod后,我开始做describe pod:

  • 最后状态:终止
  • 原因:OOMKilled
  • 退出代码:143

创建文件会导致内核内存增长,删除这些文件会导致内存减少。但是我们的服务存储数据,所以它会不断地创建很多文件,直到 Pod 因为 OOMKilled 而被杀死并重新启动。

我们测试了使用带有 --kernel-memory 参数的独立 docker 来限制内核内存,它按预期工作。内核内存增长到极限,不再上升。但是我们没有在 Kubernetes 集群中找到任何方法来做到这一点。 有没有办法限制 K8S 环境中的内核内存? 为什么文件的创建会导致内核内存增长而没有被释放?

【问题讨论】:

  • 我猜你正在设置像kubernetes.io/docs/concepts/configuration/… 这样的限制,而你已经查看了github.com/kubernetes/kubernetes/issues/61937
  • 一个java进程正在运行吗?文件是否正在写入持久卷?
  • 你好@RyanDawson。此问题发生在写入文件的 java 进程和写入文件的其他程序(非 java)中。我们可以使用 java 和非 java 程序以及 DD linux 命令重现此问题。对于 java 程序,java 使用的内存不会增长。问题是内核内存。好像写文件需要内存内核,没有释放。我们正在将文件写入持久卷中,无论是在本地磁盘中还是在 nfs 中。结果是一样的
  • 这个问题很容易重现。我很惊讶,网上没有很多类似的案例
  • 我们在部署中添加(感谢您的帖子)以下内容:initContainers: - name: init-sysctl image: busybox command: - /bin/sh - -c - | sysctl -w vm.vfs_cache_pressure=value securityContext: privileged: true

标签: docker linux-kernel kubernetes out-of-memory


【解决方案1】:

感谢所有这些信息,它非常有用!

在我的应用上,我通过创建一个新的侧容器来解决这个问题,该容器每 5 分钟运行一次 cron 作业,使用以下命令:

echo 3 > /proc/sys/vm/drop_caches

(请注意,您需要侧容器以特权模式运行)

它运行良好,并且具有可预测的优点:每 5 分钟,您的内存缓存将被清除一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    相关资源
    最近更新 更多