中间还有一个syncloop,所谓的syncloop又是控制器模式了,它要去watch一堆对象,也就是当前节点的pod对象,sync loop做完之后,下面内嵌了一堆的worker,pod worker就是当我的sync loop接收到pod的变更通知的时候,那么这个pod worker就会去干活,也就是去维护pod的生命周期。
kubelet要去监听apiserver去获取当前节点的pod清单,获取pod清单之后,然后获取的pod清单,每个pod都是一个一个的通知事件,然后podworker就会处理这些事件。
它会去调用cri,然后获取当前节点pod对应的容器是不是在启动的状态。如果没有启动,那么他就会去启动这些容器进程,把这个应用拉起来,它就是通过cri的接口。
cri接口传统都是通过dockershim去做的,但是随着kubernetes架构不断升级,它废弃了docker-shim这条线,它决定不再支持比较臃肿的dokcer shim,而是通过remote container interface,比如通过containerd,或者cri来支持整个运行时。
来看看pod worker的工作细节。
kubelet它本身的synloop,就是去监听pod的状态变化,这个pod的状态变化就是一个一个的pod的update,或者是add事件,接收到这些事件之后,它就会将事件存在updateoption里面,那么不同的worker,在kubelet里面有多个worker,每个worker都会从队列里面获取这些pod变更事件的清单。
然后针对每一个pod,它就会去执行sync pod的操作,sync pod里面最重要的行为就是computepodactions,也就是针对这个pod采取什么样的行为,它会去比对当前节点上面的已经在运行的容器进程,然后去判断说,如果pod是新的我就create,如果pod是已经存在的,比如说是delete事件,那么我就应该去删除,如果是一个更新事件,那么我就要去判断运行的容器进程和你当前的pod是不是匹配的,比如它的哈希值变的话,那么我就要重建,这就是computepodactions所做的事情。
它算完了之后就需要通过cri的接口,去create这些进程,或者kill这些进程。
右边还有个组件叫做pleg,它主要是pod lifecycle event的一个汇聚器,就是pod运行完之后,上面左边部分是用来管理pod的生命周期,管理完之后这些pod的状态如何上报,那么就是通过pleg组件去上报的。
它在pleg组件里面维护了一个pod cache,它本地的一个缓存,这个pleg会去定期的往container runtime里面去发一个list的操作,去获取当前节点上pod的清单,正在运行的pod清单,那么这里就会把当前所有在运行pod状态在pleg这里汇聚,由pleg 通过pod lifecycle event发回上报给apiserver,apiserver那端就知道这个node节点上面所有pod的状态了。
如果contained runtime不响应了,那么relist就会失败,relist失败,那么这些状态就上报不了,那么最终这个状态无法上报,那么kubernets就会认为你整个节点有问题。
所以runtime本身不响应,那么这个节点会变的不正常。
还有就是bug,退出容器的gc没有做好,就节点上出现了几千上万的exit container在那里,pleg再去跟runtime relist 这些container的时候,他就会去遍历所有的已经退出的容器,就会导致时间非常的长,它没有办法及时返回所有容器的清单,没有在它规定的时间内返回,那么整个pleg的操作就超时了,那么就会导致整个节点的状态发生变化。
-----------------------------------------------------------------------------------------------------------------------------
基本上看到上边的报错,我们可以确认,容器 runtime 出了问题。在有问题的节点上,通过 docker 命令尝试运行新的容器,命令会没有响应。这说明上边的报错是准确的。