避坑指南
从 java 10 开始,JVM 在分配堆大小的时候,会考虑容器内存限制,而不是主机配置。
对应 JVM
参数为默认开启
java -XX:+UseContainerSupport
可以用过此方法禁用
java -XX:-UseContainerSupport
此参数已向后移植到 Java 8: 文档地址
如果不修改 JVM
内存参数,则默认最大使用总内存的四分之一。
在容器中可以设置一下参数进行更细粒度的内存控制。
-
-XX:InitialRAMPercentage
-
-XX:MaxRAMPercentage
-
-XX:MinRAMPercentage
值介于 0.0 到 100.0 之间,MaxRAMPercentage
默认值为 25.0。
基于 tomcat 容器下 JVM 配置
可以通过设置容器环境变量 JAVA_OPTS
containers:
- name: java_app
env:
- name: JAVA_OPTS
value: "xxxxxxx"
基于 jdk 容器的 Spring boot 下 JVM 配置
可以通过设置容器环境变量 JAVA_TOOL_OPTIONS
containers:
- name: java_app
env:
- name: JAVA_TOOL_OPTIONS
value: "xxxxxxx"
实战
设置最大容量为总内存的 80%,且使用 k8s 限制容器最大内存为 500M
可见容器正常运行
接下来模拟一个比较苛刻的条件,我们将内存限制为 200M
可以看到容器未能正常启动
查看时间可见为 pod 使用的内存已经超过 k8s 的限制,因此 OOM killed 了
总结 使用 k8s limits
与 jvm -XX:+UseContainerSupport -XX:MaxRAMPercentage=80.0
的配合可以做到对java 程序更加细粒度的控制,无需针对每个程序进行 jvm
内存的计算,仅需控制 k8s limits
即可控制对应程序的内存控制。
参考资料
https://stackoverflow.com/questions/54516988/what-does-usecontainersupport-vm-parameter-do
https://www.oracle.com/java/technologies/javase/8u191-relnotes.html