2. Kubernetes 节点管理基础:节点生命周期、节点状态、节点健康检查机制
在实施节点滚动升级之前,必须深入理解 Kubernetes 节点的底层管理模型。节点是承载 Pod 的物理或虚拟工作单元,其生命周期、状态转换和健康检查机制直接决定了升级操作的窗口选择、风险边界和回退策略。本节将系统梳理这三个核心维度,为后续 Policy as Code 窗口控制提供坚实的知识基础。
2.1 节点生命周期:从注册到退役
Kubernetes 节点的生命周期包含四个关键阶段:注册(Registration)、就绪(Ready)、维护(Maintenance)、退役(Retirement)。每个阶段对应不同的控制面行为和调度策略。
| 阶段 | 触发条件 | 控制面行为 | 调度影响 |
|---|---|---|---|
| 注册 | kubelet 启动后向 API Server 创建 Node 对象 | 验证节点凭证,分配节点 CIDR,启动节点控制器监控 | 节点不可调度(NoSchedule)直到就绪 |
| 就绪 | 节点通过所有健康检查,NodeReady 条件为 True | 更新节点状态,调度器将 Pod 调度到该节点 | 正常调度 Pod |
| 维护 | 管理员执行 cordon/drain 或节点进入 NotReady | 标记节点不可调度,驱逐 Pod(drain 时) | 禁止新 Pod 调度,逐步迁移已有 Pod |
| 退役 | 节点被删除或长时间不可恢复 | 清理节点对象,释放关联资源(如 PV) | 节点从集群中完全移除 |
关键认知:滚动升级本质上是在“维护”阶段对节点进行批量操作。理解节点从“就绪”到“维护”再到“就绪”的完整闭环,是设计窗口控制策略的前提。
2.2 节点状态:NodeCondition 与状态机
每个节点通过 status.conditions 字段报告一组标准条件(NodeCondition)。这些条件共同构成节点的健康快照,也是节点控制器和调度器做出决策的依据。
核心 NodeCondition 包括:
- NodeReady:节点是否能够正常接受 Pod。True 表示健康,False 或 Unknown 表示异常。
- NodeDiskPressure:节点磁盘空间是否不足。True 表示存在压力,调度器会避免调度新 Pod。
- NodeMemoryPressure:节点内存是否不足。True 表示内存紧张,kubelet 可能开始驱逐低优先级 Pod。
- NodePIDPressure:节点 PID 资源是否耗尽。True 表示进程数接近上限。
- NodeNetworkUnavailable:节点网络配置是否正确。True 表示网络不可用。
节点状态机遵循以下转换逻辑:
注册 → NodeReady=False(初始)
↓
健康检查通过 → NodeReady=True(正常调度)
↓
健康检查失败 → NodeReady=False 或 Unknown(触发驱逐)
↓
管理员干预 → NodeReady=True(恢复)或 节点删除(退役)
升级窗口陷阱:如果节点在升级过程中出现 NodeMemoryPressure 或 NodeDiskPressure 为 True,即使 NodeReady 仍为 True,调度器也会限制新 Pod 调度。窗口控制策略必须将这些压力条件纳入“禁止升级”的规则集。
2.3 节点健康检查机制:kubelet 与节点控制器
Kubernetes 通过两层健康检查机制保障节点状态的准确性:kubelet 自检和节点控制器(Node Controller)监控。
2.3.1 kubelet 自检
kubelet 在每个节点上运行,定期执行以下检查:
- 资源检查:监控 CPU、内存、磁盘、PID 使用率,更新对应的压力条件。
- 运行时检查:验证容器运行时(如 containerd)是否响应。
- 网络检查:验证节点网络插件(如 Calico、Cilium)是否正常。
kubelet 通过 --node-status-update-frequency 参数(默认 10 秒)向 API Server 上报状态。如果 kubelet 自身崩溃,则停止上报。
2.3.2 节点控制器监控
节点控制器运行在控制面,负责:
- 心跳超时检测:如果节点超过
--node-monitor-grace-period(默认 40 秒)未上报状态,将 NodeReady 标记为 Unknown。 - Pod 驱逐:如果节点在
--pod-eviction-timeout(默认 5 分钟)内未恢复,开始驱逐该节点上的 Pod。 - 污点管理:自动为异常节点添加
node.kubernetes.io/unreachable或node.kubernetes.io/not-ready污点。
升级窗口关联:滚动升级时,节点会短暂重启 kubelet 或操作系统,导致心跳中断。节点控制器在
--node-monitor-grace-period 内不会触发驱逐,这为升级操作提供了天然的安全窗口。Policy as Code 应利用这个参数计算最大允许升级时间。
2.4 节点生命周期与健康检查的 SVG 架构图
下图展示了节点从注册到退役的完整生命周期,以及健康检查机制在其中的作用位置:
2.5 节点状态与健康检查的决策矩阵
在实际运维中,节点状态和健康检查结果共同决定升级操作的可行性。以下矩阵总结了常见场景下的决策逻辑:
| NodeReady | 压力条件 | kubelet 心跳 | 节点控制器动作 | 升级窗口可用性 |
|---|---|---|---|---|
| True | 全部 False | 正常 | 无 | ✅ 可用 |
| True | 任一 True | 正常 | 限制调度 | ⚠️ 谨慎(可能影响 Pod 重调度) |
| False | — | 停止 | 40s 后标记 Unknown | ❌ 不可用(节点已异常) |
| Unknown | — | 停止 | 5min 后开始驱逐 | ❌ 不可用(触发驱逐) |
Policy as Code 映射:在 OPA/Gatekeeper 或 Kyverno 策略中,应检查
status.conditions 中 NodeReady 是否为 True,且所有压力条件为 False,才允许对该节点执行升级操作。这可以避免在节点已经处于亚健康状态时进行升级,防止故障扩散。
2.6 节点管理命令速查
以下命令是节点生命周期管理的基础工具,也是滚动升级操作的前置步骤:
# 查看节点状态和条件
kubectl get nodes -o wide
kubectl describe node <node-name>
# 标记节点不可调度(cordon)
kubectl cordon <node-name>
# 驱逐节点上的 Pod(drain)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# 恢复节点调度(uncordon)
kubectl uncordon <node-name>
# 查看节点事件
kubectl get events --field-selector involvedObject.kind=Node
实践注意:
kubectl drain 会先 cordon 节点,然后驱逐所有非 DaemonSet Pod。如果 Pod 使用 emptyDir 且未设置 PDB(PodDisruptionBudget),drain 可能失败。窗口控制策略应要求目标节点上的所有关键工作负载已配置 PDB。