编程语言
首页 > 编程语言> > Unable to allocate memory on node -1

Unable to allocate memory on node -1

作者:互联网

一直以来,自己物理机装的k8s经常会卡死,摸索了很久也不知道什么原因,之前把内核给升级了好像卡的频率会相对低点,但还是会卡,今天无意中查看一下dmesge发现有这样的提示:

Unable to allocate memory on node -1

网上一通搜索,得到如下结论:

在某些内核版本上,cgroup 的 kmem account 特性有内存泄露问题,很不幸我就是那个某些,解决方法有如下几种:

一、升级内核

二、重新编译runc

三、重新编译kubelet

四、修改虚机启动的引导项 grub 中的cgroup.memory=nokmem,让机器启动时直接禁用 cgroup的 kmem 属性

我内核已经是4.4+了,所以第一种排除,第二种我也试过了,没有效果,第4种要重新电脑,麻烦就不试了,今天就做第3种的实验

1、因为kubelet是golang写的,所以编译需要安装golang

curl -s https://mirror.go-repo.io/centos/go-repo.repo | tee /etc/yum.repos.d/go-repo.repo

yum install golang

2、下载kubelrnetes完整包

git clone https://github.com.cnpmjs.org/kubernetes/kubernetes.git
cd kubernetes
git checkout v1.16.15


3、查看 cross 镜像的版本号

[root@node02 kubernetes]# cat build/build-image/cross/VERSION
v1.13.15-1

4、拉国内的镜像,然后改名

docker pull registry.aliyuncs.com/k8sxio/kube-cross:v1.13.15-1
docker tag  registry.aliyuncs.com/k8sxio/kube-cross:v1.13.15-1 us.gcr.io/k8s-artifacts-prod/build-image/kube-cross:v1.13.15-1

5、用下面的命令进行编译,

./build/run.sh make kubelet GOFLAGS="-v -tags=nokmem" KUBE_BUILD_PLATFORMS=linux/amd64

网上的这个命令编译完kubectl get node会得到notready的状态

make BUILDTAGS="nokmem" WHAT=cmd/kubelet GOFLAGS=-v GOGCFLAGS="-N -l"

查看编译完成的

ls -l _output/dockerized/bin/linux/amd64/

6、备份旧Kubelet,将编译好的kubelet进行替换,然后重启

验证方法

kubectl run nginx-1 --image=hub.baidubce.com/cce/nginx-alpine-go:latest --port=80 --restart=Never --requests='cpu=100m,memory=100Mi' --limits="cpu=200m,memory=200Mi"
docker ps |grep nginx-1

将得到的容器id进行过滤

find /sys/fs/cgroup/memory -name "memory.kmem.slabinfo"|grep ab876d139c1b
/sys/fs/cgroup/memory/kubepods/burstable/pod4f6a6db3-b18c-4094-86b2-e9cd7abce849/ab876d139c1b3609e6b347274dc2bbfdb021a6e008457b2c7fc69f158320689a/memory.kmem.slabinfo

直接查看这一串信息

cat /sys/fs/cgroup/memory/kubepods/burstable/pod4f6a6db3-b18c-4094-86b2-e9cd7abce849/ab876d139c1b3609e6b347274dc2bbfdb021a6e008457b2c7fc69f158320689a/memory.kmem.slabinfo

如果出现报错,提示没有信息则表示关闭成功,如果出现一堆详细信息说明不成功,我这边出现一堆信息,说明关闭kubelet的kmen accout还没有效果,我决定再做关闭runc的实验

关闭runc的kmem account

1、查看commit

[root@node01 kubepods]# runc --version
runc version 1.0.0-rc93
commit: 12644e614e25b05da6fd08a38ffa0cfe1903fdec
spec: 1.0.2-dev
go: go1.15.11
libseccomp: 2.3.3

根据commit跳转链接

https://github.com/opencontainers/runc/commit/12644e614e25b05da6fd08a38ffa0cfe1903fde 

根据链接找到了是这个tag

https://github.com/opencontainers/runc/tree/v1.0.0-rc93


2、下载源码

git clone https://github.com/opencontainers/runc.git
cd runc
git checkout v1.0.0-rc93

3、构建镜像,直接make shell会报错,因为我这边的git一次不稳定,我试了好几次才成功

由先前make shell得到的镜像名是

runc_dev:HEAD

构建一下

docker build  -t runc_dev:HEAD .

4、运行容器进行编译

docker run -ti --privileged --rm -v $PWD:/go/src/github.com/opencontainers/runc runc_dev:HEAD bash


make BUILDTAGS="seccomp selinux apparmor nokmem" static

5、编译完后退出容器,在当前目录生成runc文件,添加可执行权限后拷贝到/usr/bin/runc

chmod +x runc

6、验证是否重新编译成功,运行以下命令

docker run --rm --name test --kernel-memory 100M nginx:1.14.2
docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: process_linux.go:495: container init caused: process_linux.go:458: setting cgroup config for procHooks process caused: kernel memory accounting disabled in this runc build: unknown.
提示disable说明重新编译成功

参考文章:https://zhangguanzhang.github.io/2021/04/08/kubelet-runc-disable-kmem/ 

参考文章:https://cloud.tencent.com/developer/article/1739289

标签:node,--,编译,runc,Unable,allocate,memory,go,com
来源: https://blog.51cto.com/riverxyz/2743580