今天就跟大家聊聊有关k8s pod被驱逐问题分析及解决方法是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
环境说明:
异常信息:kubectl get pod
发现服务被驱逐,然后在调度到其它节点过程中出现问题,之所以出现问题是因为编排文件中添加了污点,已经标注该Pod不能被调度到其它节点。但是为什么会出现Pod被驱逐,这倒是个问题?查看/var/log/messages
中日志,发现大量镜像无法被拉取的错误,如下所示:
Nov 7 06:20:49 k8work2 kubelet: E1107 06:20:49.829886 13241 remote_image.go:113] PullImage "k8s.gcr.io/kube-proxy:v1.14.2" from image service failed: rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: dial tcp 74.125.204.82:443: connect: connection timed out
Nov 7 06:20:49 k8work2 kubelet: E1107 06:20:49.866132 13241 pod_workers.go:190] Error syncing pod 4fedf7b3-207e-11eb-90a3-2c534a095a16 ("kube-proxy-pqvvb_kube-system(4fedf7b3-207e-11eb-90a3-2c534a095a16)"), skipping: failed to "StartContainer" for "kube-proxy" with ErrImagePull: "rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: dial tcp 74.125.204.82:443: connect: connection timed out"
这段日志的意思是因为镜像无法拉取,所以启动出现启动失败问题,除此之外还有coredns、Controller
等,也出现此类镜像无法拉取问题。
出现这个问题,很容易理解,内网集群,在集群安装过程中,镜像是通过复制过来的,但是执行docker images|grep k8s
发现k8s的镜像全不在了,难道有人为删除,要不然镜像为什么会无缘无故消失呢?
于是又开始查看日志,又发现日志中存在此类信息,确认不是人为删除,而是kubelet回收掉了,具体日志如下所示:
Nov 7 05:44:51 k8work2 kubelet: I1107 05:44:51.041315 13241 image_gc_manager.go:317] attempting to delete unused images
Nov 7 05:44:51 k8work2 kubelet: I1107 05:44:51.083785 13241 image_gc_manager.go:371] [imageGCManager]: Removing image "sha256:6858809bf669cc5da7cb6af83d0fae838284d12e1be0182f92f6bd96559873e3" to free 1231725 bytes
为什么要把k8s自身运行需要的镜像回收掉呢?这里先不过多解释,具体原因,且看下文。
Nov 7 06:20:47 k8work2 kubelet: E1107 06:20:47.943073 13241 file_linux.go:61] Unable to read config path "/etc/kubernetes/manifests": path does not exist, ignoring
其实看了下网上这个问题,也挺多的,因为是计算节点,不包含manifests,但是日志中一直在提示这个错误,这种噪音日志看着就难受,我是直接在/etc/kubernetes/
创建了manifests文件夹,问题直接解决。此错误跟本文中的Pod驱逐应该没什么关系,看了看其它计算接单存在同样问题。
Nov 7 09:32:03 k8work2 kubelet: E1107 09:32:03.431224 13241 kubelet_volumes.go:154] Orphaned pod "f6a977f4-2098-11eb-90a3-2c534a095a16" found, but volume paths are still present on disk : There were a total of 1 errors similar to this. Turn up verbosity to see them.
进入到/var/lib/kubelet/pods/
,通过id号,进入kubelet的目录,可以发现里面还存在容器的数据,etc-hosts文件中还保留着pod名称等信息。
从错误信息可以推测,这台计算节点存在一个孤儿Pod,并且该Pod挂载了数据卷(volume),阻碍了Kubelet对孤儿Pod正常的回收清理。所以一直在提示上面错误信息,我在确认该Pod确认该Pod确实已经不在运行,并且没有数据丢失的风险,直接执行了rm -rf f6a977f4-2098-11eb-90a3-2c534a095a16
,删除过后,不在刷此类错误。
Nov 7 07:21:19 k8work2 kubelet: E1107 07:21:19.021705 13241 eviction_manager.go:576] eviction manager: pod es-0_log(aa41dd4c-2085-11eb-90a3-2c534a095a16) failed to evict timeout waiting to kill pod
Nov 7 07:21:22 k8work2 kubelet: I1107 07:21:22.883681 13241 image_gc_manager.go:300] [imageGCManager]: Disk usage on image filesystem is at 86% which is over the high threshold (85%). Trying to free 21849563955 bytes down to the low threshold (80%).
Nov 7 07:21:22 k8work2 kubelet: E1107 07:21:22.890923 13241 kubelet.go:1278] Image garbage collection failed multiple times in a row: failed to garbage collect required amount of images. Wanted to free 21849563955 bytes, but freed 0 bytes
日志大概提示意思是磁盘压力过大,已经超过阈值,于是df -h
查看了下磁盘,果然这台机器服务产生了大量日志,导致磁盘占用过高,但是磁盘虽然占用过高,为什么要回收镜像呢?在官网查询了下,大概是这样介绍的:
垃圾回收是
kubelet
的一个有用功能,它将清理未使用的镜像和容器。kubelet
将每分钟对容器执行一次垃圾回收,每五分钟对镜像执行一次垃圾回收。
镜像垃圾回收策略只考虑两个因素:
HighThresholdPercent
和LowThresholdPercent
。磁盘使用率超过上限阈值(HighThresholdPercent
)将触发垃圾回收。垃圾回收将删除最近最少使用的镜像,直到磁盘使用率满足下限阈值(LowThresholdPercent
)。
容器垃圾回收策略考虑三个用户定义变量。
MinAge
是容器可以被执行垃圾回收的最小生命周期。MaxPerPodContainer
是每个pod
内允许存在的死亡容器的最大数量。MaxContainers
是全部死亡容器的最大数量。可以分别独立地通过将MinAge
设置为0,以及将MaxPerPodContainer
和MaxContainers
设置为小于0来禁用这些变量。kubelet
将处理无法辨识的、已删除的以及超出前面提到的参数所设置范围的容器。最老的容器通常会先被移除。
对于k8s用户来说上述kubelet参数都是可以调整的,具体调整方式请参考:https://kubernetes.io/zh/docs/concepts/cluster-administration/kubelet-garbage-collection/
这里不在过多赘述。
说到这里大概已经找到原因,之所以出现Pod被驱逐,原因是因为磁盘压力超过阈值,在k8s看来,这个计算节点已经不正常,所以开启垃圾回收机制,按照默认回收策略首先删除了自身的镜像信息,然后导致内网镜像拉取失败问题,然后开始重新调度Pod,但是因为该Pod中添加了污点,不能被调度到其它节点,最后导致启动失败。
于是找到占用磁盘数据所在文件夹,是一个以pod PVC命名的文件,确认里面的数据可以删除之后,我直接把PVC文件夹以及内容,全部都给删掉了,再次启动Pod,一直处于init状态,event事件提示无法找到PVC,仔细看了下该Pod所在编排文件内容,发现该Pod是有状态应用,以sts进行编排,我们知道sts以特定顺序启动,并且拥有稳定网络身份标识、写入固定的存储,现在我把存储名称都给干掉了,所以导致无法启动,大家引以为戒。
但是之所以会出现上面有状态Pod无法启动的问题,究其原因是因为复用了过去的PVC,我只要把PVC、PV删除了,重新创建,一切万事大吉,于是我开始使用kubectl delete pvc pvc_name -n log
,有趣的一幕又发生了,PVC一直卡在Terminating无法删除。
网上查了查解决方式,大概两种:
直接到etcd中删除
使用kubectl patch
kubectl delete pvc pvc_name -n log
kubectl patch pvc pvc_name -p '{"metadata":{"finalizers":null}}' -n log
之所以需要强制执行,因为原生k8s不允许执行删除后的回滚动作。这大概就是k8s最终一致性原则的体现。
再次重新启动Pod,启动成功,已经重新创建PVC和PV。
通过本文可以看出两点:
当然要彻底解决此类问题,还是需要监控巡逻系统,出现磁盘告警之后能够立马通知到系统管理员或者自动做出进一步数据处理,不至于服务挂掉。如有问题,请关注公众号,加我微信,一起讨论!
看完上述内容,你们对k8s pod被驱逐问题分析及解决方法是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。