2. 节点健康检查机制:Node Condition 与 Lease 对象
Kubernetes 集群的稳定性依赖于对每个节点状态的精确感知。节点健康检查机制是调度器做出迁移决策、控制器执行自愈操作的基础数据源。本章深入剖析 Node Condition(节点状况)的五种核心指标以及 Lease 对象(节点心跳租约)的工作原理,帮助运维人员理解故障检测的底层逻辑。
2.1 Node Condition 的五种核心状况
每个 Node 对象都包含一个 status.conditions 数组,其中记录了节点当前的各种状况。kube-controller-manager 中的 node-lifecycle-controller 负责定期检查并更新这些状况。以下是五种最关键的 Condition:
| Condition 名称 | 类型 | 典型 True 含义 | 典型 False 含义 | 故障影响 |
|---|---|---|---|---|
| Ready | 综合健康 | 节点正常,Pod 可调度 | 节点异常,Pod 被驱逐 | Pod 迁移、服务中断 |
| DiskPressure | 资源压力 | 磁盘空间/Inode 充足 | 磁盘空间不足,触发驱逐 | Pod 被驱逐至其他节点 |
| MemoryPressure | 资源压力 | 内存充足 | 内存紧张,触发 BestEffort Pod 驱逐 | 低优先级 Pod 被终止 |
| PIDPressure | 资源压力 | PID 数量正常 | PID 耗尽,无法创建新进程 | 节点上所有进程受影响 |
| NetworkUnavailable | 网络状况 | 网络插件正常工作 | 网络配置失败,节点不可达 | Pod 网络不通,服务不可用 |
kubectl describe node <node-name> 可以查看所有 Condition 的详细状态、最后心跳时间以及上次转换时间。重点关注 Ready 和 DiskPressure,它们是触发 Pod 自动迁移的最常见原因。
2.2 节点心跳机制与 Lease 对象
在早期 Kubernetes 版本中,节点心跳直接通过更新 Node 对象的 status.conditions 来实现。这种方式在高密度集群中会给 API Server 带来巨大的写入压力。从 v1.13 开始,Kubernetes 引入了 Lease 对象 作为轻量级的心跳载体。
每个节点在 kube-node-lease 命名空间中拥有一个同名的 Lease 对象。kubelet 每隔 node-status-update-frequency(默认 10 秒)更新一次 Lease 的 spec.renewTime 字段。node-lifecycle-controller 检查 Lease 的更新时间,如果超过 node-monitor-grace-period(默认 40 秒)未更新,则开始标记节点为 Unknown 状态。
- node-status-update-frequency:kubelet 上报心跳的频率,默认 10s。
- node-monitor-grace-period:控制器等待心跳的超时时间,默认 40s。
- pod-eviction-timeout:节点变为 NotReady 后,驱逐其上 Pod 的等待时间,默认 5min。
2.3 Condition 状态转换与故障判定
Node Condition 的状态转换遵循严格的时序逻辑。以 Ready 状况为例,其状态机包含三个值:True、False、Unknown。当 kubelet 停止上报心跳时,控制器不会立即将节点标记为 False,而是先进入 Unknown 状态,给予节点恢复的缓冲时间。
- 0s - 40s:kubelet 正常更新 Lease,节点状态为
Ready=True。 - 40s - 5min:Lease 超时,节点变为
Ready=Unknown,调度器停止向该节点调度新 Pod。 - 5min 后:如果仍未恢复,节点变为
Ready=False,控制器开始驱逐 Pod。
2.4 实战:查看节点 Condition 与 Lease
运维人员可以通过以下命令快速诊断节点健康状态:
# 查看节点所有 Condition
kubectl describe node worker-1 | grep -A 10 Conditions
# 查看 Lease 对象的最新更新时间
kubectl get lease -n kube-node-lease worker-1 -o yaml | grep renewTime
# 监控节点状态变化
kubectl get nodes --watch
- spec.holderIdentity:持有该 Lease 的节点标识,通常为节点名。
- spec.leaseDurationSeconds:租约有效期,默认 40 秒。
- spec.renewTime:kubelet 最后一次更新 Lease 的时间戳。
- spec.acquireTime:Lease 首次被获取的时间。