java - 当 K8s 健康检查重新启动 pod 时创建 JVM heapdump - 没有发生 OOM
问题描述
我有一种情况,突然发生很长的 GC 暂停,我需要找出突然分配内存的原因。长时间的 GC 暂停(大约 30 秒)导致 pod 连续多次失败 K8s 健康检查,并且 pod 重新启动,实际上没有发生 OOM。我想在 K8s 实际重新启动 pod 之前创建一个堆转储。我意识到应该对一些外部持久安装进行转储。
我对如何导致堆转储发生的唯一想法是使用 preStop 挂钩。问题是,当 Pod 因健康检查失败而重新启动时,是否会触发 preStop 钩子?
也许有一个更优雅的解决方案?
解决方案
问题是,当 Pod 因健康检查失败而重新启动时,是否会触发 preStop 钩子?
是的。根据定义,perStop
钩子在容器因 API 请求或管理事件(例如活动探测失败、抢占、资源争用等)而终止之前立即运行。
我应该在 pod 终止之前使用 preStop 挂钩来捕获 Java 堆转储吗?
是的。但是你需要小心,如果容器已经处于终止或完成状态,对 preStop 钩子的调用会失败。当Pod 终止时,它会等待默认的 30 秒宽限期(如果 PerStop 挂钩未完成,则额外等待 2 秒),然后再发送 KILL 信号。如果 preStop 挂钩需要比默认宽限期允许的时间更长的时间来完成,您必须进行修改terminationGracePeriodSeconds
以适应这种情况。
对此有更优雅的解决方案吗?
我不知道。我想通过向 pod 添加一个空的 dir卷,并配置 JVM 以将堆转储到该目录command: ["java", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/dumps/oom.bin", "-jar", "yourapp.jar"]
应该可以工作。
为什么上述解决方案会起作用?
当 kubernetes 因为没有响应健康检查而杀死你的容器时,kubernetes 只会重新启动容器,但不会重新调度 pod,因此不会将其移动到另一个节点。因此,在将 pod 移动到另一个节点之前,不会删除空的 dir 卷。因此,当容器重新启动时,新容器将挂载相同的空目录,该目录将包含上次运行的堆转储。因此,您可以kubectl cp
在活动结束后随时查看这些文件。复制堆转储文件可能还有其他挑战,但它们是可以解决的。检查此以获取更多信息。
推荐阅读
- objective-c - 使用更新的值搜索和修改 NSMutableArray 对象
- reactjs - 如何在应用引擎 flex 上将 HSTS 标头添加到我的 nginx / react 应用?
- emacs - 如何使用图标或面孔自定义 org-agenda-write 输出?
- html - 使用 CSS 来适应 HTML 网站的所有元素的最佳方式是什么?
- javascript - 我可以访问 ES6 模块中的全局 ES5 变量吗?
- sql - 如何将学生分成3组?
- python - 键错误:'begins_at'
- visual-studio - Visual Studio - 创建一个项目模板,该模板显示在解决方案的“添加新项目”对话框中
- asp.net - 无法在 VISUAL STUDIO 中编辑和继续 ASP.NET
- alexa - Alexa 技能失败 LAMBDA - 请求的技能响应有问题