k8s故障排查一

问题一:报错 cannot allocate memory 或者 no space left on device ,修复K8S内存泄露问题
问题描述
一. 当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> : tunables : slabdata <active_slabs> <num_slabs>

解决方案
一. 解决方法思路:关闭 runc 和 kubelet 的 kmem,因为升级内核的方案改动较大,此处不采用。

二. kmem导致内存泄露的原因:

内核对于每个 cgroup 子系统的的条目数是有限制的,限制的大小定义在 kernel/cgroup.c #L139,当正常在 cgroup 创建一个 group 的目录时,条目数就加1。我们遇到的情况就是因为开启了 kmem accounting 功能,虽然 cgroup 的目录删除了,但是条目没有回收。这样后面就无法创建65535个 cgroup 了。也就是说,在当前内核版本下,开启了 kmem accounting 功能,会导致 memory cgroup 的条目泄漏无法回收。

具体实现
一. 需要重新编译 runc

配置go语言环境
wget https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz
tar xf go1.12.9.linux-amd64.tar.gz -C /usr/local/

写入bashrc
vim ~/.bashrc
export GOPATH="/data/Documents"
export GOROOT="/usr/local/go"
export PATH=“ G O R O O T / b i n : GOROOT/bin: GOROOT/bin:GOPATH/bin:$PATH”
export GO111MODULE=off

验证
source ~/.bashrc
go env
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

下载kubernetes源码
mkdir -p /root/k8s/
cd /root/k8s/
git clone https://github.com/kubernetes/kubernetes
cd kubernetes/
git checkout v1.15.3
2. 制作编译环境的镜像(Dockerfile如下)
FROM centos:centos7.3.1611

ENV GOROOT /usr/local/go
ENV GOPATH /usr/local/gopath
ENV PATH /usr/local/go/bin:$PATH

RUN yum install rpm-build which where rsync gcc gcc-c++ automake autoconf libtool make -y
&& curl -L https://studygolang.com/dl/golang/go1.12.9.linux-amd64.tar.gz | tar zxvf - -C /usr/local

  1. 在制作好的go环境镜像中来进行编译kubelet
    docker run -it --rm -v /root/k8s/kubernetes:/usr/local/gopath/src/k8s.io/kubernetes build-k8s:centos-7.3-go-1.12.9-k8s-1.15.3 bash
    cd /usr/local/gopath/src/k8s.io/kubernetes
    #编译
    GO111MODULE=off KUBE_GIT_TREE_STATE=clean KUBE_GIT_VERSION=v1.15.3 make kubelet GOFLAGS="-tags=nokmem"

三. 替换原有的 runc 和 kubelet

1 将原有 runc 和 kubelet 备份
mv /usr/bin/kubelet /home/kubelet
mv /usr/bin/docker-runc /home/docker-runc

  1. 停止 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/docker-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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值