我们在 K8s pod 上得到了 OOMKilled 事件。我们希望在发生此类事件时在 pod 被逐出之前运行本机内存分析命令。是否可以添加这样的钩子?
更具体地说:我们使用 JVM 标志运行-XX:NativeMemoryTracking=summary
。我们想在 pod 逐出之前运行jcmd <pid> VM.native_memory summary.diff
以查看导致 OOM 的原因。
看起来几乎不可能处理。
基于Github上关于在OMM上优雅停止的答案 杀戮:
当前无法更改 OOM 行为。Kubernetes(或运行时)可以在容器接近其内存限制时为您的容器提供信号。不过,这将尽最大努力,因为可能无法按时处理内存峰值。
以下是官方文档:
如果节点在 kubelet 能够回收内存之前遇到系统 OOM(内存不足)事件,则节点依赖于响应oom_killer。 kubelet 根据 Pod 的服务质量为每个容器设置一个oom_score_adj值。
因此,如您所知,您没有太多机会以某种方式处理它。 这是关于 OOM 处理的大文章,我在这里只拿一小部分,关于内存控制器的内存处理:
遗憾的是,此过程可能无法执行太多其他操作来响应 OOM 情况。如果它已使用 mlock() 或 mlockall() 将其文本锁定到内存中,或者它已经驻留在内存中,则它现在知道内存控制器内存不足。但是,它不能做太多其他事情,因为大多数感兴趣的操作都需要分配更多内存。
我唯一能提供的是从 cAdvisor(在这里您可以获得 OOM Killer 事件)或 Kubernetes API 获取数据,并在您看到非常接近内存不足的指标时运行您的命令。我不确定在获得 OOM 杀手事件后您是否有时间做某事。
以下是我们用来分析 K8S 中的 pod OOMKilled 的一些步骤。
-
通过普罗米修斯进行内存使用情况监控
- 不仅指标
container_memory_working_set_bytes
用于监视内存使用情况,还用于监视container_memory_max_usage_bytes
。 - 我们可以从上述指标中发现一些异常的内存增加,以便根据我们的逻辑代码进一步调查。
- 不仅指标
-
检查系统日志
- 在基于 systemd 的 Linux 发行版中。要使用的工具是
journalctl
.
sudo journalctl --utc -ke
-ke
仅显示内核消息并跳转到日志末尾。 下面的一些日志
memory: usage 4194304kB, limit 4194304kB, failcnt 1239 memory+swap: usage 4194304kB, limit 9007199254740988kB, failcnt 0 kmem: usage 13608kB, limit 9007199254740988kB, failcnt 0 Memory cgroup stats for /kubepods.slice/kubepods-burstable.slice/kubepods-burst...
- 我们可以在系统视图中找到一些异常的内存使用情况。
- 在基于 systemd 的 Linux 发行版中。要使用的工具是
-
检查上述文件夹中的内存 cgroup 统计信息
- 检查文件夹
/sys/fs/cgroup/memory/kubepods.slice/kubepods-burstable.slice
下的文件以查找内存分配信息。
- 检查文件夹
-
Pod 的内存转储
- 我们可以在 pod 的
preStop
添加一个钩子来转储 pod 的内存,可以根据转储文件进行进一步的调查。这是Java的一个示例
lifecycle: preStop: exec: command: - sh - -c - "jmap -dump:live,format=b,file=/folder/dump_file 1"
- 我们可以在 pod 的
-
继续个人资料
- 使用继续配置文件工具(如热像仪)监视 Pod 的内存使用情况,并查找泄漏点配置文件数据。