問題描述
一. 當k8s集群運行日久以后,有的node無法再新建pod,並且出現如下錯誤,當重啟服務器之后,才可以恢復正常使用。查看pod狀態的時候會出現以下報錯。
applying cgroup … caused: mkdir …no space left on device 或者在describe pod的時候出現cannot allocate memory
這時候你的 k8s 集群可能就存在內存泄露的問題了,當創建的pod越多的時候內存會泄露的越多,越快。
二. 具體查看是否存在內存泄露
cat /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo 當出現cat: /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo: Input/output error則說明不存在內存泄露的情況 如果存在內存泄露會出現 slabinfo - version: 2.1 # name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
解決方案
一. 解決方法思路:關閉 runc 和 kubelet 的 kmem,因為升級內核的方案改動較大,此處不采用。
二. kmem導致內存泄露的原因:
內核對於每個 cgroup 子系統的的條目數是有限制的,限制的大小定義在 kernel/cgroup.c #L139,當正常在 cgroup 創建一個 group 的目錄時,條目數就加1。我們遇到的情況就是因為開啟了 kmem accounting 功能,雖然 cgroup 的目錄刪除了,但是條目沒有回收。這樣后面就無法創建65535個 cgroup 了。也就是說,在當前內核版本下,開啟了 kmem accounting 功能,會導致 memory cgroup 的條目泄漏無法回收。
具體實現
一. 需要重新編譯 runc
1. 需要配置go語言環境
2. 下載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
3. 編譯
安裝編譯組件 sudo yum install libseccomp-devel make BUILDTAGS='seccomp nokmem' 編譯完成之后會在當前目錄下看到一個runc的可執行文件,等kubelet編譯完成之后會將其替換
二. 編譯kubelet
1.下載kubernetes源碼
cd /root/go/src/github.com/ git clone https://github.com/kubernetes/kubernetes cd kubernetes/ git checkout v1.18.6
2. 編譯kubelet
GO111MODULE=on KUBE_GIT_TREE_STATE=clean KUBE_GIT_VERSION=v1.18.6 make kubelet GOFLAGS="-tags=nokmem"
生成的kubelet二進制文件在生成的_output路徑下。
三. 替換原有的 runc 和 kubelet
1、將原有 runc 和 kubelet 備份
mv /usr/bin/kubelet /home/kubelet mv /usr/bin/runc /home/runc
2. 停止 docker 和 kubelet
systemctl stop docker systemctl stop kubelet
3. 將編譯好的runc和kubelet進行替換
cp kubelet /usr/bin/kubelet cp kubelet /usr/local/bin/kubelet cp runc /usr/bin/runc
4. 檢查kmem是否關閉前需要將此節點的pod殺掉重啟或者重啟服務器,當結果為0時成功
cat /sys/fs/cgroup/memory/kubepods/burstable/memory.kmem.usage_in_bytes
5. 是否還存在內存泄露的情況
cat /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo
6.經測試需要重啟服務器后內存泄漏問題才能解決
參考:https://zhuanlan.zhihu.com/p/343031257
參考:https://zhuanlan.zhihu.com/p/106757502
參考:https://blog.csdn.net/qq_33317586/article/details/109285758 (推薦)
