英文:
Quotas and others for a Java Microservice, JVM Params, k8s and Docker
问题
假设通过Docker和Kubernetes部署Java微服务(Dropwizard)。
一个示例微服务以192Mi
HeapSize启动并运行无误。
这被确定为基本内存要求。
一个示例Dockerfile,使用openjdk-runtime:11-hotspot
FROM some-container-reg/openjdk-runtime:11-hotspot
# 准备构建
COPY --chown=1001:1001 build/install/svc-example .
COPY --chown=1001:1001 config.yml .
# 暴露端口
EXPOSE 8080
# 设置入口点...
ENTRYPOINT ["bin/svc-example", "server", "config.yml"]
注意:
由于使用了openjdk > 10
,JVM会检测是否在容器中运行。
因此,无需像在Java 8中那样启用实验性VM功能来实现此功能。
有关详细信息,请参见下面的链接。
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8146115
对应的k8s部署
resources:
limits:
cpu: 250m
memory: 288Mi
requests:
cpu: 100m
memory: 192Mi
env:
- name: JAVA_OPTS
value: "-XX:MaxRAMPercentage=75.0"
容器的请求等于Java应用程序本身的工作量。
限制已定义为请求加上96Mi
的偏移量。
通过这样做,我希望确保除了JVM堆之外的要求有足够的资源正常工作 - MetaspaceSize,CodeCache,...
。
还在容器部署中定义了JAVA_OPTS
,通过应用-XX:MaxRAMPercentage=75.0
,这定义了JVM的总内存的75%的限制。
为什么不在-XX:Xmx=192Mi
内显式定义堆限制?有关详细信息,请参见下面的链接。
那么,现在是我的问题:
- 我上面的建议正确吗?
- 如何确定限制以实现低成本部署?
- 是否需要为JVM应用额外的参数,比如
GC
或MaxMetaspaceSize
,以防止超出限制的内存使用? - 我需要在Dockerfile中定义JVM参数吗?更明确地说,Docker的JVM和Java微服务的JVM是相同的吗?
英文:
Assuming the deployment of a Java microservice (Dropwizard) via Docker and Kubernetes.
An example microservice starts and runs flawlessly with 192Mi
HeapSize.
This is determined as the basic memory requirement.
An example Dockerfile, using openjdk-runtime:11-hotspot
FROM some-container-reg/openjdk-runtime:11-hotspot
# prepare build
COPY --chown=1001:1001 build/install/svc-example .
COPY --chown=1001:1001 config.yml .
# exposing port(s)
EXPOSE 8080
# setting entry point...
ENTRYPOINT ["bin/svc-example", "server", "config.yml"]
Note:
Since using openjdk > 10
the JVM detects if it's running in a container.
Therefore there is no need to enable experimental VM features to achieve this like back in Java 8.
For Details, please see the link below.
> https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8146115
Corresponding k8s Deployment
resources:
limits:
cpu: 250m
memory: 288Mi
requests:
cpu: 100m
memory: 192Mi
env:
- name: JAVA_OPTS
value: "-XX:MaxRAMPercentage=75.0"
The container request equals the working amount from the java application itself.
The limits have been defined as the request plus an offset of 96Mi
.
By doing this I want to ensure that the requirements besides the JVM-Heap have enough resources to work properly - MetaspaceSize, CodeCache, ...
.
Also defining JAVA_OPTS
within the container deployment by applying -XX:MaxRAMPercentage=75.0
which defines a limit of 75% of total memory for the JVM.
Why not defining explicit heap limitations within -XX:Xmx=192Mi
? For details, please see the link below.
> https://bugs.openjdk.java.net/browse/JDK-8186315
So, now to my questions:
- Am I correct with the suggestions above?
- How do you determine the limits to achieve a low-cost deployment?
- Is it required to apply additional params to the JVM, like
GC
orMaxMetaspaceSize
to prevent memory usage above the limits? - Do I need to define JVM-Args to the Dockerfile too? More clearly, the JVM of Docker and the JVM of the Java-Microservice are the same?
答案1
得分: 1
你需要使用性能分析工具对应用程序进行分析,并使用APM工具进行监控,以便根据需要微调内存需求,这是一个持续的活动。关于最后一个问题,无论Docker镜像中包含哪个JRE/JDK,都将使用该JDK/JRE来创建Kubernetes中的容器。另外我注意到你正在使用一个不推荐用于生产部署的JDK,建议改用JRE。
从Kubernetes配额的角度来看,需要记住的一点是,如果Java应用程序的内存消耗在任何时候超过了限制中定义的值,Pod将被终止。
如果没有任何节点的可用内存大于请求中定义的内存量,那么Pod将根本无法被调度。
英文:
You need to profile your app using profilers and monitor it using APM tools to fine tune memory requirements as and when its needed and its a continuous activity. Regarding the last question whatever JRE/JDK the docker image have is the JDK/JRE used to create the container for the pod in kubernetes. Also I noticed you are using a JDK which is not recommend for production deployment...rather use a JRE.
The thing to remember from Kubernetes quota perspective is that at any point if the memory consumption by the java app goes beyond the value defined in the limits the pod will be terminated.
And pod will be not be scheduled at all if there is no node which has that much free memory defined in the requests.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论