Kubernetes环境Elasticsearch主节点堆内存溢出持续GC排查咨询
Elasticsearch专用主节点堆内存故障排查方案
堆转储排查方式的有效性说明
通过分析hprof堆转储文件定位JVM堆内存溢出、持续GC问题的思路是完全正确的,这是定位Java进程内存泄漏、大对象滞留、类加载异常等内存问题最直接、最准确的手段。
加密堆转储文件的获取方法
你拿到的堆转储文件无法读取,本质是取文件的方式不对,K8s环境下存储静态加密、容器运行时文件系统加密都会导致直接从宿主机底层存储路径拷贝的文件是加密态,按以下步骤拿可直接分析的明文文件:
- 若故障主节点Pod还未重启,直接执行
kubectl exec -it <故障主节点Pod名> -n <ES所在命名空间> -- /bin/bash进入容器内部,到JVM参数-XX:HeapDumpPath指定的堆转储输出路径(未自定义的话默认在ES工作目录下)直接拷贝文件,容器内进程读取的是解密后的明文,拷出的文件可以直接用MAT、jhat等工具分析 - 若Pod已经因OOM重启,可将故障Pod绑定的PVC临时挂载到同命名空间下的调试用busybox容器,使用和原ES Pod相同的服务账号、存储挂载权限挂载,进入调试容器后拷贝出的hprof文件就是明文可用的
- 禁止直接从宿主机的CSI挂载底层路径、块存储快照路径直接拷文件,这类路径存的是静态加密后的密文数据,无法直接用于分析。
无可用堆转储时的替代排查方案
先明确你当前集群的主节点配置本身就存在极高OOM风险,优先核查配置问题,再结合运行时指标定位根因:
- 主节点资源配置严重不符合生产要求:专用主节点负责集群元数据管理、分片调度、集群状态同步,你当前给主节点配的4G堆内存、4G容器内存限额、10G磁盘完全不满足生产要求——堆内存设为4G时,连基本的系统预留、堆外内存空间都没有,只要集群状态体积稍大、待执行任务稍有堆积就会触发OOM;10G磁盘也会导致堆转储写一半就磁盘打满,出现文件损坏。生产环境专用主节点堆内存最低配8G,对应容器内存限额设为16G(遵循堆内存不超过物理内存50%、不超过32G的JVM优化原则),磁盘最低配50G。
配置核查完后按以下步骤排查:
- 查GC日志定位内存变化趋势:ES默认开启GC日志,在容器内
/var/log/elasticsearch/路径下找gc日志文件,重点看每次Full GC之后老年代的内存占用率,如果Full GC后老年代占用没有明显回落、还在持续升高,基本可以确定存在内存泄漏 - 查JVM内存分项占用:在主节点本地执行
curl -XGET http://localhost:9200/_nodes/stats/jvm?pretty,看返回结果里segments、fielddata、query_cache这类数据节点专属的内存占用项——专用主节点不存储索引数据,这类项占比应该低于5%,如果占比过高说明节点角色配置错误,主节点混跑了数据/ingest角色 - 查集群状态体积:在主节点本地执行
curl -s http://localhost:9200/_cluster/state | wc -c计算集群状态大小,如果集群状态体积超过100MB,4G堆内存根本无法承载,基本是索引、分片数量过多导致元数据占满堆,这种情况要清理长期不用的关闭索引、降低单分片大小、减少冗余分片 - 查堆积的集群任务:执行
curl -XGET http://localhost:9200/_cluster/pending_tasks?pretty查看是否有持续堆积的分片分配、元数据更新任务,任务长期积压会在内存中生成大量滞留对象,直接占满堆内存。
排查前建议先逐台滚动调整主节点资源配置,把堆内存升到8G以上先恢复业务,不要在业务高峰直接做节点重启、索引清理操作
内容的提问来源于stack exchange,提问作者Balaji Arun
相关产品推荐
相关产品推荐

