更新容器镜像的时候,经常遇到遇到pod一直卡住在containerCreating状态,检查该pod的事件信息,
显示pod一直在pulling镜像,即pod的创建阻塞在拉取镜像到节点的过程中。
出现上述问题的pod,在uat测试环境和prod生产环境2个集群都有出现。
检查pod有关事件,发现该pod从调度成功到报错ErrImagePull,中间有2个多小时,且事件显示**Failed to pull image xxx,pull QPS exceed**
分析pull QPS exceed代码,判断kubelet默认串行拉取镜像的(现在的默认策略),
串行也会走到 pull QPS exceeded 这个报错,也就是只有可能有其它镜像拉取的时候卡住了,才导致这么慢的。
即kubelet拉取镜像是串行的,上一个拉取任务未结束不会继续下一个,目前怀疑如下可能:
1、拉取镜像慢,即可能网络带宽很慢,造成长时间阻塞。2、有任务阻塞了拉取队列,造成新建的pod的拉取任务阻塞在队列。3、containerd自身卡在了拉取状态而阻塞队列,即pod的镜像拉取任务其实已经开始运行,但是未知原因,造成拉取阻塞。
重启containerd 后,队列后的请求马上就全部失败清空了
解决办法
总结调查过程,故障原因为上游镜像仓库异常,结合kubelet默认串行拉取镜像的策略综合导致。且kubelet拉取任务是同步任务,即拉取任务会一直等待镜像仓库返回,否则会一直阻塞在队列上。在上游镜像仓库异常无返回时,会造成镜像拉取的阻塞(客户使用了2个镜像源地址,一个异常的镜像源地址阻塞了kubelet的镜像拉取队列,造成正常的镜像源地址的镜像也无法pull了)。解决办法是优先保证上游镜像仓库的稳定,第二是修改kublet拉取策略为并行缓解。并行只是缓解了在使用了多个上游镜像仓库源时,一个镜像仓库源异常不会造成拉取其他镜像仓库源阻塞。在pod全部使用一个镜像仓库源且该源异常时,并行拉取反而会额外增加系统负载。
修改kubelet拉取镜像为并行方式
编辑kubelet配置文件,增加serializeImagePulls: false配置
参考:https://mp.weixin.qq.com/s/XZ7lCNNNGmkxek41sMS6IA