关于java k8s容器环境中的jvm配置与优化

1. 前言

环境

版本

备注

k8s

v1.22+

配置cpu/mem limit、健康/就绪检查

openjdk

8

openjdk version "1.8.0_342"

k8s容器化(docker)环境更好的解决了 java app 运行环境的封装问题。但存在着一些限制,比如 Java 并不能发现 pod 设置的内存限制(mem limit,java 默认以宿主机的内存为基准),当 java 内存占用超出 pod mem limit限制时,很容易导致OOM,导致pod重启(健康检查不通过),使服务无法正常对外提供服务等。可以通过以下方式查看:

# 异常查看方法

# 可以查看系统日志
dmesg -T |grep "Out of memory"

# 查看pod状态
kubectl get pod

# 查看pod事件
kubectl describe pod pod-name

OOM说明:

操作系统有一个内核job称为 “Out of memory killer (OOM 终结者)”,当在可用内存极低的情况下会杀死某些进程。只要达到触发条件就会激活,选中某个进程并杀掉。 通常采用启发式算法,对所有进程计算评分 (heuristics scoring),得分最低的进程将被 kill 掉(怎么计算的我也不是很懂~)。 因此 OOM 是系统内核内置的安全保护措施,当可用内存不足, 可能会影响系统稳定,就会设法找出进程并kill。

2. 问题

Docker 容器本质是是宿主机上的一个进程,容器中的查看内存、cpu 与宿主机一致(cat /proc/meminfo,/proc/cpuinfo或使用命令top查看),而 Java 是通过 /proc/meminfo 来获取到内存信息。默认情况下,JVM 的 Max Heap Size 是系统内存的 1/4。

因此,通过设置pod 的 limit 资源限制,可能会导致容器分配的内存小于 JVM 的内存,从而 JVM 进程会被杀死引发OOM。

3. 解决方案

jdk 1.8 堆内存逻辑上分为三部分:新生区+养老区+元空间

这里提供的方法解决 JVM 内存与容器内存配置不一致的问题(还有一种是设置MaxRAMPercentage参数,这里不作讨论),通过在启动参数中设置 JVM xmx xms等参数调整jvm内存大小等,实现 JVM 内存与容器内存配置一致,参数参考如下

ENTRYPOINT ["java", "-Xms512m","-Xmx512m","-Xmn256m","-XX:MetaspaceSize=256m","-XX:MaxMetaspaceSize=256m","-XX:+UseG1GC","-jar","app.jar"]

参数说明:

参数

说明

备注

-Xms

设定程序启动时占用内存

建议与-Xmx相同,避免每次垃圾回收完成后JVM重新分配内存

-Xmx

设定程序运行期间最大可占用的内存

建议为实例内存的3/5

-Xmn

设置年轻代大小

对响应有要求的应用,此值可以尽可能的设大

-XX:MetaspaceSize

设置元空间大小

元空间和gc回收有关,值太小会触发fullGC的异常,参考值256m / 512m

-XX:MaxMetaspaceSize

设置元空间最大大小

默认无限制,不配置的话元空间占用的内存会一直增长

-XX:+UseG1GC

开启G1垃圾收集器

回收垃圾,释放资源

-XX:+HeapDumpOnOutOfMemoryError

设置内存溢出时导出堆中相关信息

根据需要配置

-XX:HeapDumpPath=./logs/heap

设置导出堆信息日志路径

示例所占内存配置为

pod分配内存

jvm内存

备注

>=1G

512m+256m+256m

jvm=heap+metaspace+other

注意事项:

metaspacesize要设置最大空间大小,否则空间占用无限大(java8版本之后)

4. 总结及参考配置

分配内存   堆配置推荐

1.5G          -Xmx1G -Xms1G -Xmn256M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M

3G              -Xmx2G -Xms2G -Xmn750M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M

7G              -Xmx6G -Xms6G -Xmn750M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M

以上是关于jvm优化的心得,实际的配置,可结合jvm监控Actuator/ JMX Exporter等方式进行观测统计后配置。个人小解,仅作参考~

觉得有用点个关注/收藏吧~

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
监控KubernetesK8s容器内部的JVM是一种重要的操作,它能够帮助我们了解JVM的性能和健康状况以及整个容器环境JVM运行情况。以下是一些方法和工具来监控K8s容器内部的JVM。 首先,我们可以使用Kubernetes Dashboard或类似的监控工具来查看容器的资源使用情况,例如CPU、内存和存储。这可以帮助我们了解JVM是否正在消耗太多的资源或者是否需要进行资源调整。 其次,我们可以通过日志收集工具,如ELK(Elasticsearch、Logstash和Kibana)堆栈,监控JVM的日志输出。这些工具可以帮助我们实时查看JVM的日志,并进行搜索和过滤。 另外,可以使用性能监控工具,例如Prometheus和Grafana,来监控JVM的性能指标,如内存使用、GC(垃圾回收)时间、线程和类加载情况等。这些工具提供了仪表板和可视化图表,使我们能够直观地了解JVM运行情况。 还可以使用工具如VisualVM和JMX(Java Management Extensions)来远程监控JVM。这些工具可以通过JMX协议访问JVM的MBean(管理Bean),并提供可视化界面来监控和分析JVM运行时数据。 最后,我们还可以使用APM(Application Performance Monitoring)工具来监控K8s容器内部的JVM。APM工具可以提供更深入的性能监控和分析,例如方法级别的调用链跟踪、错误和异常的监测等。 综上所述,监控K8s容器内部的JVM可以通过使用Kubernetes Dashboard、ELK堆栈、Prometheus和Grafana、VisualVM、JMX和APM等工具来实现。这可以帮助我们全面了解JVM的性能和健康状况,并及时发现和解决潜在的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值