Home / PostsPost
k8s的一个节点的kubelet 报了这么一个错 GenericPLEG: Unable to retrieve pods: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (4195184 vs. 4194304)
嘟噜聪2020/12/15 13:57:27 [Docker] [Kubernetes] [k8s] [容器] [开普勒] [开普勒云平台] 5162人已阅
简介 在开普勒上发现了一个神奇的问题,一个应用只设置启了一个pod,但却显示了两个并且其中一个没有流量,一种假死的状态,删除后就没有不会重新再启一下。既然看到了,那就顺手执行了一下 `journalctl -exf` 发现了一个错误: `"GenericPLEG: Unable to retrieve pods: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (4195184 vs. 419
k8s的一个节点的kubelet 报了这么一个错 GenericPLEG: Unable to retrieve pods: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (4195184 vs. 4194304)
在开普勒上发现了一个神奇的问题,一个应用只设置启了一个pod,但却显示了两个并且其中一个没有流量,一种假死的状态,删除后就没有不会重新再启一下。
既然看到了,那就顺手执行了一下 journalctl -exf
发现了一个错误: "GenericPLEG: Unable to retrieve pods: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (4195184 vs. 4194304)"
顺手就get了一下nodes: kubectl get nodes
,发现有一个节点挂掉了。
先说解决方案
- 进入master节点执行命令,先把问题节点禁止被调度到
- 删除所有引起问题的的Deployment、CronJob等其他类型的资源
- 把问题节点上的pods全部清除掉,让其自动飘到其他节点
- 清理问题节点的不常使用的容器
- 重启动问题节点的 docker 和 kubelet
- 恢复问题节点的调度
# 让问题节点不被调度
$ kubectl cordon k8s-node-02
# 驱逐问题节点上所有的pod,此步可能会卡住 通常情况下还需要单独手动删除,因为此时kubelet已经废了... 做不到没关系进入下一步
$ kubectl drain kpl-k8s-node-02 --ignore-daemonsets --delete-local-data --force
# 进入问题节点
$ ssh k8s-node-02
# 查看节点容器占用,确认没啥大问题
$ docker system df
# 清理不常使用的容器,或是一些没用的
$ docker system prune
# 进入 /var/lib/containers 目录查看是否都清理完
$ ls /var/lib/containers
# 重启Docker及Kueblet
$ systemctl restart docker && systemctl restart kubelet
# 查看是否还有其他报错
$ journalctl -exfu kubelet
# 回到master节点并放开问题节点的调度
$ ssh k8s-master-01
$ kubectl uncordon k8s-node-02
执行完上面操作后,问题解决。
我们这目前生产的版本是 Kubernetes v1.10.x
是存在该问题的: https://github.com/kubernetes/kubernetes/issues/63858
在github上有这个Issue。该问题应该是在 v1.12.7
之后的版本修复了。
为什么会产生这个错误
Dec 14 09:55:55 kpl-k8s-node-02 kubelet[19456]: E1214 09:55:55.210671 19456 generic.go:197] GenericPLEG: Unable to retrieve pods: rpc error: code = ResourceExhausted desc = grpc: received message larger than max (4195184 vs. 4194304)
这次的问题跟上次一样,也是意外之中发现的,然后又偷偷解决掉了。上篇是处理ETCD的问题: 处理一次k8s、无法获取podIP的心路历程,这次遇到问题就淡定多了,至少不是整集群的问题。
这又是一个不能靠重启解决的问题...差评...
从kubelet报的错误来看应该是kubelet与cri-o的通信超过了grpc的最大限制。但为什么会有这么多的数据呢?我们pods数量应该没多少呀。
试着查看一下集群所有的pods状态
$ kubectl get pods --all-namespaces -o wide
似乎有点慢,查出来的结果居然是有上万个pod,并且绝大部分的pod都是失败的。
顺着这个方向继续查。最终确认是因为CronJob创建的pod因连接问题失败了,而CronJob所设置的规则是失败会重新尝试启动,如此循环下去CronJob会无限制的创新pod,那些这pod一直失败,占用资源。
既然问题已找到,那就开始解决问题。
- 在能查看到失败pod的日志情况下先查一下,保留现场,这很重要,方便查为什么这个任务会失败
- 保留CronJob的yaml,做一个备份
- 尝试删除对应用CronJob的副本
- 如果依然还在调度任务,尝试删除对应的CronJob
处理好不再产生新的垃圾pod之后,来处理一下遗留的问题。
按上开头所说的步骤以此执行。
把问题节点设置为不被调度之后,将该问题节点上的pod全部驱逐出去,并做好重启服务器的最坏打算。 因为产生的巨量的pod,该节点上的kubelet已经无法正常工作了,也别指望能让kubelet来清理掉无用容器。就算是手动重启动了docker 及kubelet,问题依然会存在。
进入到容器目录后可以看到该目录有巨量的目录,目测(・_・;有超过过1万多个目录,一个目录下最多可以放下65536个目录,应该是没超过这个限制的。
千万别急着使用rm -rf *
,咱们应该按正常流程来走。
使用以下Docker命令,查看Docker空间使用量:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 1843 96 93.31GB 87.74GB (94%)
Containers 291 268 715.6MB 5.662MB (0%)
Local Volumes 5 4 135.8MB 67.89MB (50%)
Build Cache 0B 0B
再执行清理命令:
$ docker system prune
稍等片刻之后会完成。再查看目录只剩下几个必须的目录了,我这里只留下了filebeat、calico-node的容器。
清理完成之后,把Docker及kubelet都重启一下:
$ systemctl restart docker && systemctl restart kubelet
尾巴
通过又一次偷偷化解的危机,我们应该好好思考一下,到底是因为监控不够多,还是使用的姿势不对?监控应该要多细致才也避免各种各样的神奇问题?
还是那句话: "没事上去点点,说不定会有您意想不到的惊喜(惊吓)。(苦笑)"
谢谢
很赞哦! (18)
下一篇:信用卡管理系统-小程序版