【kubernetes】K8S节点状态的维护

server/2025/1/17 7:32:51/

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/server/159032.html

相关文章

pycharm python pyqt5

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file UI1.ui # # Created by: PyQt5 UI code generator 5.13.0 # # WARNING! All changes made in this file will be lost! #PyCharm,从 Tools -> ExternalTools -> QtDesigner 打开 QtDesign…

【gin】模型绑定、参数验证及文件上传go案例演示

Gin 框架参数绑定与验证 在开发 Web 应用时&#xff0c;通常需要处理来自客户端的请求数据。Gin 提供了强大的 请求绑定&#xff08;Binding&#xff09; 和 参数验证&#xff08;Validation&#xff09; 功能。 1. Gin 请求数据绑定 Gin 使用 ShouldBind 和 ShouldBindJSON…

C# 多线程 Task TPL任务并行

先总结一下 之前发展过程的要点 1&#xff1a; 为了保证多线程正确顺序执行 线程同步 2&#xff1a; 为了节省操作系统线程资源 线程池 异步 方式管理 正常来讲 使用这俩个要点 进行使用 多线程可以满足开发使用需求 但是 新的问题产生了 那就是 多个异步操作 需要编写大量的代…

level(三) filterblock

filterblock用于确定某个key是否存在于某个datablock中&#xff0c;在插入一个key到datablock中时也会插入一个key到filterblock中&#xff0c;filterblock中会记录所有的key&#xff0c;并通过布隆过滤器来确定一个key是否存于这个datablock中。下面来看下filterblock的代码&a…

SQLite 3.48.0 发布,有哪些更新?

SQLite 开发团队于 2025 年 1 月 14 日发布了 SQLite 3.48.0 版本&#xff0c;我们来解读一下新版本的改进功能。 EXPLAIN QUERY PLAN SQLite 使用 EXPLAIN QUERY PLAN 命令获取查询语句的执行计划&#xff0c;新版本改进了执行计划输出结果中的覆盖索引优化信息&#xff1a;…

计算机的错误计算(二百一十三)

摘要 利用大模型计算 实验表明&#xff0c;其输出有 1位正确数字。 刚刚登录了一个新的大模型&#xff0c;之前从未使用过。本节将讨论该大模型在 IEEE 754-2019标准下函数计算的准确性。 例1. 计算 下面是与新的大模型的对话。 点评&#xff1a; &#xff08;1&#xff…

MySQL SQL优化技巧与原理

前言 随着业务数据量的不断增加&#xff0c;MySQL查询语句的执行效率对程序的运行效率影响逐渐增大。因此&#xff0c;进行SQL优化变得至关重要。本文将结合SQL的执行语句顺序和各种SQL场景&#xff0c;介绍一些常见的MySQL SQL优化技巧及其背后的原理。 一、MySQL SQL执行语…

smart_web 管理端说明

smart_web 操作手册 1. smart_web 是什么&#xff1f; smart_web 是 smart_rtmpd 的付费版本&#xff0c;拥有比免费版本更多的功能支持&#xff0c;基于 web 的管理方式&#xff0c;让您随时随地在大部分设备上都能远程对服务器进行维护管理。smart_web 带有进程守护&#x…