软硬件环境
- 硬件环境:ARM64
- 软件环境
version | |
---|---|
kernel | 4.4.58-20171215.kylin.server.YUN+-generic |
docker | 17.03.2-ce-rc1 |
runc | version 1.0.0-rc10+dev |
kubernetes | 1.14.1 |
问题现象
问题首先出现是操作系统出现了只读,经过排查系统日志,发现了以下关键词:
SLUB: Unable to allocate memory on node -1
No space left on device
以上现象,据查是由于cgroup内存泄露引起的。
问题分析
什么是cgroup内存泄露呢,这要从内核的kernel memory accounting机制说起。
为了防止出现“fork bomb”,社区中就有人提议通过linux内核限制cgroup中的kmem容量使用,从而限制恶意进程的行为。于是就有了kernel memory accounting机制。
kernel memory accounting机制为cgroup的内存限制增加了stack pages(例如新进程创建)、 slab pages(SLAB/SLUB分配器使用的内存)、sockets memory pressure、tcp memory pressure等。
有人会说,既然kernel memory accounting机制是为了限制cgroup中的kmem容量使用,那为什么还会出现内存无法分配的问题呢,一句话总结,就是当前的内核版本对kernel memory accounting机制的支持存在BUG。
解决方案
- 重新编译runc,关闭kmem,替换原先的runc。编译方法如下(可参照https://github.com/opencontainers/runc#build-tags):
go get github.com/opencontainers/runc
cd $GOPATH/src/github.com/opencontainers/runc
make BUILDTAGS='nokmem'
- 重新编译kubelet,关闭kmem,替换原先的kubelet。编译方法如下:
git clone https://github.com/kubernetes/kubernetes
cd kubernetes
git checkout v1.14.1
make kubelet GOFLAGS="-tags=nokmem"
- 重启机器
- 验证禁用是否生效,方法和正确结果如下:
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>
cat /sys/fs/cgroup/memory/kubepods/burstable/pod<podid>/<containerID>/memory.kmem.usage_in_bytes
0
参考资料:
- https://github.com/kubernetes/kubernetes/issues/61937
- https://tencentcloudcontainerteam.github.io/2018/12/29/cgroup-leaking/
- https://github.com/opencontainers/runc
- http://www.iceyao.com.cn/2020/01/04/%E8%AE%B0%E4%B8%80%E6%AC%A1k8s-cgroup%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/
网友评论