关联
现象
2026-05-14 18:00 ~ 2026-05-15 10:00 时间窗口内,prod freetier-01 集群出现两类异常:
1. 两个 CNClaim 绑定同一个 Pod
019503e7-a833-7d33-b069-7f1c1fdc4d0e-normal-6rh6f cn-8fqpx Bound 13h
019584b6-c2e4-7e8b-a2fb-491bbf9424a7-normal-rjj66 cn-8fqpx Bound 36h
与 #581 相同模式:两个 claim 同时标记 Bound 到 cn-8fqpx。
2. CNClaim 绑定到已不存在的 Pod
Issue 时间点的 CN Pod 列表中,以下 Pod 后续全部被删除(NotFound),但 claim 状态仍为 Bound:
cn-8fqpx — 被 6rh6f 和 rjj66 同时绑定
cn-5fl29 — issue 创建时 phase=Idle,后来不存在
cn-7lrb7 — 已不存在
cn-bxqrq — 已不存在(sys claim 绑定的 pod)
Operator 日志时间线
Phase 1: 约 21:46 — 密集 reconcile + scale 循环
operator 进入高频 reconcile loop(每秒 2-4 次),持续 scale cnset replicas=13。此时 cn-8fqpx 已出现 conflict error(两个 controller 竞争 patch Pod annotation):
21:48:34 cnstore/controller.go:454 "error sync stats" pod=cn-8fqpx error="object has been modified"
此 conflict error 从 21:48 持续到 02:09,说明 cn-8fqpx 一直被两个 claim 并发操作。
Phase 2: 22:04 — CN does not exist 错误
22:04:00 cnclaim/controller.go:280 "error keep bound CN working" claim=t5wzs error="CN does not exist"
22:04:00 cnclaim/controller.go:280 "error keep bound CN working" claim=ob-sys-klfb4 error="CN does not exist"
22:04:00 cnclaim/controller.go:280 "error keep bound CN working" claim=shared-pkdj4 error="CN does not exist"
多个 claim 报告 CN store 不存在 → 触发迁移。
Phase 3: 22:14 — 迁移卡住(每秒重试)
claim h2mvc 迁移 cn-glhd9 → cn-qnl95 卡在 migrate.go:41 持续重试(22:14:47 ~ 22:15:28),每秒一次 log。22:15:02 才开始 draining source pod。
Phase 4: 02:19 — Pod 被删除,claim 被 finalize
02:19:52 cnstore/controller.go:101 "call HAKeeper to remove CN store" pod=cn-8fqpx
02:19:52 reconciler.go:370 "resource finalizing complete, remove finalizer" pod=cn-8fqpx
02:19:52 cnclaim/controller.go:280 "error keep bound CN working" claim=6rh6f error="CN does not exist"
02:20:24 cnclaim/controller.go:341 "finalize CNClaim" claim=6rh6f
02:22:00 cnclaim/controller.go:341 "finalize CNClaim" claim=rjj66
Pod cn-8fqpx 被 HAKeeper 移除后,绑定它的两个 claim 都被 finalize 删除。
根因分析
Bug 1: 重复绑定(与 #581 相同)
selectCN() (controller.go:137-176) 选择 Idle Pod 时:
- 仅通过 label selector 筛选
phase=Idle 的 Pod
- 不检查是否有其他 CNClaim 的
spec.podName 已指向该 Pod
- 依赖
ctx.Update(pod) 的乐观并发控制(OCC)防止双绑,但如果另一个 claim 通过 migration 绑定(不走 selectCN),则 OCC 无法防护
Bug 2: Claim 绑定不存在的 Pod
Sync() (controller.go:249-260) 在 Pod NotFound 时:
- 如果
BoundTime 存在且距今 < waitCacheTimeout,则 requeue 等待
- 超时后设置
phase=Lost
但实际观察:Pod 早已删除,claim 仍显示 Bound 而非 Lost。可能原因:
waitCacheTimeout 期间 CNClaimSet controller 重建了 claim,新 claim 继承了已删除 Pod 的 spec.podName
- 或者 claim 在 Lost 后又被某个 reconcile 路径刷回 Bound
Bug 3: 迁移 reconcile 风暴
迁移过程中(migrate.go:36-75),每次 reconcile 失败都打印完整的 migrate log 并 resync(10s interval),但实际日志显示每秒都在重试,说明有其他事件不断触发 reconcile,导致 operator CPU 负载激增。
当前状态
手工介入修复。通过人工删除异常 claim、修正 Pod label 等操作恢复绑定关系,operator 未能自愈。
修复建议
- selectCN 增加双重校验:选中 Idle Pod 后,检查集群中是否有其他 CNClaim 的
spec.podName 指向该 Pod
- Finalize 时检查其他 claim 引用:
Finalize() 回收 Pod 前,确认无其他 CNClaim 引用同一 Pod
- 迁移目标排除已占用 Pod:migrate 选择 target 时排除已被其他 claim 的
spec.podName 占用的 Pod
- Webhook 拦截重复绑定:admission webhook 拒绝将 Pod 的
claimed-by label 设为与已有 claim 不同的值
复现条件
- 多个 CNClaim 同时需要 Pod(如 scale-down 后重建)
- 迁移过程中源 Pod 被释放变为 Idle,被新 claim 抢占
- operator 高频 reconcile(每秒多次)加剧竞态窗口
关联
nightly-eb9b356-2026-04-26freetier-01现象
2026-05-14 18:00 ~ 2026-05-15 10:00 时间窗口内,prod freetier-01 集群出现两类异常:
1. 两个 CNClaim 绑定同一个 Pod
与 #581 相同模式:两个 claim 同时标记 Bound 到
cn-8fqpx。2. CNClaim 绑定到已不存在的 Pod
Issue 时间点的 CN Pod 列表中,以下 Pod 后续全部被删除(NotFound),但 claim 状态仍为 Bound:
cn-8fqpx— 被6rh6f和rjj66同时绑定cn-5fl29— issue 创建时 phase=Idle,后来不存在cn-7lrb7— 已不存在cn-bxqrq— 已不存在(sysclaim 绑定的 pod)Operator 日志时间线
Phase 1: 约 21:46 — 密集 reconcile + scale 循环
operator 进入高频 reconcile loop(每秒 2-4 次),持续 scale cnset replicas=13。此时
cn-8fqpx已出现 conflict error(两个 controller 竞争 patch Pod annotation):此 conflict error 从 21:48 持续到 02:09,说明
cn-8fqpx一直被两个 claim 并发操作。Phase 2: 22:04 — CN does not exist 错误
多个 claim 报告 CN store 不存在 → 触发迁移。
Phase 3: 22:14 — 迁移卡住(每秒重试)
claim
h2mvc迁移cn-glhd9 → cn-qnl95卡在migrate.go:41持续重试(22:14:47 ~ 22:15:28),每秒一次 log。22:15:02 才开始 draining source pod。Phase 4: 02:19 — Pod 被删除,claim 被 finalize
Pod
cn-8fqpx被 HAKeeper 移除后,绑定它的两个 claim 都被 finalize 删除。根因分析
Bug 1: 重复绑定(与 #581 相同)
selectCN()(controller.go:137-176) 选择 Idle Pod 时:phase=Idle的 Podspec.podName已指向该 Podctx.Update(pod)的乐观并发控制(OCC)防止双绑,但如果另一个 claim 通过 migration 绑定(不走 selectCN),则 OCC 无法防护Bug 2: Claim 绑定不存在的 Pod
Sync()(controller.go:249-260) 在 Pod NotFound 时:BoundTime存在且距今 <waitCacheTimeout,则 requeue 等待phase=Lost但实际观察:Pod 早已删除,claim 仍显示 Bound 而非 Lost。可能原因:
waitCacheTimeout期间 CNClaimSet controller 重建了 claim,新 claim 继承了已删除 Pod 的spec.podNameBug 3: 迁移 reconcile 风暴
迁移过程中(migrate.go:36-75),每次 reconcile 失败都打印完整的 migrate log 并 resync(10s interval),但实际日志显示每秒都在重试,说明有其他事件不断触发 reconcile,导致 operator CPU 负载激增。
当前状态
手工介入修复。通过人工删除异常 claim、修正 Pod label 等操作恢复绑定关系,operator 未能自愈。
修复建议
spec.podName指向该 PodFinalize()回收 Pod 前,确认无其他 CNClaim 引用同一 Podspec.podName占用的 Podclaimed-bylabel 设为与已有 claim 不同的值复现条件