关于java k8s容器环境中的jvm配置与优化
环境版本备注k8sv1.22+配置cpu/mem limit、健康/就绪检查openjdk8k8s容器化(docker)环境更好的解决了 java app 运行环境的封装问题。但存在着一些限制,比如 Java 并不能发现 pod 设置的内存限制(mem limit,java 默认以宿主机的内存为基准),当 java 内存占用超出 pod mem limit限制时,很容易导致OOM,导致pod重启(
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等方式进行观测统计后配置。个人小解,仅作参考~
觉得有用点个关注/收藏吧~
更多推荐



所有评论(0)