【问题标题】:Create JVM heapdump when K8s healthcheck restarts the pod - no OOM occur当 K8s 健康检查重新启动 pod 时创建 JVM heapdump - 没有发生 OOM
【发布时间】:2020-11-22 15:35:32
【问题描述】:

我有一种情况,突然发生了很长的 GC 暂停,我需要找出突然分配内存的原因。长时间的 GC 暂停(大约 30 秒)导致 pod 连续多次失败 K8s 健康检查,并且 pod 重新启动,实际上没有发生 OOM。我想在 K8s 实际重新启动 pod 之前创建一个堆转储。我意识到应该对一些外部持久挂载进行转储。

我对如何导致堆转储发生的唯一想法是使用 preStop 挂钩。 问题是,当pod因为健康检查失败而重新启动时,是否会触发preStop hook?

也许有更优雅的解决方案?

【问题讨论】:

    标签: java kubernetes jvm heap-dump kubernetes-health-check


    【解决方案1】:

    问题是,当 pod 运行时是否会触发 preStop 钩子 由于健康检查失败而重新启动?

    是的。根据definitionperStop 挂钩会在容器因 API 请求或管理事件(如活性探测失败、抢占、资源争用等)而终止之前立即运行。


    我应该使用 preStop 钩子在 pod 之前捕获 Java Heap Dump 终止?

    是的。但是你需要小心,如果容器已经处于终止或完成状态,对 preStop 钩子的调用会失败。当pod is terminated 时,它会在发送 KILL 信号之前等待默认的 30 秒宽限期(如果 PerStop 挂钩未完成,则额外等待 2 秒)。如果 preStop 挂钩需要比默认宽限期允许的时间更长的时间来完成,您必须修改 terminationGracePeriodSeconds 以适应这种情况。


    对此有更优雅的解决方案吗?

    我不知道。我想通过向 pod 添加一个 empty dir 卷,并配置 JVM 以将堆转储到该目录 command: ["java", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/dumps/oom.bin", "-jar", "yourapp.jar"] 应该可以工作。

    为什么上述解决方案会起作用?

    当 kubernetes 因为没有响应健康检查而杀死你的容器时,kubernetes 只会重启容器,但不会重新调度 pod,因此不会将其移动到另一个节点。因此,在将 pod 移动到另一个节点之前,不会删除空的 dir 卷。因此,当容器重新启动时,新容器将挂载相同的空目录,该目录将包含上次运行的堆转储。因此,您可以在活动结束后随时kubectl cp 这些文件。复制堆转储文件可能还有其他挑战,但它们是可以解决的。更多信息请查看this

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 2021-05-07
      • 2019-09-29
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 2018-12-30
      • 1970-01-01
      • 2021-06-13
      相关资源
      最近更新 更多