我正在使用Docker镜像jboss/wildfly:20.0.1.Final在Kubernetes 1.19.3上运行多个Java应用程序。Wildfly服务器正在OpenJDK 11上运行,因此jvm支持容器内存限制(cgroups)。
如果我设置了内存限制,则在Kubernetes中运行时容器完全忽略此限制。但是在同一台机器上以普通Docker方式运行时,此限制得到尊重:
1. 使用300M的内存限制在Docker中运行Wildfly:
$ 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中使用300M内存限制运行Wildfly:
现在我将同样的容器在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接收到的Metric数据输出不正确。卸载kube-prometheus,并改用metric-server进行安装后,所有数据都正确地显示在kubctl top中。现在它显示与docker stats相同的值。我不知道为什么kube-prometheus会计算错误的数据。实际上,它为所有内存数据提供了双倍的值。