K8s 内存泄漏 runc、kubelet 编译方法

准备一台和生产节点相同内核版本的机器

# 安装 go 
# 下载地址: https://golang.google.cn/dl/

# 也可以直接 yum 安装,连带 git 一起安装了 下载源码时会用到
yum install golang git -y

# 安装编译工具和依赖包
yum -y install gcc gcc-c++ kernel-devel libseccomp-devel

runc 编译

有两种方法下载runc的代码

# 通过go工具下载
# runc的源码自动下载到$GOPATH/src/github.com/opencontainers/runc目录下
# go get github.com/opencontainers/runc


# 直接通过git工具克隆代码
cd $GOPATH/src/github.com/opencontainers
git clone https://github.com/opencontainers/runc


# 切换到对应的版本
cd runc
git checkout v1.0.0-rc9

# 编译 runc
# 编译完成之后会在当前目录下看到一个runc的可执行文件
# 可能需要配置 export GO111MODULE=off 参数
make BUILDTAGS='seccomp nokmem'

kubelet 编译

#下载 Kubernetes 源码
cd $GOPATH/src/github.com/opencontainers
git clone https://github.com/kubernetes/kubernetes
cd kubernetes/

# 版本还原:根据自己安装的K8S版本,将源码还原到对应的版本:
git checkout v1.20.9
#
GO111MODULE=on KUBE_GIT_TREE_STATE=clean KUBE_GIT_VERSION=v1.20.9 make kubelet GOFLAGS="-tags=nokmem"
# make编译的时候,必须要加上参数 GOFLAGS="-tags=nokmem"。这样编译的kubelet才不会开启kmem属性,也就不会导致内存泄漏。
# 生成的kubelet二进制文件在生成的_output路径下的bin当中。

替换 runc、kubelet

# 替换原有的 runc 和 kubelet
# 将原有 runc 和 kubelet 备份
mv /usr/bin/kubelet /home/kubelet
mv /usr/bin/runc /home/runc


# 停止 docker 和 kubelet
systemctl stop docker
systemctl stop kubelet



# 将编译好的runc和kubelet进行替换
cp /root/k8s/kubernetes/_output/bin/kubelet /usr/bin/kubelet
cp /root/k8s/kubernetes/_output/bin/kubelet /usr/local/bin/kubelet
cp /data/Documents/src/github.com/opencontainers/runc/runc /usr/bin/runc

检查验证

检查kmem是否关闭前需要将此节点的pod杀掉重启或者重启服务器,当结果为0时成功

# 重启服务器
reboot

# 查看结果
cat /sys/fs/cgroup/memory/kubepods/burstable/memory.kmem.usage_in_bytes
cat /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo

参考