概述
本来面临双十二这一天,线上出问题就会很紧张,本想今天应该没啥大问题,但很不巧,在11号晚上7点50时候,收到了k8s的events报警。
看到这个报警,赶紧看下服务,发现服务目前正常,但有一个正发布的服务,销毁不了老的pod,我怀疑node节点可能是不可用了。果不其然,在控制节点上查看node状态,为not ready。
检查
报的内核报警,但是其实不应该导致node节点不可用,故赶紧深究一下,先将node节点打上污点,不可调度。
当集群节点进入NotReady状态的时候,我们需要做的第一件事情,肯定是检查运行在节点上的kubelet是否正常。在这个问题出现的时候,使用systemctl命令查看kubelet状态,发现它作为systemd管理的一个daemon,是运行正常的。当我们用journalctl查看kubelet日志的时候,发现下边的错误。
1 | Dec 11 19:38:45 ali-worker-k8s-001 kubelet[20140]: E1211 19:38:45.239546 20140 kubelet.go:1551] error killing pod: failed to "KillPodSandbox" for "31321cfc |
order-oms-64544b9c65-4lq5d_sec-mall 这个pod杀不掉,导致了docker死锁,所以判断是containerd的问题
问了下阿里的大佬
1 | shim其实扮演父进程,回收容器里进程的角色,跟systemd去回收系统进程一样。linux上如果systemd卡主了,就会有一堆defunct。shim老版本的同步机制,就用了一个32大小的channel,理论上超过32个进程一起退出,就会overflow |
于是我exec进入容器,果然发现进程很多,都是多于32,于是选择升级containerd解决问题
具体操作步骤如下
1 | 1、下载1.2.10 containerd |
网上看到的另一个bug是systemd的问题
什么是PLEG
这个报错很清楚的告诉我们,容器runtime是不工作的,且PLEG是不健康的。这里容器runtime指的就是docker daemon。Kubelet通过直接操作docker daemon来控制容器的生命周期。而这里的PLEG,指的是pod lifecycle event generator。PLEG是kubelet用来检查容器runtime的健康检查机制。这件事情本来可以由kubelet使用polling的方式来做。但是polling有其成本上的缺陷,所以PLEG应用而生。PLEG尝试以一种“中断”的形式,来实现对容器runtime的健康检查,虽然实际上,它同时用了polling和”中断”两种机制。
基本上看到上边的报错,我们可以确认,容器runtime出了问题。在有问题的节点上,通过docker命令尝试运行新的容器,命令会没有响应。这说明上边的报错是准确的.
容器runtime
容器runtime包括docker daemon,containerd,containerd-shim以及runC。组件containerd负责集群节点上容器的生命周期管理,并向上为docker daemon提供gRPC接口。
故也升级了下systemd。升级systemd,直接yum update systemd就可以。
其中如果遇到容器起不来网络插件的情况,可以ip link del dev cni0,会自动重启的