4、节点状态同步概念
在集群节点扩容场景中,新节点加入集群后,其本地状态必须与集群控制面(Control Plane)保持一致,这个过程称为状态同步。状态同步是节点可调度、Pod 正常运行的先决条件,也是后续回滚操作的基础。
4.1 什么是状态同步
状态同步是指将节点上的运行时状态(如节点健康、Pod 生命周期、容器资源使用)上报至 API Server,并同时从 API Server 拉取期望状态(如调度决策、Pod 规约)以修正本地行为的过程。在 Containerd 环境下,kubelet 是状态同步的核心执行者,它通过 CRI(Container Runtime Interface)与 Containerd 通信,获取容器级状态并聚合为 Pod 状态和节点状态。
4.2 同步的维度
节点状态同步包含三个层次,从下至上依次为:容器状态、Pod 状态、节点状态。三者之间存在明确的依赖关系:容器状态是基础,Pod 状态是聚合,节点状态是全局视图。
| 同步维度 | 数据来源 | 同步内容 | 上报频率(默认) |
|---|---|---|---|
| 节点状态 | kubelet 本地采集 + 系统指标 | 节点 Ready/NotReady、磁盘压力、内存压力、PID 压力、网络可用性 | 每 10 秒(--node-status-update-frequency) |
| Pod 状态 | kubelet 通过 CRI 查询 Containerd | Pod Phase(Pending/Running/Succeeded/Failed/Unknown)、Pod 条件(Ready/Initialized/ContainersReady) | 每 10 秒(同步周期内) |
| 容器状态 | Containerd 通过 CRI 返回 | 容器状态(Created/Running/Exited/Unknown)、退出码、资源使用(CPU/内存/磁盘) | 每 10 秒(kubelet 主动查询) |
4.2.1 节点状态
节点状态是集群调度决策的直接依据。kubelet 通过 NodeStatus 对象向 API Server 报告以下关键条件:
- Ready:节点是否能够正常接收 Pod。如果 Containerd 服务异常或 CRI 通信超时,该条件变为 False。
- DiskPressure:节点磁盘空间是否充足。Containerd 的镜像存储目录(默认
/var/lib/containerd)空间不足时会触发此条件。 - MemoryPressure:节点内存是否接近耗尽。
- PIDPressure:节点 PID 分配是否接近上限。
- NetworkUnavailable:节点网络插件(如 CNI)是否就绪。
4.2.2 Pod 状态
Pod 状态是 kubelet 对 Pod 内所有容器状态的综合判断。kubelet 通过 CRI 调用 ListContainers 和 ContainerStatus 接口从 Containerd 获取每个容器的运行时状态,然后聚合为 Pod 的 status.phase 和 status.conditions。
- 所有容器均为 Running → Pod Phase = Running
- 至少一个容器为 Waiting(如镜像拉取中)→ Pod Phase = Pending
- 所有容器均为 Terminated 且退出码为 0 → Pod Phase = Succeeded
- 至少一个容器为 Terminated 且退出码非 0 → Pod Phase = Failed
- kubelet 无法获取容器状态(如 Containerd 宕机)→ Pod Phase = Unknown
4.2.3 容器状态
容器状态是状态同步的最小粒度。Containerd 通过 CRI 返回的容器状态包含以下字段:
- state:
CONTAINER_CREATED、CONTAINER_RUNNING、CONTAINER_EXITED、CONTAINER_UNKNOWN - exit_code:容器退出码(仅 Exited 状态有效)
- reason:状态变更原因(如
OOMKilled、Error、Completed) - resources:容器资源使用统计(CPU 时间、内存 RSS、磁盘读写)
4.3 同步的挑战
在集群节点扩容场景中,状态同步面临以下核心挑战:
| 挑战 | 描述 | 典型场景 | 影响 |
|---|---|---|---|
| 网络延迟 | 节点与 API Server 之间的网络往返时间(RTT)导致状态上报延迟 | 跨地域集群、公有云节点与控制面不在同一可用区 | 节点状态更新滞后,调度器可能将 Pod 调度到实际已不可用的节点 |
| 数据一致性 | kubelet 本地状态与 API Server 期望状态出现偏差 | 节点重启后 Containerd 容器状态丢失、并发调度冲突 | Pod 被重复调度、孤儿 Pod、资源泄漏 |
| 状态风暴 | 大量节点同时加入或状态变更时,API Server 和 etcd 写入压力激增 | 集群扩容 100+ 节点同时上线 | API Server 响应变慢,甚至触发限流导致同步失败 |
| CRI 超时 | kubelet 调用 Containerd CRI 接口超时,无法获取容器状态 | Containerd 负载过高、镜像拉取阻塞、磁盘 I/O 瓶颈 | Pod 状态变为 Unknown,节点可能被标记为 NotReady |
4.3.1 网络延迟的应对策略
Kubernetes 通过以下机制缓解网络延迟的影响:
- 节点租约(Node Lease):Kubernetes 1.14+ 使用 Lease API 替代心跳更新,减少 etcd 写入频率。节点每 10 秒更新一次 Lease,而非每次更新完整的 NodeStatus。
- 节点状态容忍时间:
--node-monitor-grace-period默认 40 秒,允许节点在短暂网络中断后恢复而不被标记为 NotReady。 - Pod 驱逐超时:
--pod-eviction-timeout默认 5 分钟,给网络恢复留出缓冲窗口。
4.3.2 数据一致性的保障机制
数据一致性是状态同步中最复杂的挑战。kubelet 采用以下策略保证最终一致性:
- 乐观并发控制:kubelet 通过
resourceVersion字段检测状态更新冲突,冲突时重试。 - 本地状态持久化:kubelet 将 Pod 状态缓存到本地文件系统(
/var/lib/kubelet/pods),节点重启后可从本地恢复。 - CRI 状态查询:kubelet 定期调用
ListContainers和ListPodSandbox从 Containerd 重建本地状态视图。
4.4 状态同步流程总览
下图展示了节点扩容时,从节点加入集群到状态完全同步的完整流程:
4.5 状态同步与回滚的关系
状态同步是回滚流程的数据基础。当节点扩容过程中出现状态不一致时(如 Pod 启动失败、节点标记为 NotReady),回滚操作需要依赖同步的状态信息做出决策:
- 回滚触发条件:节点状态持续 NotReady 超过阈值、Pod 状态长时间 Pending 或 CrashLoopBackOff、容器状态异常(如 OOM 频繁)。
- 回滚执行依据:kubelet 本地缓存的状态快照 + API Server 中的期望状态,两者对比确定需要清理的 Pod 和容器。
- 回滚后状态重建:回滚完成后,kubelet 重新执行状态同步,确保节点恢复到扩容前的已知状态。
RemoveContainer、StopPodSandbox)在重复调用时不会产生副作用。