zhangguanzhang's Blog

k8s java 容器未设置 requests.cpu 导致性能问题

字数统计: 471阅读时长: 2 min
2022/12/30

内部性能测试发现了 java 容器在 k8s 的问题

由来

内部之前 es 是 docker 起的,后面换成 k8s staticPod + hostPath ,在性能压测的时候发现性能很低

过程

和版本无关,所以不放版本信息了,直接写过程了。

眉目

当时看 Prometheus 发现机器占用很低,感觉 es 没充分利用机器资源。查看下 es 的接口:

1
2
3
4
5
$ curl -s --user xxx:xxx xxx:9200/_nodes/os
...
"available_processors": 1,
"allocated_processors": 1
...

发现不对劲,默认没限制应该和宿主机 cpu 核心一样的。然后对比了下,发现 docker run 的 es 正常, k8s 则是上面的异常,对比了 docker inspect 发现 k8s 的容器 CpuShares 设置的是 2,docker 是 1024

1
"CpuShares": 2,

利用代码测测试下

1
2
3
4
5
6
7
8
9
10
11
12
cat > /opt/test.java << EOF
public class Main {
public static void main(String[] args) {
System.out.println("Available Processors = " +Runtime.getRuntime().availableProcessors());
}
}
EOF

$ docker run --rm -v /opt/test.java:/test.java --cpu-shares=2 elasticsearch:7.9.3 /usr/share/elasticsearch/jdk/bin/java /test.java
Available Processors = 1
$ docker run --rm -v /opt/test.java:/test.java elasticsearch:7.9.3 /usr/share/elasticsearch/jdk/bin/java /test.java
Available Processors = 16

通过一下步骤可以看到 docker 默认参数下 cpu.share 是 1024:

1
2
3
4
5
6
7
8
$ docker inspect xxx | grep Pid
$ grep cpu /proc/$pid/cgroup
# 用获得的 cgroup path查
$ find /sys -type d -name xxxxxxxxxxxxxxxxxxx
$ cat /sys/fs/cgroup/cpu,cpuacct/docker/xxxxxxxxxxxxxxxxxxx/cpu.shares
1024
$ docker run --rm -v /opt/test.java:/test.java --cpu-shares=1024 elasticsearch:7.9.3 /usr/share/elasticsearch/jdk/bin/java /test.java
Available Processors = 16

解决办法

可以看文章结尾参考关于大佬们的讨论,java 计算可用核心是关于 cpu 几个 cgroup 的值,默认在接口调用 docker 的时候,没给 docker 传递的话,cpu.shares 默认就是 2,可以给 pod 一个 request.cpu 1 即可避免这种问题

参考

CATALOG
  1. 1. 由来
  2. 2. 过程
    1. 2.1. 眉目
    2. 2.2. 解决办法
  3. 3. 参考