K8S线上集群排查,实测排查Node节点NotReady异常状态

一,文章简述

你们好,本篇是我的的第 2 篇文章。是关于在以前项目中,k8s 线上集群中 Node 节点状态变成 NotReady 状态,致使整个 Node 节点中容器中止服务后的问题排查。node

文章中所描述的是本人在项目中线上环境实际解决的,那除了如何解决该问题,更重要的是如何去排查这个问题的原由。git

关于 Node 节点不可用的 NotReady 状态,当时也是花了挺久的时间去排查的。github

二,Pod 状态

在分析 NotReady 状态以前,咱们首先须要了解在 k8s 中 Pod 的状态都有哪些。而且每一个状态都表示什么含义,不一样状态是很直观的显示出当前 Pod 所处的建立信息。docker

为了不你们对 Node 和 Pod 的概念混淆,先简单描述下二者之间的关系(引用一张 K8S 官方图)。缓存

从图中很直观的显示出最外面就是 Node 节点,而一个 Node 节点中是能够运行多个 Pod 容器,再深刻一层就是每一个 Pod 容器能够运行多个实例 App 容器。服务器

所以关于本篇文章所阐述的 Node 节点不可用,就会直接致使 Node 节点中全部的容器不可用。网络

毫无疑问,Node 节点是否健康,直接影响该节点下全部的实例容器的健康状态,直至影响整个 K8S 集群。app

那么如何解决并排查 Node 节点的健康状态?不急,咱们先来聊聊关于关于 Pod 的生命周期状态。oop

  • Pending:该阶段表示已经被 Kubernetes 所接受,可是容器尚未被建立,正在被 kube 进行资源调度。
  • 1:图中数字 1 是表示在被 kube 资源调度成功后,开始进行容器的建立,可是在这个阶段是会出现容器建立失败的现象
  • Waiting或ContainerCreating:这两个缘由就在于容器建立过程当中镜像拉取失败,或者网络错误容器的状态就会发生转变。
  • Running:该阶段表示容器已经正常运行。
  • Failed:Pod 中的容器是以非 0 状态(非正常)状态退出的。
  • 2:阶段 2 可能出现的状态为CrashLoopBackOff,表示容器正常启动可是存在异常退出。
  • Succeeded:Pod 容器成功终止,而且不会再在重启。

上面的状态只是 Pod 生命周期中比较常见的状态,还有一些状态没有列举出来。post

这。。。状态有点多。休息 3 秒钟

不过话又说回来,Pod 的状态和 Node 状态是一回事吗?嗯。。。其实并不彻底是一回事。

可是当容器服务不可用时,首先经过 Pod 的状态去排查是很是重要的。那么问题来了,若是 Node 节点服务不可用,Pod 还能访问吗?

答案是:不能

所以排查Pod的健康状态的意义就在于,是什么缘由会致使Node节点服务不可用,所以这是一项很是重要的排查指标。

三,业务回顾

因为本人的工做是和物联网相关的,暂且咱们假设 4 台服务器(假设不考虑服务器自己性能问题,若是是这个缘由那最好是升级服务器),其中一台作 K8S-Master 搭建,另外 3 台机器作 Worker 工做节点。

每一个 worker 就是一个 Node 节点,如今须要在 Node 节点上去启动镜像,一切正常 Node 就是ready状态。

可是过了一段时间后,就成这样了

这就是咱们要说的 Node 节点变成 NotReady 状态。

四,问题刨析

这跑着跑着就变成 NotReady 了,啥是 NotReady?

这都运行一段时间了,你告诉我还没准备好?

好吧,那就看看为何还没准备好。

4.1 问题分析

再回到咱们前面说到问题,就是 Node 节点变成 NotReady 状态后,Pod 容器是否还成正常运行。

图中用红框标示的就是在节点edgenode上,此时 Pod 状态已经显示为Terminating,表示 Pod 已经终止服务。

接下来咱们就分析下 Node 节点为何不可用。

(1)首先从服务器物理环境排查,使用命令df -m查看磁盘的使用状况

或者直接使用命令free查看

磁盘并无溢出,也就是说物理空间足够。

(2)接着咱们再查看下 CPU 的使用率,命令为:top -c (大写P可倒序)

CPU 的使用率也是在范围内,不论是在物理磁盘空间仍是 CPU 性能,都没有什么异常。那 Node 节点怎么就不可用了呢?并且服务器也是正常运行中。

这彷佛就有点为难了,这可咋整?

(3)不慌,还有一项能够做为排查的依据,那就是使用 kube 命令 describe 命令查看 Node 节点的详细日志。完整命令为:

kubectl describe node <节点名称>,那么图中 Node 节点如图:

哎呀,好像在这个日志里面看到了一些信息描述,首先咱们先看第一句:Kubelet stoped posting node status,大体的意思是 Kubelet 中止发送 node 状态了,再接着Kubelet never posted node status意思为再也收不到 node 状态了。

查看下 Kubelet 是否在正常运行,是使用命令:systemctl status kubelet,若是状态为 Failed,那么是须要重启下的。但若是是正常运行,请继续向下看。

分析一下好像有点眉目了,Kubelet 为何要发送 node 节点的状态呢?这就抛出了关于 Pod 的另外一个知识点,请耐心向下看。

五,Pod 健康检测 PLEG

根据咱们最后面分析的情形,彷佛是 node 状态再也没有收到上报,致使 node 节点不可用,这就引伸出关于 Pod 的生命健康周期。

PLEG全称为:Pod Lifecycle Event Generator:Pod 生命周期事件生成器。

简单理解就是根据 Pod 事件级别来调整容器运行时的状态,并将其写入 Pod 缓存中,来保持 Pod 的最新状态。

在上述图中,看出是 Kubelet 在检测 Pod 的健康状态。Kubelet 是每一个节点上的一个守护进程,Kubelet 会按期去检测 Pod 的健康信息,先看一张官方图。

PLEG去检测运行容器的状态,而 kubelet 是经过轮询机制去检测的。

分析到这里,彷佛有点方向了,致使 Node 节点变成 NotReady 状态是和 Pod 的健康状态检测有关系,正是由于超过默认时间了,K8S 集群将 Node 节点中止服务了。

那为何会没有收到健康状态上报呢?咱们先查看下在 K8S 中默认检测的时间是多少。

在集群服务器是上,进入目录:/etc/kubernetes/manifests/kube-controller-manager.yaml,查看参数:

–node-monitor-grace-period=40s(node驱逐时间)

–node-monitor-period=5s(轮询间隔时间)

上面两项参数表示每隔 5 秒 kubelet 去检测 Pod 的健康状态,若是在 40 秒后依然没有检测到 Pod 的健康状态便将其置为 NotReady 状态,5 分钟后就将节点下全部的 Pod 进行驱逐。

官方文档中对 Pod 驱逐策略进行了简单的描述,https://kubernetes.io/zh/docs/concepts/scheduling-eviction/eviction-policy/

kubelet 轮询检测 Pod 的状态实际上是一种很消耗性能的操做,尤为随着 Pod 容器的数量增长,对性能是一种严重的消耗。

在 GitHub 上的一位小哥对此也表示有本身的见解,原文连接为:

https://github.com/fabric8io/kansible/blob/master/vendor/k8s.io/kubernetes/docs/proposals/pod-lifecycle-event-generator.md

到这里咱们分析的也差很少了,获得的结论为:

  • Pod 数量的增长致使 Kubelet 轮询对服务器的压力增大,CPU 资源紧张

  • Kubelet 轮询去检测 Pod 的状态,就势必受网络的影响

  • Node 节点物理硬件资源限制,没法承载较多的容器

而因为本人当时硬件的限制,及网络环境较差的前提下,因此只改了上面了两项参数配置,延长 Kubelet 去轮询检测 Pod 的健康状态。实际效果也确实获得了改善。

// 须要重启docker
sudo systemctl restart docker

// 须要重启kubelet
sudo systemctl restart kubelet

可是若是条件容许的状况下,我的建议最好是从硬件方面优化。

  • 提升 Node 节点的物理资源
  • 优化 K8S 网络环境

六,K8S 经常使用命令

最后分享一些经常使用的 K8S 命令

1,查询所有 pod(命名空间)

kubectl get pods -n

2,查询所有 node 节点

kubectl get nodes

3,查看 pod 详细信息和日志

kubectl describe pod -n

kubectl logs -f -n

4,查看 pod-yaml 文件

kubectl get pod -n -o yaml

5,经过标签查询 pod

kubectl get pod -l app= -n

6,查询 pod 具体某一条信息

kubectl -n get pods|grep |awk '{print $3}'

7,删除 pod(或经过标签 -l app=)

kubectl delete pod -n

8,删除 deployment

kubectl delete deployment -n

9,强制删除 pod

kubectl delete pod -n --force --grace-period=0

10,进入 pod 容器

kubectl exec -it -n -- sh

11,给 node 打标签

kubectl label node app=label

12,查看某一个 node 标签

kubectl get node -l " "

13,查看所有 node 标签

kubectl get node --show-labels=true

七,总结

关于 Node 节点的 NotReady 状态当时也是排查了好久,对不少种状况也是猜想,并不能具体肯定是什么缘由。

网上关于这方面的内容也不是不少,只能是根据提示一步一步去排查问题的源头,并加以验证,最后也是在条件限制下解决了这个问题。

之后的工做也是作 AIOT 相关的,所谓 A 是指 Ai,IOT 指物联网。也是和 K8S 强相关的内容,后续也还会继续和你们分享关于 K8S 相关的知识。

若是您也是 K8S 的使用者,或者想接触学习 K8S,欢迎关注我的公众号!

最后,求关注


总结辛苦,原创不易!但愿一些正能量的支持,求关注,点赞,转发(一键三连)

相关文章
相关标签/搜索