mirror of
https://github.com/Baim0/baim0-learn.git
synced 2026-10-19 17:57:45 +08:00
2.0 KiB
2.0 KiB
title, date, tags, categories
| title | date | tags | categories | ||
|---|---|---|---|---|---|
| APIServer Cache 脏数据导致 Ghost Pod 仍在调度 | 2026-06-02 |
|
|
问题现象
发现调度器仍在调度已不存在或早已下线的 Pod。Pod 实际已不存在(etcd 中无记录),但 kube-scheduler 组件重启后 list/watch 仍能获取到该 Pod 信息,疑似脏数据导致。
问题原因
根因是 APIServer cache 与 etcd 数据不一致:
- 部分 APIServer 副本的 watch cache 数据是旧的(stale),导致 scheduler 通过 informer → watch → APIServer cache 这条链路一直能读到旧的 pending Pod 数据。
- 调度器写 binding 走的是 etcd quorum(强一致性),所以写的时候拿到的是真值(404,Pod 已不存在)。
- 调度器读 Pod 走的是 informer → watch → APIServer cache(最终一致性),所以读到的是 stale 数据。
读写两条路径不同步,这是 ghost Pod 的本质。
架构示意
调度器 ──读 Pod──→ Informer ──Watch──→ APIServer Cache(stale ❌)
调度器 ──写 Binding──→ APIServer ──→ etcd Quorum(真实 ✅)
解决方案
短期:滚动重启异常 APIServer
滚动重启缓存数据异常的 APIServer 副本即可恢复。重启后 watch cache 重建,与 etcd 数据重新同步。
长期:升级集群至 1.34+
Kubernetes 1.34 及以上版本默认开启 KUBE_WATCHCACHE_CONSISTENCY_CHECKER 功能,会定期检查 APIServer cache 与 etcd 之间的一致性,并在检测到不一致时自动修复(自愈),从根源上杜绝该类问题。
关键要点
| 链路 | 一致性模型 | 结果 |
|---|---|---|
| 读 Pod | APIServer Cache | 可能读到 stale |
| 写 Pod | etcd Quorum | 始终为真实值 |
排查此类问题时,核心思路是:对比 informer 侧拿到的数据与直接查 etcd/APIServer 的结果是否一致,若不一致,则高度怀疑 watch cache 脏数据。