Leader Election 原理与流程详解
1. 核心组件
- client-go LeaderElector
- Lock 接口及实现
- LeaseLock(基于 CoordinationV1 Lease)
- ConfigMapLock(基于 ConfigMap)
- EndpointsLock(基于 Endpoints)
- Kubernetes API Server(协调资源的读写)
- 回调函数(OnStartedLeading、OnStoppedLeading、OnNewLeader)
2. 基础原理
每个副本都会尝试在 Kubernetes 集群中获取对某个「锁资源」的独占控制权。这个锁通常是一个 Lease 对象,包含以下字段:
- HolderIdentity:当前锁的持有者(通常是 Pod 名称)
- LeaseDurationSeconds:持有者需要定期「续约」的时间窗口
- AcquireTime / RenewTime:锁的首次获取和每次续约时间
借助 Kubernetes API 的资源版本(resourceVersion)机制,所有对同一 Lease 对象的更新都具备原子性和乐观并发控制。
3. 选举流程
-
NewLeaderElector 初始化
- 构造
LeaderElector
对象,配置锁类型、租约时长、续约超时、重试间隔,以及各类回调。
- 构造
-
进入选举循环(Run)
- 每隔
RetryPeriod
调用tryAcquireOrRenew()
:- 若 Lease 不存在,则尝试创建并持有该锁。
- 若 Lease 存在,检查:
- 如果 HolderIdentity 是自己,则更新 RenewTime(续约)。
- 如果当前时间 > RenewTime + LeaseDuration,则锁「过期」,尝试通过更新 HolderIdentity 抢占锁。
- 否则视为已有 Leader,等待下一轮重试。
- 每隔
-
成为 Leader 后
tryAcquireOrRenew()
成功后触发OnStartedLeading
回调,执行导出/消费事件的主逻辑。- Leader 会在
RenewDeadline
内不断续约,保证自己在租约期内保持主控权。
-
锁丢失或主动退出
- 若续约失败(如 API Server 无响应或网络抖动),超出
RenewDeadline
,LeaderElector
会调用OnStoppedLeading
。 - 之后其它副本可进入争夺,调用对应的
OnNewLeader
通知观测方当前的 Leader 身份。
- 若续约失败(如 API Server 无响应或网络抖动),超出
4. 关键参数说明
参数 | 含义 | 建议配置原则 |
---|---|---|
LeaseDuration | 一旦 Leader 停止续约,多少秒后可重选 | 视业务可容忍中断时间,通常 15–30 秒 |
RenewDeadline | Leader 续约的超时阈值 | 建议不超过 LeaseDuration 的 2/3 |
RetryPeriod | 非 Leader 轮询尝试锁操作的间隔 | 1–3 秒,兼顾及时性和 API Server 压力 |
5. 涉及到的 Kubernetes API 资源
- CoordinationV1 API
- Lease 对象(推荐用于 Leader Election)
- CoreV1 API
- ConfigMap / Endpoints(作为备选锁类型,不建议新项目使用)
6. 调优与最佳实践
- 将锁对象存放于一个专用的命名空间,避免与业务 ConfigMap 冲突
- 监控 Lease 对象状态:使用
kubectl get lease -n <ns>
或 Prometheus 自定义监控 - 配置合理的超时参数,避免网络短暂抖动导致频繁切换 Leader
- 在 OnStoppedLeading 回调中做好清理工作,确保不会干扰后续选举
如果你想进一步研读 tryAcquireOrRenew()
的源码细节,或模拟选举失败场景进行调试,请告诉我!