2. 节点生命周期管理:节点注册、节点状态(Ready/NotReady)、节点健康检查机制

节点(Node)是 Kubernetes 集群的工作负载载体。理解节点从加入集群到被驱逐的完整生命周期,是集群运维与资源调度的基础。本节聚焦节点注册流程、状态机转换模型以及 kubelet 健康检查机制,帮助你在扩容场景下快速定位节点异常。

2.1 节点注册:从 kubelet 到 API Server

节点注册分为自注册和管理员手动创建两种方式。生产环境几乎全部采用自注册模式。

注册方式 触发条件 适用场景 风险点
自注册 kubelet 启动时,通过 --register-node(默认 true)向 API Server 发起 POST 请求 自动扩缩容、云环境、大规模集群 kubelet 证书过期、Node 对象残留
手动创建 管理员通过 kubectl create node 或 YAML 定义 Node 对象 边缘节点、离线环境、特殊硬件节点 人工配置错误、状态不同步

自注册流程包含以下关键步骤:

  1. kubelet 启动:读取节点元数据(hostname、OS、内核、容器运行时版本、资源容量)。
  2. 创建 Node 对象:kubelet 使用自身 ServiceAccount 向 API Server 提交 Node 资源。
  3. 节点准入:API Server 执行准入控制(NodeRestriction 插件限制 kubelet 只能修改自身 Node)。
  4. 状态上报:kubelet 启动周期性 NodeStatus 更新(默认 10s 一次)。
  5. Controller Manager 确认:node-controller 检查 Node 对象是否在 --node-monitor-period(默认 5s)内收到心跳。
💡 生产建议: 自注册节点必须配置 --kubelet-preferred-address-types 为 InternalIP,ExternalIP,Hostname,避免 DNS 解析失败导致节点不可达。

2.2 节点状态机:Ready / NotReady / Unknown

Kubernetes 通过一组 NodeCondition 描述节点状态,其中最核心的是 Ready 条件。节点状态机围绕 kubelet 心跳与 Controller Manager 的超时判定进行转换。

节点状态机转换图 Ready NotReady Unknown 心跳超时(node-monitor-grace-period) kubelet 恢复心跳 超过 node-startup-grace-period kubelet 重新上报 关键参数 node-monitor-period: 5s node-monitor-grace-period: 40s node-startup-grace-period: 1m0s pod-eviction-timeout: 5m0s

节点状态转换的核心判定逻辑:

  • Ready → NotReady:kubelet 在 node-monitor-grace-period(默认 40s)内未上报 NodeStatus。
  • NotReady → Unknown:节点在 node-startup-grace-period(默认 1m)内仍未恢复心跳。
  • NotReady / Unknown → Ready:kubelet 成功上报一次有效 NodeStatus,且所有条件满足。
⚠️ 关键时间线: 从节点失联到 Pod 被驱逐,默认总等待时间为 node-monitor-grace-period (40s) + pod-eviction-timeout (5m) = 5m40s。对于延迟敏感业务,应通过 --pod-eviction-timeout 或 tolerationSeconds 缩短该窗口。

2.3 节点健康检查机制

kubelet 是节点健康检查的执行者,它通过多个维度的探针汇总节点状态,并上报给 API Server。健康检查机制分为三层:

检查层级 检查项 上报字段 失败影响
运行时层 Container Runtime 响应(CRI 接口)、kubelet 自身存活 Ready 条件 节点标记 NotReady
系统层 磁盘空间(DiskPressure)、内存压力(MemoryPressure)、PID 压力(PIDPressure) NodeCondition 扩展字段 触发 Pod 驱逐或调度禁止
网络层 节点网络连通性(通过 NodeLifecycleController 的 --node-eviction-rate 控制) NetworkUnavailable 条件 节点被标记为不可调度

2.3.1 kubelet 内部健康检查流程

// kubelet 状态更新伪代码(简化)
func (kl *Kubelet) updateNodeStatus() {
    // 1. 检查容器运行时
    runtimeReady := kl.runtimeService.Status()
    if !runtimeReady {
        kl.recordNodeCondition(Ready, False, "RuntimeNotReady")
        return
    }

    // 2. 检查系统资源
    if kl.isOutOfDisk() {
        kl.recordNodeCondition(Ready, False, "OutOfDisk")
    }
    if kl.hasMemoryPressure() {
        kl.recordNodeCondition(MemoryPressure, True, "MemoryPressure")
    }

    // 3. 检查 kubelet 自身健康
    if !kl.probeKubeletHealthz() {
        kl.recordNodeCondition(Ready, False, "KubeletNotHealthy")
    }

    // 4. 汇总并上报
    kl.patchNodeStatus()
}

2.3.2 节点压力驱逐机制

当节点出现 DiskPressure 或 MemoryPressure 时,kubelet 会触发主动驱逐,以保护节点稳定性。驱逐优先级由 QoS 类别决定:

  1. BestEffort Pod:最先被驱逐,无资源保证。
  2. Burstable Pod:当资源使用超过 requests 时被驱逐。
  3. Guaranteed Pod:最后被驱逐,仅在节点资源严重耗尽时。
📌 排障技巧: 使用 kubectl describe node <node-name> 查看 Conditions 字段中的 LastHeartbeatTime 和 LastTransitionTime,可以快速判断节点失联时长。结合 kubectl get events --field-selector involvedObject.kind=Node 查看节点事件链。

2.4 节点生命周期常见异常场景

异常现象 可能原因 排查命令 修复措施
节点一直 NotReady kubelet 未启动、容器运行时挂死、CNI 网络故障 systemctl status kubelet
journalctl -u kubelet -f
重启 kubelet、检查 containerd/cri-o 状态
节点频繁 Ready/NotReady 抖动 kubelet 心跳超时、节点负载过高、磁盘 I/O 瓶颈 top / iostat -x 1 调整 node-monitor-grace-period、扩容节点资源
节点 Ready 但 Pod 无法调度 节点被 taint、资源不足、DiskPressure 条件为 True kubectl describe node 查看 Taints 和 Conditions 删除 taint、清理磁盘、调整资源预留
节点被自动删除 node-controller 在 NodeMonitorGracePeriod 后删除 Node 对象(云环境自动修复) kubectl get node -o wide 查看 Age 检查云实例状态,重新注册节点
🔧 自动化运维建议: 在集群中部署 node-problem-detector 组件,它可以捕获内核日志、Docker/containerd 错误、硬件故障等底层问题,并上报为 NodeCondition,让集群自动响应非标准故障。

节点生命周期管理是集群稳定性的基石。掌握注册流程、状态机转换和健康检查机制,能让你在节点扩容或故障时快速定位根因,避免因节点状态误判导致 Pod 大面积迁移或服务中断。