K8s-kubelet状态与事件反馈流程
Kubelet 状态与事件回传流程
目标
这篇文档只回答一个核心问题:kubelet 如何把节点侧观察到的 Pod 运行结果回传给控制面?
重点放在状态回传与事件上报两条通信链路的区别,以及控制器真正依赖的观察面是什么。
一句话摘要
kubelet 通过 statusManager 异步批量把 PodStatus 同步到 API Server,并通过事件记录器上报诊断性 Event;控制器主要观察的是 API Server 中资源对象的状态变化,而不是 kubelet 内部事件流本身。
1. 流程总览
从通信视角看,这条链路包含两条并行但职责不同的子链路:
- 状态回传链路:kubelet 把 Pod 运行状态写回 API Server,成为控制面的共享事实。
- 事件上报链路:kubelet 把诊断性 Event 写入 API Server,用于排障与审计。
这两条链路共享 API Server 作为存储,但消费方和语义完全不同。
Mermaid:总览图
flowchart LR
A[Kubelet subsystems] --> B[statusManager]
A --> C[EventRecorder]
B --> D[API Server PodStatus]
C --> E[API Server Events]
D --> F[Controllers watch Pods]
E --> G[Humans / monitoring tools]
状态与事件双链路架构图
flowchart TB
subgraph 状态产生["状态产生源"]
direction TB
PW[podWorkers<br/>容器状态]
PM[probeManager<br/>健康检查]
PLEG[PLEG<br/>生命周期事件]
VM[volumeManager<br/>卷状态]
end
subgraph 状态链路["状态回传链路 (控制面输入)"]
direction TB
SM[statusManager<br/>状态缓存]
SYNC[syncBatch<br/>批量同步]
PATCH[PATCH /status<br/>API 调用]
end
subgraph 事件链路["事件上报链路 (诊断面输入)"]
direction TB
ER[EventRecorder<br/>事件记录]
EB[EventBroadcaster<br/>批量上报]
POST[POST Events<br/>API 调用]
end
subgraph API层["API Server"]
API[kube-apiserver]
ETCD[(etcd)]
end
subgraph 消费者["消费方"]
direction TB
CTRL[Controllers<br/>驱动控制逻辑]
KUBECTL[kubectl describe<br/>调试工具]
MON[监控系统<br/>Prometheus/ELK]
end
PW --> SM
PM --> SM
PLEG --> SM
VM --> SM
PW -.->|异常事件| ER
PM -.->|探针失败| ER
PLEG -.->|容器死亡| ER
SM --> SYNC
SYNC --> PATCH
PATCH --> API
ER --> EB
EB --> POST
POST --> API
API <--> ETCD
API -->|watch Pod| CTRL
API -->|读取 Event| KUBECTL
API -->|读取 Event| MON
StatusManager 内部工作机制图
flowchart TD
subgraph 输入["状态输入"]
I1[SetPodStatus]
I2[SetContainerReadiness]
I3[TerminatePod]
end
subgraph 缓存层["本地缓存"]
PS["podStatuses<br>map UID versionedPodStatus"]
ASV["apiStatusVersions<br>已同步版本"]
CH["podStatusChannel<br>变更通知"]
end
subgraph 同步循环["同步循环"]
START[Start goroutine]
BATCH[syncBatch]
CHECK{需要同步}
BUILD[构建 PATCH 请求]
SEND[发送到 API Server]
RETRY{成功}
UPDATE[更新 apiStatusVersions]
WAIT[等待下一周期]
end
I1 --> PS
I2 --> PS
I3 --> PS
PS --> CH
START --> BATCH
CH --> BATCH
BATCH --> CHECK
CHECK -->|是| BUILD
CHECK -->|否| WAIT
BUILD --> SEND
SEND --> RETRY
RETRY -->|是| UPDATE
RETRY -->|否| WAIT
UPDATE --> WAIT
WAIT --> BATCH
这张图想表达什么
- 状态是控制面的输入,事件是诊断面的输入。
- 控制器主要看对象状态,而不是事件流。
- 状态同步是异步批量的,有本地缓存和版本控制机制。
2. 分阶段通信流程
阶段一:kubelet 内部产生状态变更
这个阶段的本质是:各个子系统把观察到的运行结果汇总到 statusManager。
步骤 1.1:podWorkers 完成一次 SyncPod
当 podWorkers 完成一次 SyncPod 后,它会得到容器的创建/启动结果。这些结果需要被反映到 PodStatus 中。
通信方向:podWorkers → statusManager(通过 SetPodStatus)
步骤 1.2:probe manager 执行健康检查
probeManager 定期执行 liveness/readiness/startup 探针。当探针结果变化时(例如从成功变失败),它会更新对应的 probe result manager。
通信方向:probeManager → livenessManager/readinessManager/startupManager
步骤 1.3:probe result 触发状态更新
当探针结果变化时,会触发 statusManager 的状态更新。例如,readiness 探针失败会导致 Pod 的 Ready 条件变为 False。
通信方向:probe result manager → statusManager
步骤 1.4:PLEG 检测到容器变化
PLEG(Pod Lifecycle Event Generator)定期 relist 容器状态,检测到变化时会生成 Pod 生命周期事件,触发 Pod 同步,间接导致状态更新。
通信方向:PLEG → podWorkers → statusManager
步骤 1.5:statusManager 缓存新状态
statusManager.SetPodStatus(...) 把新状态写入本地缓存 podStatuses。此时状态还没有写入 API Server,只是 kubelet 内部视图更新了。
通信方向:statusManager 内部 map 更新
阶段二:statusManager 异步同步到 API Server
这个阶段的本质是:把本地缓存的状态批量写回控制面。
步骤 2.1:statusManager 启动同步循环
statusManager.Start() 启动一个 goroutine,定期或在收到状态变更信号时执行 syncBatch(...)。
通信方向:statusManager 内部循环
步骤 2.2:判断是否需要同步
syncBatch 会检查每个 Pod 的状态是否有变化,以及是否到达同步间隔。只有需要同步的 Pod 才会被处理。
通信方向:statusManager 内部判断
步骤 2.3:构造 Patch/Update 请求
对于需要同步的 Pod,statusManager 会构造一个 Patch 或 Update 请求,只更新 status 子资源,而不是整个 Pod 对象。
通信方向:statusManager 内部构造
步骤 2.4:发送到 API Server
statusManager 通过 client-go 向 API Server 发送请求。API Server 校验权限后更新 Pod 的 status 字段。
通信方向:statusManager → API Server(HTTP PATCH/PUT)
步骤 2.5:处理同步失败
如果同步失败(例如网络问题、冲突),statusManager 会保留该 Pod 在缓存中,等待下一个周期重试。
通信方向:statusManager 内部错误处理
步骤 2.6:更新同步版本
同步成功后,statusManager 会记录当前的 apiStatusVersions,用于后续判断是否需要再次同步。
通信方向:statusManager 内部状态更新
阶段三:事件上报并行发生
这个阶段的本质是:除了状态,kubelet 还会并行上报诊断性事件。
步骤 3.1:子系统检测到需要记录的事件
当容器启动失败、探针失败、镜像拉取失败等情况发生时,相关子系统会调用 EventRecorder 记录事件。
通信方向:各子系统 → EventRecorder
步骤 3.2:EventRecorder 构造 Event 对象
EventRecorder 会构造一个 v1.Event 对象,包含:
- 事件类型(Normal/Warning)
- 原因(Reason)
- 消息(Message)
- 相关对象引用(InvolvedObject)
通信方向:EventRecorder 内部构造
步骤 3.3:EventBroadcaster 批量上报
EventBroadcaster 会收集多个事件,批量发送到 API Server。这样可以减少 API 调用次数。
通信方向:EventBroadcaster → API Server(HTTP POST)
步骤 3.4:事件存储在 API Server
API Server 收到事件后,会存储在 etcd 中。事件有 TTL(默认 1 小时),过期后自动清理。
通信方向:API Server → etcd
步骤 3.5:事件对控制器的影响
控制器通常不消费事件流作为控制输入。事件主要用于:
kubectl describe显示- 日志收集系统
- 告警系统
通信方向:事件是只读的诊断信息
小结:这条链路的 2 条通信链路
| 链路 | 目的 | 消费方 | 是否驱动控制逻辑 |
|---|---|---|---|
| PodStatus 同步 | 把运行状态变成控制面事实 | 控制器 | 是 |
| Event 上报 | 记录诊断信息 | 人类/监控系统 | 否(通常) |
核心结论:控制器主要观察 API Server 中的对象状态,而不是消费事件流。
2.5 完整流程图
下面这张图把本文所有步骤串在一起,方便一眼看完整个通信链路:
flowchart TD
subgraph 状态产生["状态产生"]
A1[podWorkers SyncPod 完成] --> A2[容器状态]
A2 --> A3[statusManager.SetPodStatus]
A4[probeManager 探针] --> A5[liveness/readiness/startup 结果]
A5 --> A6[probe result manager]
A6 --> A3
A7[PLEG relist] --> A8[Pod 生命周期事件]
A8 --> A9[podWorkers]
A9 --> A3
A3 --> A10[本地缓存 podStatuses]
end
subgraph 状态同步["状态同步"]
A10 --> B1[syncBatch 循环]
B1 --> B2{需要同步?}
B2 -->|是| B3[构造 Patch 请求]
B2 -->|否| B4[等待下一周期]
B3 --> B5[发送到 API Server]
B5 --> B6{成功?}
B6 -->|是| B7[更新 apiStatusVersions]
B6 -->|否| B8[保留缓存等待重试]
end
subgraph 事件上报["事件上报"]
C1[子系统检测事件] --> C2[EventRecorder.Eventf]
C2 --> C3[构造 Event 对象]
C3 --> C4[EventBroadcaster 批量]
C4 --> C5[POST 到 API Server]
C5 --> C6[存储到 etcd]
C6 --> C7[kubectl describe 显示]
end
subgraph 控制器观察["控制器观察"]
B5 --> D1[API Server Pod 更新]
D1 --> D2[controller informer]
D2 --> D3[本地缓存更新]
D3 --> D4[触发 reconcile]
end
2.6 与其他组件的交互
这条链路不只是 kubelet 内部的事,还涉及多个外部系统的协作:
与各类 Controller 的交互
不同控制器会消费 PodStatus 来驱动各自的收敛逻辑:
| 控制器 | 关注的 PodStatus 字段 | 做什么 |
|---|---|---|
| ReplicaSet Controller | phase, podIP |
管理 Pod 生命周期 |
| Deployment Controller | conditions[Ready] |
控制滚动更新 |
| Service Controller | podIP, ready |
更新 Endpoint |
| Job Controller | phase, containerStatuses |
跟踪任务完成 |
关键理解:控制器通过 informer/watch 观察 Pod 对象,而不是被 kubelet 主动通知。
与监控系统的交互
Event 是监控系统的重要输入:
flowchart LR
A[EventRecorder] --> B[API Server]
B --> C[Event 对象]
C --> D[Prometheus Event Exporter]
C --> E[ELK/日志系统]
C --> F[告警系统]
| 系统 | 如何消费 Event |
|---|---|
| Prometheus | 通过 Event Exporter 转换为指标 |
| ELK | 直接索引 Event 对象 |
| 告警系统 | 监听 Warning 类型 Event |
关键理解:Event 有 TTL(默认 1 小时),不适合作为长期存储。
与 kubectl describe 的交互
kubectl describe pod 会聚合显示 Pod 的状态和事件:
flowchart TD
A[kubectl describe] --> B[读取 Pod 对象]
B --> C[显示 PodStatus]
A --> D[查询相关 Event]
D --> E[按时间排序]
E --> F[显示事件列表]
关键理解:Event 的 involvedObject 字段关联到具体 Pod,方便查询。
与 PLEG(Pod Lifecycle Event Generator)的交互
PLEG 是状态产生的重要来源:
flowchart LR
A[PLEG] --> B[定期 relist 容器]
B --> C[对比上次状态]
C --> D{有变化?}
D -->|是| E[生成 PodLifecycleEvent]
E --> F[podWorkers]
F --> G[触发 SyncPod]
G --> H[statusManager]
关键理解:PLEG 不是直接写 API Server,而是通过触发 podWorkers 间接导致状态更新。
与探针系统的交互
探针结果直接影响 PodStatus 中的条件:
flowchart TD
A[容器启动成功] --> B[probeManager]
B --> C{liveness 探针}
B --> D{readiness 探针}
B --> E[startup 探针]
C --> F[livenessManager]
D --> G[readinessManager]
E --> H[startupManager]
F --> I[statusManager]
G --> I
H --> I
I --> J[更新 Pod conditions]
| 探针类型 | 影响的条件 | 失败后果 |
|---|---|---|
| liveness | 无直接条件 | 容器重启 |
| readiness | Ready |
从 Service 移除 |
| startup | Initialized |
阻塞其他探针 |
关键理解:探针结果先写入 probe result manager,再通过 statusManager 同步到 API Server。
交互总结表
| 外部系统 | 交互方式 | 影响什么 |
|---|---|---|
| 各类 Controller | informer/watch Pod | 驱动控制逻辑 |
| 监控系统 | 读取 Event | 指标、告警 |
| kubectl describe | 读取 Pod + Event | 诊断信息 |
| PLEG | 生成事件触发 SyncPod | 状态产生 |
| 探针系统 | 写入 probe result manager | Pod 条件 |
3. 关键时序图
Mermaid:主时序图
sequenceDiagram
participant Subsys as Kubelet Subsystems
participant StatusMgr as statusManager
participant APIServer
participant EventRecorder
participant Controller
Subsys->>StatusMgr: SetPodStatus(...)
StatusMgr->>StatusMgr: cache new status
StatusMgr->>APIServer: syncBatch patch/update PodStatus
Subsys->>EventRecorder: Eventf(...)
EventRecorder->>APIServer: create Event object
APIServer-->>Controller: watch Pod status changes
Controller->>Controller: reconcile based on object state
时序图里的 3 个关键点
statusManager有本地缓存,状态同步是异步批量的。- Event 与 PodStatus 是两条独立的写入路径。
- 控制器通过 watch 对象状态来驱动收敛,而不是消费 Event 流。
4. 异常与分支路径
Mermaid:异常/分支路径图
flowchart TD
A[status change observed] --> B[SetPodStatus to local cache]
B --> C{syncBatch triggered?}
C -->|Yes| D[patch/update PodStatus to API Server]
D --> E{write succeeds?}
E -->|No| F[retry in next syncBatch cycle]
E -->|Yes| G[controllers observe new state]
C -->|No| H[wait for next tick or event]
I[probe failure / container crash] --> J[EventRecorder.Eventf]
J --> K[write Event to API Server]
K --> L[visible in kubectl describe / logs]
读这张图时要关注什么
- 状态同步失败:会在下一个 syncBatch 周期重试,而不是立即丢弃。
- Event 写入失败:通常不会影响控制逻辑,只是诊断信息丢失。
- 控制器观察的是对象状态:即使 Event 丢失,控制器仍然可以根据 PodStatus 做出正确决策。
5. 这个流程里谁负责什么
| 组件 | 主要职责 | 不负责什么 |
|---|---|---|
statusManager |
缓存 PodStatus 并异步同步到 API Server | 不直接驱动控制逻辑 |
EventRecorder |
上报诊断性 Event | 不是控制面的主输入 |
kube-apiserver |
持久化 PodStatus 和 Event | 不执行控制器逻辑 |
controllers |
通过 informer/watch 观察对象状态 | 不消费 Event 作为主控制输入 |
6. 常见误解
误解 1:控制器主要靠 Event 驱动控制逻辑
不是。Event 更偏向诊断信号,主观察面通常是 Pod/Node 等对象状态。
误解 2:每次状态变化都同步阻塞写 API Server
不是。statusManager 有本地缓存与批量异步同步机制。
误解 3:kubelet 内部事件流 = 控制面对象状态
不是。对外一致性语义主要体现为 API Server 中的对象状态,而不是 kubelet 内部事件流。
7. 版本差异说明
这条链路在 Kubernetes 1.27/1.28/1.29 中有一些值得注意的变化:
1.27 → 1.28 变化
| 变化点 | 说明 |
|---|---|
| Job Pod Failure Policy (Beta) | Job 控制器可以更精细地根据 Pod 失败条件决定是否重试 |
| Indexed Job 改进 | Indexed Job 的状态回传更准确 |
| Event API 改进 | Event 的 regarding 字段支持更多对象类型 |
1.28 → 1.29 变化
| 变化点 | 说明 |
|---|---|
| 终止 Pod IP 字段修复 | 修复了终止态 Pod 的 PodIP 字段可能被临时移除的问题 |
| 探针超时处理改进 | startup 探针超时后的状态传播更准确 |
| Event TTL 可配置 | 通过 --event-ttl 可以配置 Event 保留时间 |
向后兼容性
| 版本 | 兼容性注意 |
|---|---|
| 1.27+ | Job Pod Failure Policy 需要更新 Job API 使用方式 |
| 1.28+ | Event API 变化对老客户端透明 |
| 1.29+ | 终止 Pod IP 修复可能影响依赖该行为的逻辑 |
需要关注的废弃
| 废弃项 | 替代方案 | 移除版本 |
|---|---|---|
--event-burst 默认值变更 |
调整为 10000 | 1.28 已变更 |
Event firstTimestamp/lastTimestamp |
使用 eventTime 和 series |
计划移除 |
7. 与后续文档的关系
建议按这个顺序阅读:
docs/pod-on-node-realization-flow.md- 本文:理解运行结果如何回到控制面
docs/node-heartbeat-and-health-flow.md:理解节点健康信号如何影响控制面判断
8. 代码入口(精简版)
如果读者想从流程跳回实现,可从下面几个入口开始:
- status manager 启动同步循环:
pkg/kubelet/status/status_manager.go:194Start()
- 写入 PodStatus:
pkg/kubelet/status/status_manager.go:283SetPodStatus(...)
- 批量同步到 API Server:
pkg/kubelet/status/status_manager.go:766syncBatch(all bool)
9. 详细时序图
9.1 状态同步完整时序图
sequenceDiagram
autonumber
participant PW as podWorkers
participant PR as probeManager
participant PLEG as PLEG
participant SM as statusManager
participant CACHE as 本地缓存
participant API as kube-apiserver
participant CTRL as Controller
Note over PW,SM: 状态产生源
par 并行状态更新
PW->>SM: SetPodStatus(pod, status)
PW->>CACHE: 写入 podStatuses[UID]
PR->>PR: 执行探针
PR->>SM: SetContainerReadiness(pod, containerID, ready)
PLEG->>PLEG: relist 容器
PLEG->>PW: PodLifecycleEvent
PW->>SM: SetPodStatus(pod, status)
end
Note over SM: 同步循环
loop 每 syncBatch 周期
SM->>CACHE: 遍历 podStatuses
SM->>SM: 检查是否需要同步
alt 状态有变化 或 到达同步间隔
SM->>SM: 构造 PATCH 请求
SM->>API: PATCH /api/v1/namespaces/<ns>/pods/<pod>/status
alt 同步成功
API-->>SM: 200 OK
SM->>SM: 更新 apiStatusVersions
else 同步失败 (冲突)
API-->>SM: 409 Conflict
SM->>SM: 保留在缓存,下周期重试
else 同步失败 (网络)
API-->>SM: Error
SM->>SM: 保留在缓存,下周期重试
end
else 无需同步
SM->>SM: 跳过
end
end
Note over API,CTRL: Controller 感知状态变化
API-->>CTRL: watch 推送 Pod UPDATE
CTRL->>CTRL: 更新本地缓存
CTRL->>CTRL: 触发 reconcile 逻辑
9.2 事件上报时序图
sequenceDiagram
autonumber
participant SUBSYS as Kubelet 子系统
participant ER as EventRecorder
participant EB as EventBroadcaster
participant API as kube-apiserver
participant ETCD as etcd
participant USER as 用户/监控
Note over SUBSYS: 检测到需要记录的事件
SUBSYS->>ER: Eventf(regarding, related, eventtype, reason, message)
ER->>ER: 构造 Event 对象
Note over ER: Event{<br/> Type: Normal/Warning,<br/> Reason: "Started",<br/> Message: "...",<br/> InvolvedObject: Pod<br/>}
ER->>EB: Action(events channel)
Note over EB: 批量聚合
loop 批量发送
EB->>API: POST /api/v1/namespaces/<ns>/events
API->>ETCD: 存储 Event
ETCD-->>API: 确认
API-->>EB: 201 Created
end
Note over API,USER: 事件消费
par 并行消费
USER->>API: kubectl describe pod
API-->>USER: 返回 Pod + Events
and
USER->>API: kubectl get events
API-->>USER: 返回 Event 列表
and
MONITOR->>API: watch events
API-->>MONITOR: 实时推送 Events
end
9.3 探针状态传播时序图
sequenceDiagram
autonumber
participant CTR as 容器
participant PR as probeManager
participant LM as livenessManager
participant RM as readinessManager
participant SM as statusManager
participant API as kube-apiserver
participant SVC as Service/Endpoint
Note over PR: 定期执行探针
loop 每个探针周期
PR->>CTR: HTTP GET /healthz (或 TCP/Exec)
alt 探针成功
CTR-->>PR: 200 OK
PR->>RM: Set(containerID, results.Success)
else 探针失败
CTR-->>PR: Timeout/Error
PR->>RM: Set(containerID, results.Failure)
end
end
Note over RM: 探针结果变化
RM->>SM: 触发状态更新
SM->>SM: 更新 Pod conditions[Ready]
alt Ready=True
SM->>API: PATCH Pod status
API-->>SVC: watch 触发
SVC->>SVC: 添加 Pod IP 到 Endpoint
else Ready=False
SM->>API: PATCH Pod status
API-->>SVC: watch 触发
SVC->>SVC: 从 Endpoint 移除 Pod IP
end
Note over LM: Liveness 失败处理
alt Liveness 探针持续失败
LM->>LM: 记录失败次数
LM->>LM: 超过阈值
LM->>SM: 触发容器重启
SM->>SM: 更新 Pod status
end
10. 故障排查指南
10.1 常见问题与诊断方法
问题 1:Pod 状态与实际容器状态不一致
症状:kubectl get pod 显示 Running,但容器实际已退出
排查流程图:
flowchart TD
A[状态不一致] --> B{检查 PLEG}
B --> B1[PLEG relist 正常?]
B1 -->|否| C[PLEG 问题]
C --> C1[检查 relist 错误日志]
C --> C2[检查 CRI 连接]
B1 -->|是| D{检查 statusManager}
D --> D1[检查 syncBatch 是否执行]
D1 --> D2[检查 API 同步错误]
D --> E{检查网络}
E --> E1[检查与 API Server 连接]
E --> E2[检查权限]
A --> F{手动触发同步}
F --> F1[删除 Pod 触发重建]
F --> F2[重启 kubelet]
诊断命令:
1 | # 检查 Pod 实际状态 |
问题 2:事件丢失或延迟
症状:kubectl describe pod 看不到预期的事件
排查流程图:
flowchart TD
A[事件丢失/延迟] --> B{检查 Event 对象}
B --> B1[检查 Event 是否存在]
B1 -->|存在| C[显示问题]
C --> C1[检查 kubectl 权限]
C --> C2[检查 Event TTL]
B1 -->|不存在| D{检查事件上报}
D --> D1[检查 EventRecorder 日志]
D --> D2[检查 EventBroadcaster]
D --> E{检查 API Server}
E --> E1[检查 API Server 负载]
E --> E2[检查 etcd 性能]
A --> F{检查事件量}
F --> F1[事件过多被限流]
F --> F2[调整 event-burst]
诊断命令:
1 | # 查看 Pod 相关事件 |
问题 3:探针状态未正确传播
症状:容器健康但 Pod Ready=False
排查流程图:
flowchart TD
A[Ready 状态异常] --> B{检查探针配置}
B -->|无 readinessProbe| C[无探针,检查默认行为]
B -->|有探针| D{检查探针执行}
D --> D1[检查探针日志]
D1 --> D2{探针成功?}
D2 -->|否| E[探针失败]
E --> E1[检查探针端口]
E --> E2[检查探针路径]
E --> E3[检查容器网络]
D2 -->|是| F{检查状态传播}
F --> F1[检查 readinessManager]
F --> F2[检查 statusManager]
A --> G{检查容器状态}
G --> G1[容器是否 Running?]
G --> G2[容器是否 Ready?]
诊断命令:
1 | # 检查探针配置 |
10.2 关键日志关键词
| 场景 | 日志关键词 | 含义 |
|---|---|---|
| 状态同步 | syncBatch |
批量同步 |
| 状态写入 | SetPodStatus |
状态写入缓存 |
| API 同步 | PatchPodStatus |
API 更新 |
| 探针执行 | Probe succeeded/failed |
探针结果 |
| 事件上报 | Event |
事件记录 |
| PLEG | relist |
容器状态列表 |
10.3 配置参数参考
| 参数 | 默认值 | 说明 |
|---|---|---|
--event-burst |
10000 | 事件突发量 |
--event-qps |
5 | 每秒事件数 |
--sync-frequency |
1m | 同步频率 |
--status-update-frequency |
10s | 状态更新频率 |
--minimum-container-ttl-duration |
0s | 容器 TTL |
10.4 一键诊断命令
1 | # 状态同步诊断脚本 |
11. 面试题与详细解答
11.1 基础概念题
Q1: StatusManager 是如何工作的?
答案:
StatusManager 负责将 kubelet 内部的 Pod 状态同步到 API Server。
架构设计:
1 | ┌─────────────────────────────────────────────────────┐ |
关键特性:
- 本地缓存:
podStatusesmap 缓存每个 Pod 的最新状态 - 版本控制:
version字段防止旧状态覆盖新状态 - 异步同步:
syncBatch定期批量同步,不阻塞主流程 - 失败重试:同步失败的状态保留在缓存,下次重试
代码实现:
1 | // pkg/kubelet/status/status_manager.go:283 |
Q2: Event 和 Status 有什么区别?
答案:
| 维度 | Status | Event |
|---|---|---|
| 目的 | 驱动控制逻辑 | 诊断和审计 |
| 消费方 | Controllers | 人类/监控系统 |
| 存储 | 持久化,Pod 对象的一部分 | TTL 限制(默认 1 小时) |
| 更新方式 | PATCH /status | POST 创建新对象 |
| 格式 | 结构化状态数据 | 事件描述文本 |
| 是否影响调度 | 是(Ready condition) | 否 |
使用场景示例:
1 | # Status - 用于控制决策 |
关键理解:控制器主要 watch Pod status,而不是 Event 流。
11.2 进阶原理题
Q3: 探针(Liveness/Readiness/Startup)如何影响 Pod 状态?
答案:
三种探针对状态的不同影响:
| 探针类型 | 失败后果 | 影响的状态字段 |
|---|---|---|
| liveness | 容器重启 | 无直接 condition |
| readiness | 从 Service 移除 | conditions[Ready] |
| startup | 阻塞其他探针 | conditions[Initialized] |
Readiness 探针影响 Ready Condition 的流程:
sequenceDiagram
participant PM as ProbeManager
participant RM as readinessManager
participant SM as statusManager
participant API as kube-apiserver
participant EP as Endpoint Controller
PM->>PM: 执行 readiness probe
alt 探针成功
PM->>RM: Set(containerID, Success)
RM->>SM: 更新 Ready=True
SM->>API: PATCH Pod status
API-->>EP: watch Pod update
EP->>EP: 添加 Pod IP 到 Endpoint
else 探针失败
PM->>RM: Set(containerID, Failure)
RM->>SM: 更新 Ready=False
SM->>API: PATCH Pod status
API-->>EP: watch Pod update
EP->>EP: 从 Endpoint 移除 Pod IP
end
代码实现:
1 | // pkg/kubelet/prober/prober.go |
Q4: 为什么 statusManager 采用异步批量同步而不是实时同步?
答案:
设计原因:
性能优化
- 减少 API Server 压力
- 合并多次小更新为一次批量更新
- 避免频繁的 HTTP 请求
容错能力
- 网络抖动不影响本地状态
- 失败自动重试
- 最终一致性保证
资源效率
- 减少网络带宽
- 减少 etcd 写入
- 降低系统负载
实现细节:
1 | // pkg/kubelet/status/status_manager.go:766 |
同步策略:
- 状态变化时立即触发
- 定期全量同步(默认 10 秒)
- 终止状态的 Pod 优先同步
11.3 故障排查题
Q5: Pod 状态与实际容器状态不一致,如何排查?
答案:
排查流程:
flowchart TD
A[状态不一致] --> B{确认不一致类型}
B -->|Pod 显示 Running, 容器已退出| C[PLEG 问题]
C --> C1[检查 PLEG relist 日志]
C --> C2[检查容器运行时连接]
B -->|Pod 显示 NotReady, 容器正常| D[探针问题]
D --> D1[检查探针配置]
D --> D2[手动测试探针端点]
B -->|状态更新延迟| E[statusManager 问题]
E --> E1[检查 syncBatch 日志]
E --> E2[检查 API Server 连接]
A --> F{验证步骤}
F --> F1[kubectl get pod -o yaml]
F --> F2[crictl ps -a]
F --> F3[对比两者状态]
诊断命令:
1 | # 1. 对比 Pod status 和容器状态 |
常见原因:
| 原因 | 症状 | 解决方案 |
|---|---|---|
| PLEG relist 失败 | 状态不更新 | 检查 CRI 连接 |
| 探针超时 | Ready=False | 调整探针超时时间 |
| statusManager 同步失败 | 状态延迟 | 检查 API Server 连接 |
| 容器快速重启 | 状态跳动 | 检查应用崩溃原因 |
11.4 设计思想题
Q6: 为什么 Kubernetes 将状态和事件分开存储?
答案:
分离设计的优势:
职责分离
- Status:控制面输入,驱动 Controller 决策
- Event:诊断信息,用于调试和审计
性能优化
- Status 是高频更新,需要持久化
- Event 是低频诊断,可以 TTL 过期
存储效率
- Status:每个 Pod 一个 status 对象
- Event:每次事件一个 Event 对象,但有过期清理
访问模式不同
- Status:Controllers watch,需要实时
- Event:人类查询,可以延迟
数据流对比:
1 | Status 流: |
Event 的设计考量:
1 | // Event 有 TTL,默认 1 小时 |

