如何从 buildpack 生成的 docker 映像中禁用内存计算器
Posted
技术标签:
【中文标题】如何从 buildpack 生成的 docker 映像中禁用内存计算器【英文标题】:how to disable memory calculator from docker image generated by buildpack 【发布时间】:2022-01-07 22:38:37 【问题描述】:当我在 deployment.yml 中为使用命令 (mvn spring-boot:build-image) 生成 docker 映像的 Spring Boot 应用程序建立内存限制 (-Xmx512m -Xms512m) 时,我收到以下错误:
Setting Active Processor Count to 4
Adding $JAVA_OPTS to $JAVA_TOOL_OPTIONS
unable to calculate memory configuration
all memory regions require 1130933K which is greater than 956052K available for allocation:
-Xmx512M, 0 headroom, -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=94645K, -XX:ReservedCodeCacheSize=240M,
-Xss1M * 250 threads ←[31;1mERROR: ←[0mfailed to launch: exec.d: failed to execute exec.d file
at path '/layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator': exit status 1
当前的 deployment.yml 配置:
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: JAVA_OPTS
value: >-
-XX:+PrintGCDetails
-Xlog:gc
-XX:+UseParallelGC
-XX:+PrintFlagsFinal
-Xmx512m
-Xms512m
resources:
requests:
cpu: 1554m
memory: 979M
limits:
cpu: 1554m
memory: 979M
如何正确设置内存限制或禁用 buildpack 内存计算器?
注意:我使用的是 JAVA 11。
更新:
感谢您的回答。 但是我应用了第二个选项,我理解您的观点,我将尝试对方法进行总结
迭代 1:无限制
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: JAVA_OPTS
value: >-
-Xlog:gc
-XX:+UseParallelGC
grafana visualization it1
内存计算器:
Calculating JVM memory based on 13287832K available memory
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx12681764K -XX:MaxMetaspaceSize=94067K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 13287832K, Thread Count: 250, Loaded Class Count: 14194, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 128 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError -XX:ActiveProcessorCount=4 -Xlog:gc -XX:+UseParallelGC -XX:MaxDirectMemorySize=10M -Xmx12681764K -XX:MaxMetaspaceSize=94067K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enable=true
Xmx12681764K = 1585,2205 MB
在这种情况下,Grafana 从硬件可视化所有资源,这不是理想的配置,因此,有必要从上边界定义限制,即 Pod。
迭代 2:在 kubernetes 级别定义了限制
env:
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: JAVA_OPTS
value: >-
-Xlog:gc
-XX:+UseParallelGC
resources:
requests:
cpu: 1554m
memory: 979M
limits:
cpu: 1554m
memory: 979M
grafana visualization it2
内存计算器:
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx349984K -XX:MaxMetaspaceSize=94067K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 956052K, Thread Count: 250, Loaded Class Count: 14194, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 128 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError -XX:ActiveProcessorCount=4 -Xlog:gc -XX:+UseParallelGC -XX:MaxDirectMemorySize=10M -Xmx349984K -XX:MaxMetaspaceSize=94067K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enabl
在这种情况下,内存计算器会确定与应用程序一起运行的最小内存,但不限制上限,因为它受 k8s 级别的配置限制。我的疑问是由 grafana 可视化的延迟引起的。
正如您所说,内存计算器是我们的帮手。
在此先感谢
阿尔贝托。
【问题讨论】:
【参考方案1】:你得到了错误:
all memory regions require 1130933K which is greater than 956052K available for allocation:
-Xmx512M, 0 headroom, -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=94645K, -XX:ReservedCodeCacheSize=240M,
-Xss1M * 250 threads
这告诉您您的内存配置无效。您要分配给 JVM 的内存量不符合您对容器设置的限制。
有很多方法可以解决这个问题:
增加容器内存限制以适应 JVM。错误消息告诉您需要多少,1130933K
。
减少分配给 JVM 的内存量,使其符合容器内存限制。错误消息告诉您正在使用哪些 JVM 内存设置,您可以在JAVA_TOOL_OPTIONS
(或JAVA_OPTS
,其中添加的任何内容都包含在JAVA_TOOL_OPTIONS
)中覆盖它们以限制它们。
从 JAVA_OPTS 中删除 -Xmx512m -Xms512m
并让内存计算器生成最大的 JVM 内存配置,该配置将适合您分配的容器内存限制。您不会获得那么多堆,但会在给定的容器内存限制内获得尽可能大的堆。
关于这些选项的一些说明:
如果您尝试选项 #2,请注意减少的内容。 JVM 需要大量内存,但这也是它如此之快的原因。确保在进行任何更改之前和之后进行性能测试,以确保不会影响应用程序的性能(或确认您的性能仍然达到要求的水平)。
使用 Paketo Java buildpack,您真的不应该设置 -Xmx
和 -Xms
。相反,您要做的是调整其他内存设置,例如-Xss
、-XX:ReservedCodeCacheSize=240M
、-XX:MaxDirectMemorySize=10M
、线程数等...
内存计算器将动态调整-Xmx
和-Xms
设置,以便它们消耗容器中剩余的内存。如果您手动设置这些值,可能会发生错误,因为这些值太大(这里发生的情况),或者您将它们设置得太低并且 JVM 没有使用所有可用的内存.让内存计算器完成它的工作,您将获得最佳设置。
没有禁用内存计算器的选项,我强烈警告不要尝试这样做。内存计算器是你的朋友。
它就像一个用于 JVM 内存设置的编译器。它正在检查和验证您输入的设置,因此它可以提前告诉您内存配置是否存在问题。它抱怨可能很烦人,但这比让你的容器在半夜崩溃要好得多,因为它内存不足。如果它抱怨,请调整您的内存配置,然后放心地知道所有内容都已适当大小以适合您的容器。
默认情况下,内存计算器会根据生产部署调整您的应用程序大小,优化性能,而不是低内存消耗。同样,Java 以更高的内存消耗换取速度。为此,这意味着您的容器至少需要 1G 的 RAM。
内存计算器有一个Paketo RFC to add a low-memory mode。这将使运行 PoC 应用程序和其他低流量应用程序变得更容易,这些应用程序愿意接受潜在的较低性能以换取减少内存消耗(从而降低成本)。此 RFC 在本文中尚未实施,但我们希望在不久的将来实施。
【讨论】:
以上是关于如何从 buildpack 生成的 docker 映像中禁用内存计算器的主要内容,如果未能解决你的问题,请参考以下文章
使用云原生buildpacks将你的代码转换成Docker Image | 技术干货
在 Paketo.io / Cloud Native Buildpacks 构建的 Docker 容器中运行 Nuxt.js