为啥 OpenJDK Docker 容器会忽略 Kubernetes 中的内存限制?
Posted
技术标签:
【中文标题】为啥 OpenJDK Docker 容器会忽略 Kubernetes 中的内存限制?【英文标题】:Why is OpenJDK Docker Container ignoring Memory Limits in Kubernetes?为什么 OpenJDK Docker 容器会忽略 Kubernetes 中的内存限制? 【发布时间】:2021-02-11 08:42:19 【问题描述】:我正在 Kubernetes 1.19.3 上使用 Docker 映像 jboss/wildfly:20.0.1.Final 运行多个 Java 应用程序。 Wildfly 服务器在 OpenJDK 11 中运行,因此 jvm 支持容器内存限制 (cgroups)。
如果我设置了内存限制,则在 Kubernetes 中运行时,容器会完全忽略此限制。但是当我在普通 Docker 中运行它时,它在同一台机器上受到尊重:
1.在 Docker 中运行 Wildfly,内存限制为 300M:
$ docker run -it --rm --name java-wildfly-test -p 8080:8080 -e JAVA_OPTS='-XX:MaxRAMPercentage=75.0' -m=300M jboss/wildfly:20.0.1.Final
验证内存使用情况:
$ docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
515e549bc01f java-wildfly-test 0.14% 219MiB / 300MiB 73.00% 906B / 0B 0B / 0B 43
正如预期的那样,容器不会超过 300M 的内存限制。
2。在 Kubernetes 中运行 Wildfly,内存限制为 300M:
现在我在 kubernetes 中启动同一个容器。
$ kubectl run java-wildfly-test --image=jboss/wildfly:20.0.1.Final --limits='memory=300M' --env="JAVA_OPTS='-XX:MaxRAMPercentage=75.0'"
验证内存使用情况:
$ kubectl top pod java-wildfly-test
NAME CPU(cores) MEMORY(bytes)
java-wildfly-test 1089m 441Mi
300M的内存限制被完全忽略并立即超过。
为什么会这样?两个测试都可以在同一台机器上进行。
回答
高值的原因是从项目kube-prometheus 收到的度量数据输出不正确。卸载 kube-projemet 并安装 metric-server 后,所有数据都使用 kubctl top 正确显示。它现在显示与 docker stats 相同的值。我不知道为什么 kube-prometheus 确实计算了错误的数据。事实上,它为所有内存数据提供了双精度值。
【问题讨论】:
我怀疑 Docker 和 Kubelet 使用不同的 cgroup 驱动程序运行。我该如何检查? 你运行的是什么分布的 kubernetes? 我在 Debian Buster 上运行的自托管节点上安装了 kubernetes。 你使用的是哪个 docker 版本? 我添加了自己的答案。原因是 kube-prometheus 的输出错误。使用 kubernetes metric-server 解决了这个问题。 【参考方案1】:我将此答案作为社区 wiki 放置,因为它可能对社区有所帮助。 Kubectl top 显示不正确的数据。 OP 解决了卸载 kube-prometheus 堆栈并安装 metric-server 的问题。
高值的原因是 Metric 的输出不正确 从项目 kube-prometheus 收到的数据。卸载后 kube-projemet 并安装 metric-server 所有数据 使用 kubectl top 正确显示。它现在显示的值与 码头工人统计。我不知道为什么 kube-prometheus 确实计算错误 数据。事实上,它为所有内存数据提供了双精度值。
【讨论】:
以上是关于为啥 OpenJDK Docker 容器会忽略 Kubernetes 中的内存限制?的主要内容,如果未能解决你的问题,请参考以下文章
Docker openjdk-8-jdk-alpine 容器时间与jdk时区不同修改方法
为啥 Kubernetes 的容器在 runsc (gVisor) 上作为 Docker 中的运行时运行时会失败?