当突然发生一个非常长的GC暂停时,我需要找出突然内存分配的来源。长时间的GC暂停(大约30秒)导致吊舱连续几次K8s健康检查失败,吊舱被重新启动,而OOM实际上没有发生。我想在K8s真正重新启动pod之前创建一个堆转储。我意识到转储应该做一些外部持久安装。
我对如何使堆转储发生的唯一想法是使用preStop钩子。问题是,当吊舱因健康检查失败而重新启动时,是否启动了preStop钩子?
也许有一个更优雅的解决方案?
发布于 2020-08-02 10:54:15
问题是,当吊舱因健康检查失败而重新启动时,是否启动了preStop钩子?
是。根据定义,由于PreStop请求或管理事件(如活动探测失败、抢占、资源争用等),在容器终止之前立即运行PreStop钩子。
在结束符终止之前,我应该使用preStop钩子来捕获Java转储吗?
是。但是您需要小心,如果容器已经处于终止状态或已完成状态,则调用preStop钩子将失败。当吊舱终止时,它在发送杀死信号之前等待默认的30秒宽限期(如果PerStop钩子未完成,则增加2秒)。如果preStop钩子需要比默认的宽限期更长的时间来完成,则必须修改terminationGracePeriodSeconds以适应这种情况。
对此还有更优雅的解决方案吗?
我不知道。我想,通过向pod添加一个空dir卷,并配置JVM将堆转储到command: ["java", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/dumps/oom.bin", "-jar", "yourapp.jar"]应该可以工作。
为什么上面的解决方案会起作用?
当kubernetes由于没有响应健康检查而杀死您的容器时,kubernetes只会重新启动容器,但是它不会重新安排容器的时间,因此不会将它移动到另一个节点。因此,在吊舱被移动到另一个节点之前,不会删除空的dir卷。因此,当容器重新启动时,新容器将挂载相同的空dir,其中将包含上次运行的堆转储。因此,您可以在事件发生后的任何时候对这些文件进行kubectl cp。复制堆转储文件可能还有其他挑战,但它们是可以解决的。有关更多信息,请访问这。
https://stackoverflow.com/questions/63214691
复制相似问题