Kubernetes上java应用内存的限制
背景:最近生产环境上有一个java应用pod隔三差五的重启,通过排查发现,jvm设置参数以及kubernetes deployment部署配置文件分别如下
在镜像构建中启动参数如下
......
......
......
......
ENV JAVA_OPTS="-Xmx1008M -Xms1008M -Xmn512M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=128M -XX:OnOutOfMemoryError=$JAVA_HOME/bin/killjava.sh -XX:+ExitOnOutOfMemoryError"
......
......
......
......
部署配置文件如下
...
containers:
- name: gk-app-ehrs
image: IMAGE_NAME
imagePullPolicy: Always
ports:
- containerPort: 80
resources:
requests:
cpu: 300m
memory: 1Gi
limits:
cpu: 500m
memory: 1Gi
...
...
经过详细的分析,我们明白了 Pod 为什么会不断的重启?原来是我们对应用的内存限制值以及应用启动参数设置的不合理导致的。
- 通过监控在业务并不繁忙的时候,该pod内存使用就已经达到了900Mi,未考虑到业务顶峰的时候场景,-Xmx 与-Xms的值1008M设置值过小
- pod内存限制资源不合理,requests和limits字段的memory值太小
下面我们来看一下 Kubernetes 下面部署 Java 应用的资源限制该如何设置?我们需要考虑哪些因素?:
requests != Xms 更准确的表述是:你的 requests 的值一定要设置的比 Xms 的值大,具体大多少这取决你的应用是否复杂,如果只是一个不复杂的应用,那么增加30%左右即可。
limits != Xmx 同样的这里不能简单的将 limits 设置为 Xmx 的值
腾讯云提供的一个设置规则
容器内存 Requests >= 1.25 * JVM 最大堆内存 ;
容器内存 Limits >= 2 * JVM 最大堆内存;
最终将配置修改如下
......
......
......
......
ENV JAVA_OPTS="-Xmx1500M -Xms1500M -Xmn1500M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=128M -XX:OnOutOfMemoryError=$JAVA_HOME/bin/killjava.sh -XX:+ExitOnOutOfMemoryError"
......
......
......
......
部署配置文件如下
...
containers:
- name: gk-app-ehrs
image: IMAGE_NAME
imagePullPolicy: Always
ports:
- containerPort: 80
resources:
requests:
cpu: 1
memory: 1875Mi
limits:
cpu: 1
memory: 2048Mi
...
...
修改后应用恢复正常,不会再隔三差五的重启啦。不同的应用会有不同的参数,应该有一些基准测试和压力测试,查看应用运行高峰时,内存的需求突发值是多少?如果你压测数据显示你设置的最大值明显过大,那么我们就适当降低该值以降低成本,他并不会导致 OOM 而引起 Pod 不断被驱逐的风险。
评论区