甘草片
作者甘草片·2023-08-30 18:07
软件开发工程师·安天科技

K8S升级1.25后java应用内存使用剧增

字数 4782阅读 665评论 0赞 0

K8S v1.25 版本开始引入cgroup v2,OpenShift v4.12目前暂未正式引入,处于技术预览阶段。

老版本 java(低于openjdk11.0.16,低于openjdk8u372) 不识别 cgroup v2,会存在一个兼容性问题,导致升级k8s 1.25后,java 应用内存使用率增加到两倍或者更多,在节点资源不够充分的情况下,应用资源使用剧增会频繁触发驱逐机制。

网上很多用户k8s升级到1.25遇到了这个问题
https://github.com/Azure/AKS/issues/3443

什么是 cgroup

什么是 cgroup?
cgroups 是一种可建立资源管理功能的 Linux 内核能力, 例如为正在运行的进程限制 CPU 使用率或设置内存限制。
当使用 Kubernetes 中的资源管理能力时,例如配置 Pod 和容器的请求和限制, Kubernetes 会使用 cgroups 来强制执行你的资源请求和限制。
Linux 内核提供了两个版本的 cgroup:cgroup v1 和 cgroup v2。

什么是 cgroup v2?
cgroup v2 是 Linux cgroup API 的最新版本, 提供了一个具有增强的资源管理能力的统一控制系统。反正就是更强了,详细看这个 release 说明:https://kubernetes.io/zh-cn/blog/2022/08/31/cgroupv2-ga-1-25/

解决方法

Openjdk11.0.16及更高版本或者openjdk15或更高版本 Openjdk11.0.16 在dockerhub可以下载,如果是用的redhat openjdk可在redhat的镜像仓库中查询 https://bugs.openjdk.org/browse/JDK-8230305

Openjdk8u372 及更高版本 openjdk8u372 在dockerhub上还没更新,急用的话需要自己做一个镜像。如果是用的redhat openjdk可在redhat的镜像仓库中查询 https://developers.redhat.com/articles/2023/04/19/openjdk-8u372-feature-cgroup-v2-support#

创建测试集群,识别节点 cgroup 版本

找个k8s集群复现下问题,并测试一下升级 java 能不能解决问题。

cgroup 版本取决于正在使用的 Linux 发行版和操作系统上配置的默认 cgroup 版本。要检查你的发行版使用的是哪个 cgroup 版本,请在该节点上运行 stat -fc %T /sys/fs/cgroup/ 命令。官网

https://kubernetes.io/zh-cn/docs/concepts/architecture/cgroups/

stat -fc %T /sys/fs/cgroup/

对于 cgroup v2,输出为 cgroup2fs。对于 cgroup v1,输出为 tmpfs。

在 azure 上创建一个AKS测试集群,添加两个节点池,使用一样的规格 B2ms,选择不同的版本,分别是1.24.9 和1.25.6。完成后通过 kubectl get node 查看节点信息

[root@centos8 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
aks-pool124-50226831-vmss000001 Ready agent 22h v1.24.9
aks-pool125-31550517-vmss000000 Ready agent 22h v1.25.6

[root@centos8 ~]# kubectl debug node/aks-pool124-50226831-vmss000001 -it --image=mcr.microsoft.com/dotnet/runtime-deps:6.0
Creating debugging pod node-debugger-aks-pool124-50226831-vmss000001-v86tf with container debugger on node aks-pool124-50226831-vmss000001.
If you don't see a command prompt, try pressing enter.
root@aks-pool124-50226831-vmss000001:/# stat -fc %T /sys/fs/cgroup/
tmpfs

这个节点v1.24.9是cgroup v1

[root@centos8 ~]# kubectl debug node/aks-pool125-31550517-vmss000000 -it --image=mcr.microsoft.com/dotnet/runtime-deps:6.0
Creating debugging pod node-debugger-aks-pool125-31550517-vmss000000-8jn6b with container debugger on node aks-pool125-31550517-vmss000000.
If you don't see a command prompt, try pressing enter.
root@aks-pool125-31550517-vmss000000:/# stat -fc %T /sys/fs/cgroup/
cgroup2fs

这个节点v1.25.6是cgroup v2

发布测试 java 应用,获取内存占用

找一个 java 代码编译打包制作镜像,基础镜像分别选择 openjdk:11.0.11 和 openjdk:11.0.16。做好的镜像推送到仓库
cai11745/openjdk:11.0.11-spring-petclinic-v1
cai11745/openjdk:11.0.16-spring-petclinic-v1
java 代码我使用这个,以前测试用的一个简单demo
https://github.com/cai11745/spring-petclinic

创建一个 java11011 namespace,发布一个deployment,两个pod分布在两个节点,过5分钟,kubectl top pod 查看两个pod 的内存使用情况,会发现 1.25.6 节点上pod明细比 1.24.9 节点上pod内存使用更多,基本是双倍了。

[root@centos8 ~]# kubectl create ns java11011  

[root@centos8 ~]# kubectl create deploy java11011 --image=cai11745/openjdk:11.0.11-spring-petclinic-v1 -n java11011
[root@centos8 ~]# kubectl -n java11011 scale deploy java11011 --replicas=2

[root@centos8 ~]# kubectl -n java11011 get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
java11011-65646f98ff-d8tdk 1/1 Running 0 11h 10.244.0.10 aks-pool125-31550517-vmss000000
java11011-65646f98ff-fjl72 1/1 Running 0 11h 10.244.1.7 aks-pool124-50226831-vmss000001

[root@centos8 ~]# kubectl -n java11011 top pod
NAME CPU(cores) MEMORY(bytes)
java11011-65646f98ff-d8tdk 2m 577Mi
java11011-65646f98ff-fjl72 2m 229Mi

创建一个 java11016 namespace,发布一个deployment,使用 java11.0.16的镜像,会发现两个pod使用内存差不多,说明了 java 版本的升级已经解决了cgroup2 带来的影响。

[root@centos8 ~]# kubectl create ns java11016
[root@centos8 ~]# kubectl create deploy java11016 --image=cai11745/openjdk:11.0.16-spring-petclinic-v1 -n java11016
[root@centos8 ~]# kubectl -n java11016 scale deploy java11016 --replicas=2

[root@centos8 ~]# kubectl -n java11016 get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
java11016-59c7c945f7-88v56 1/1 Running 0 12h 10.244.0.11 aks-pool125-31550517-vmss000000
java11016-59c7c945f7-lvhps 1/1 Running 0 12h 10.244.1.8 aks-pool124-50226831-vmss000001

[root@centos8 ~]# kubectl -n java11016 top pod
NAME CPU(cores) MEMORY(bytes)
java11016-59c7c945f7-88v56 2m 242Mi
java11016-59c7c945f7-lvhps 2m 234Mi

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广