【kubernetes】K8S节点状态的维护

news/2025/1/16 14:46:52/

1 节点状态

节点是K8S集群中的一类重要资源,节点的状态通常可以作为判断集群异常的重要手段。

为了展示节点在各方面的健康程度,在kubectl describe node k8s-master的输出结果中的Conditions部分可以查看k8s-master节点的一些状态数据:

  • NetworkUnavailable:网络配置是否正常
  • MemoryPressure:是否还有可用内存
  • DiskPressure:是否还有可用磁盘
  • PIDPressure:节点上是否有太多的进程
  • Ready:节点是否健康

每种类型用5个字段描述:

  • Status:状态,通常有三种状态:True、False、Unknown
  • LastHeartbeatTime:上一次心跳事件,也就是上次上报该状态信息的时间
  • LastTransitionTime:上一次状态转换的时间
  • Reason:处于当前状态的原因
  • Message:状态描述

NetworkUnavailable状态不是实时的,而是相关的网络插件启动后上报一次,表示网络插件正常启动,但是也无法表明当前的网络是否是正常的,而且,插件运行过程中也没办法知道当前网络是否正常,因此,NetworkUnavailabel只是表明插件成功启动过,无法知道当前的网络是否真的良好。

MemoryPerssure、DiskPressure、PIDPressure都可以通过采集当前节点的数据得到:

  • MemoryPerssure:采集当前节点的内存信息,
  • DiskPressure:采集当前节点的磁盘信息,
  • PIDPressure:采集当前节点的进程信息,

这三个状态值都是由kubelet定时向apiserver上报状态而来,而kube-controller-manager会判断一段时间未上报的情况。

kubectl get node展示的状态即为Conditions中的Ready,该状态由多个条件综合计算而来。

上述状态更新的流程:

  • kubelet会每隔一段时间(kubelet的–node-status-update-frequency参数,默认为10秒)更新节点状态到apiserver
  • NodeController每隔一段时间(kube-controller-manager的–node-monitor-period参数,默认为5秒)检查一次节点状态
  • 如果kubelet超过一段时间(kube-controller-manager的–node-monitor-grace-period参数,默认为50秒)未向apiserver上报,NodeController将节点状态标记为Unknown

2 Kubelet

kubelet在启动时会先上报一次节点状态。

  • fastNodeStatusUpdate(pkg/kubelet/kubelet_node_status.go)
    • originalNode, err := kl.GetNode() 获取当前节点的信息
    • readyIdx, originalNodeReady := nodeutil.GetNodeCondition(&originalNode.Status, v1.NodeReady) 获取当前节点的Condition中的NodeReady,如果为True,则直接返回
    • node, changed := kl.updateNode(ctx, originalNode) 更新当前节点的信息,并返回新的节点信息以及节点信息是否变化的状态,如果节点状态没有变化,则直接返回
    • readyIdx, nodeReady := nodeutil.GetNodeCondition(&node.Status, v1.NodeReady) 获取当前节点的最新信息中的NodeReady状态,如果为False,则直接返回
    • kl.patchNodeStatus(originalNode, node) 此时节点状态发生了由NotReady向Ready的变化
      • nodeutil.PatchNodeStatus 向apiserver上报节点Ready(毕竟节点没办法自己上报NotReady)
    • kl.syncNodeStatus() 如果上面向apiserver上报节点Ready失败了,则调用syncNodeStatus()
      • kl.registerWithAPIServer() 向apiserver注册节点,如果已经注册过了则直接返回
      • kl.updateNodeStatus(ctx) 更新节点状态
        • kl.tryUpdateNodeStatus(ctx, i)
          • util.FromApiserverCache(&opts) 将GET操作的选项中的ResourceVersion设置为0
          • originalNode, err := kl.heartbeatClient.CoreV1().Nodes().Get(ctx, string(kl.nodeName), opts) 调用apiserver接口获取节点信息,为了减少apiserver访问etcd带来的性能影响,这里调用时apiserver会从缓存中获取,而不是读取etcd
          • updatedNode, err := kl.patchNodeStatus(originalNode, node) 如果检测出apiserver返回的节点信息和当前获取到的节点信息有变化,或者距离上次节点信息上报超过--node-status-update-frequency参数,则向apiserver更新节点状态

kubelet启动时为了尽可能快地将节点状态上报给apiserver,每隔100毫秒执行一次fastNodeStatusUpdate函数,有两种情况结束执行:

  • 成功地将Ready状态上报给apiserver
  • 启动后超过2分钟状态还未更新

在kubelet启动后,会每隔--node-status-update-frequency时间上报一次:

// pkg/kubelet/kubelet.go
// func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate)
go wait.JitterUntil(kl.syncNodeStatus, kl.nodeStatusUpdateFrequency, 0.04, true, wait.NeverStop)

3 NodeLifecycleController

节点控制器在K8S中是NodeLifecycleController(节点生命周期控制器)。

kube-controller-manager在创建NodeLifecycleController时会传递三个参数:

  • NodeMonitorPeriod:检查节点状态的周期
  • NodeStartupGracePeriod:节点启动的缓冲期,当节点创建或者节点重启时会预留一段时间
  • NodeMonitorGracePeriod:检查节点状态的缓冲期

NodeLifecycleController在启动时会创建一个定时任务的协程:

// pkg/controller/nodelifecycle/node_lifecycle_controller.go
// func (nc *Controller) Run(ctx context.Context)
go wait.UntilWithContext(ctx, func(ctx context.Context) {if err := nc.monitorNodeHealth(ctx); err != nil {logger.Error(err, "Error monitoring node health")}}, nc.nodeMonitorPeriod)

monitorNodeHealth的调用流程如下:

  • monitorNodeHealth
    • nodes, err := nc.nodeLister.List(labels.Everything()) 获取所有的节点
    • added, deleted, newZoneRepresentatives := nc.classifyNodes(nodes) 将节点分为三类:新增的、删除的、no zone states?
    • 分别对上述的三种类别的节点进行处理
    • workqueue.ParallelizeUntil(ctx, nc.nodeUpdateWorkerSize, len(nodes), updateNodeFunc) 并发执行updateNodeFunc函数,updateNodeFunc的调用流程如下:
      • node := nodes[piece].DeepCopy() 函数的参数是个索引piece,然后从获取到的所有节点中根据索引piece取出节点
      • _, observedReadyCondition, currentReadyCondition, err = nc.tryUpdateNodeHealth(ctx, node) 尝试更新节点的健康状态
        • _, currentReadyCondition := controllerutil.GetNodeCondition(&node.Status, v1.NodeReady) 获取节点的Condition中的NodeReady
        • 如果当前节点的的ReadyCondition为空,说明kubelet从未上报过节点状态,则将gracePeriod设置为NodeStartupGracePeriod,否则将gracePeriod设置为NodeMonitorGracePeriod
        • observedLease, _ := nc.leaseLister.Leases(v1.NamespaceNodeLease).Get(node.Name) 获取节点的lease
        • 如果距离上次探测时间超过gracePeriod,说明节点状态更新已经超过缓冲期,则执行以下逻辑:
          • 遍历所有的Condition类型(此处不考虑NodeNetworkUnavailable)
          • 如果没有某个类型的Condition,则将Condition中的Reason设置为NodeStatusNeverUpdated
          • 如果存在某个类型的Condition,则将Condition中的Reason设置为NodeStatusUnknown
          • 如果Condition发生变化,则调用nc.kubeClient.CoreV1().Nodes().UpdateStatus(ctx, node, metav1.UpdateOptions{})更新Node的Status

4 总结

kubelet和kube-controller-manager更新Conditions的流程与前面说的基本一致:

  • kubelet会每隔一段时间(kubelet的–node-status-update-frequency参数,默认为10秒)更新节点状态到apiserver
  • NodeController每隔一段时间(kube-controller-manager的–node-monitor-period参数,默认为5秒)检查一次节点状态
  • 如果kubelet超过一段时间(kube-controller-manager的–node-monitor-grace-period参数,默认为50秒)未向apiserver上报,NodeController将节点的Condition中的Ready状态修改为False

http://www.ppmy.cn/news/1563633.html

相关文章

【Linux】8.Linux基础开发工具使用(2)

文章目录 1. Linux编译器-gcc/g使用关于sudo1.1 背景知识1.2 gcc如何完成1.2.1 预处理(进行宏替换)1.2.2 编译&#xff08;生成汇编&#xff09;1.2.3 汇编&#xff08;生成机器可识别代码&#xff09;1.2.4 连接&#xff08;生成可执行文件或库文件&#xff09;1.2.5 总结 1.3…

OmniAudio-2.6B 简介与音频转文本实践

OmniAudio-2.6B 是一个基于 Transformer 的先进语音识别模型&#xff0c;具有强大的音频转文本能力。它利用大规模预训练和多语言支持&#xff0c;为离线和在线语音处理提供高精度的解决方案。 一、OmniAudio-2.6B 的原理 1. 核心技术 Transformer 架构&#xff1a;OmniAudio…

极客说|Azure AI Agent Service 结合 AutoGen/Semantic Kernel 构建多智能体解决⽅案

作者&#xff1a;卢建晖 - 微软高级云技术布道师 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

ParcelFileDescriptor+PdfRenderer在Android渲染显示PDF文件

ParcelFileDescriptor 是一个非常重要的类&#xff0c;用于表示一个文件描述符&#xff08;File Descriptor&#xff0c;简称 FD&#xff09;&#xff0c;它可以让文件或数据通过进程间通信&#xff08;IPC&#xff09;进行共享。 1. 基本概念 ParcelFileDescriptor 是 andro…

【行空板K10】上传温湿度信息到EasyIoT平台

目录 引言 EasyIoT平台 程序编写 测试结果 结语 引言 今天测试一下使用行空板K10上传数据到EasyIoT平台。这个平台是DFRobot自由的物联网云平台&#xff0c;也是Mind支持的4个MQTT平台之一。 EasyIoT平台 EasyIoT平台的优点是非常简单&#xff0c;没有阿里云、华为云那…

蓝桥杯刷题第二天——背包问题

题目描述 有N件物品和一个容量是V的背包。每件物品只能使用一次。第i件物品的体积是Vi价值是Wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整数&#xff0c;N&#xff0c;V&am…

《分布式光纤传感:架设于桥梁监测领域的 “智慧光网” 》

桥梁作为交通基础设施的重要组成部分&#xff0c;其结构健康状况直接关系到交通运输的安全和畅通。随着桥梁建设规模的不断扩大和服役年限的增长&#xff0c;桥梁结构的安全隐患日益凸显&#xff0c;传统的监测方法已难以满足对桥梁结构健康实时、全面、准确监测的需求。分布式…

开始使用Panuon开源界面库环境配置并手写VS2019高仿界面

1. Panuon环境配置 1.1. 通过Nuget 安装 Panuon.WPF.UI1.2. xaml引用命名空间1.3. using Panuon.WPF.UI; 2. VS2019 view 2.1. 设置窗体尺寸和title2.2. 添加静态资源 2.2.1. 什么是静态资源 2.3. 主Grid 2.3.1. 盒子模型2.3.2. 嵌套布局 3. 总结 1. Panuon环境配置 1.1. 通…