环境
arm ubuntu平台
- Kubernetes v1.14.6
- Etcd 3.3.12
- Docker 18.09.9
- Kernel 4.4.131
现象
现象如这个issue里面所描述的https://github.com/kubernetes/kubernetes/issues/61937 , 还有复现方法
cgroup内存泄露, 现象关键字如下
SLUB: Unable to allocate memory on node -1
No space left on device
解决方法:
- 重新编译runc、kubelet禁用kmem accounting
- 内核禁用cgroup kmem(Kernel 3.10.0-1062.4.1.el7.x86_64支持)
kernel memory accounting机制简介
为了防止出现“fork bomb”,社区中就有提议通过linux内核限制cgroup中的kmem容量使用从而限制恶意进程的行为, kernel memory accounting机制为cgroup的内存限制增加了stack pages(例如新进程创建)、 slab pages(SLAB/SLUB分配器使用的内存)、sockets memory pressure、tcp memory pressure等
重编译runc、kubelet
安装go环境
下载go
# wget -c https://dl.google.com/go/go1.13.5.linux-arm64.tar.gz
解压至/usr/local目录
# tar xf go1.13.5.linux-arm64.tar.gz -C /usr/local/
设置环境变量, 追加到~/.bashrc
# vim ~/.bashrc
export GOPATH="/data/Documents"
export GOROOT="/usr/local/go"
export PATH="$GOROOT/bin:$GOPATH/bin:$PATH"
export GO111MODULE=off
验证go环境是否有效
source ~/.bashrc
# go env
GO111MODULE="off"
GOARCH="arm64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="linux"
下载runc、kubernetes源码
下载runc源码
# mkdir -p /data/Documents/src/github.com/opencontainers/
# cd /data/Documents/src/github.com/opencontainers/
# git clone https://github.com/opencontainers/runc
# cd runc/
# git checkout v1.0.0-rc9 # 切到v1.0.0-rc9 tag
编译, seccomp选项默认都会带上
apt-get install -y libseccomp-dev pkg-config
make BUILDTAGS='seccomp nokmem'
runc可执行文件在当前目录, 更多编译选项查看README.md
查看runc版本
# ./runc -v
runc version 1.0.0-rc9
commit: d736ef14f0288d6993a1845745d6756cfc9ddd5a
spec: 1.0.1-dev
网上说升级docker-ce 到 18.09.1以上, runc默认把kmem accounting功能关闭了, 发现18.09.9版本并没有关闭
下载k8s源码
# mkdir -p /data/Documents/src/k8s.io/
# cd /data/Documents/src/k8s.io/
# git clone https://github.com/kubernetes/kubernetes
# cd kubernetes/
# git checkout v1.14.6
# GO111MODULE=off KUBE_GIT_TREE_STATE=clean KUBE_GIT_VERSION=v1.14.6 make kubelet GOFLAGS="-tags=nokmem"
编译v1.14.6版本的kubelet, 产物在当前目录_output/bin/kubelet
跨平台编译
make kubelet KUBE_BUILD_PLATFORMS=linux/arm64
验证
备份原有runc、kubelet
service kubelet stop
service docker stop
mv /usr/bin/kubelet /home/kubelet
mv /usr/bin/runc /home/runc
新版本替换
mv kubelet /usr/bin/kubelet
mv runc /usr/bin/runc
启动服务
service docker starrt
service kubelet start
不重启机器的话,需要删除原来所有的pod
查看新创建pod的cgroup memory kmem
pod uid、container id获取
kubectl get pod `kubectl get pod|grep test-hello| awk '{print $1}'` -o yaml |egrep "uid|container"
查看kmem.slabinfo
cat /sys/fs/cgroup/memory/kubepods/burstable/pod<pod-id>/<containerID>/memory.kmem.slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
没有禁用kmem的情况下, 这下面会有数值的; 禁用kmem的情况下, 在内核3.10.0-862.11.6.el7.x86_64版本下会显示Input/output error, 在内核4.4.131版本下显示的和内核3.10.0-862.11.6.el7.x86_64不一样, 它也没有数值
所以再查看kmem.usage_in_bytes, 以这个为标准
cat /sys/fs/cgroup/memory/kubepods/burstable/pod<pod-id>/<containerID>/memory.kmem.usage_in_bytes
0
显示为0, 说明有效
参考链接
- https://github.com/kubernetes/kubernetes/issues/61937
- https://tencentcloudcontainerteam.github.io/2018/12/29/cgroup-leaking/?nsukey=VOA6Ga0MWGzmiqZAw%2F8WzLptJWfcnMMDuP3F2KP3qm18ZVlcabhFQBnNpFnPc1V8tjh6kNsK%2Bjsw9l5Og35a6hbOobAkkJLfIAZ8blfi0keARy%2FGM6RZBd0wZvEtyMFtu0k7XYfyiuzECgizSxQER%2F4JerJEZkfd7RcBdNHCxdVps7IGcQQ9UyfM8oSYTlNUQD8wphVnSTxHJVG4I5e7Wg%3D%3D
- https://www.jianshu.com/p/033fe2518476
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付