K8s多副本工作负载如何实现master选举并保证升级时最后升级?
云原生友好的多副本Master选举实现
目前完全无需引入外部中间件、符合K8s原生设计的Master选举方案已经非常成熟,核心是依托K8s的原生协调能力实现:
- 基于
coordination.k8s.ioAPI组下的Lease资源实现分布式锁选举:K8s自身的核心组件(比如kube-controller-manager、多副本控制面组件)都是采用这种方式选主,完全不需要额外部署ZooKeeper、外部独立etcd集群等传统中间件。多副本实例启动后,共同竞争读写同一个命名空间下的Lease对象,成功持有Lease的实例即可标记为Master角色,其余实例为从角色。 - 借助K8s官方提供的
leaderelection客户端库快速接入:不需要开发者从零实现锁的续约、异常转移逻辑,仅需少量代码即可完成Lease锁的对接,完全对齐K8s的API规范,没有侵入式的自定义逻辑。 - 针对StatefulSet部署的实例,可进一步结合Pod的固定网络身份做校验,避免选主过程中的脑裂问题,相比Deployment下随机生成的Pod名称,选举状态的稳定性会更高。
Kubernetes场景下保障Master Pod最后升级的实现方案
Kubernetes本身提供了原生的升级顺序控制能力,不需要自定义控制器即可实现“所有非Master Pod先升级完成,Master Pod最后更新”的需求,核心是利用Pod的删除成本机制实现动态顺序控制:
- 核心原理:K8s从1.21版本开始GA了
spec.podDeletionCost字段,字段取值为整数,值越小的Pod,在滚动升级过程中越会被优先删除。我们可以让Pod的删除成本值和实时的Master身份动态绑定,而非硬编码固定的Pod名称。 - 具体配置流程:
- 完成Master选举后,每个实例根据自身角色调用K8s API,修改对应Pod的
podDeletionCost值:非Master Pod设置为较低值(比如10),Master Pod设置为最高值(比如100)。 - 滚动升级触发后,K8s会按照Pod删除成本从低到高的顺序删除旧版本Pod,自动先完成所有非Master Pod的更新,最后才会删除、更新持有Master角色的Pod。
- 完成Master选举后,每个实例根据自身角色调用K8s API,修改对应Pod的
- 不同工作负载的适配注意点:
- 适配Deployment:Deployment默认的滚动升级流程天然支持
podDeletionCost的顺序控制,只需要完成上述的动态成本值配置即可,不需要调整默认的升级策略参数。 - 适配StatefulSet:需要先将StatefulSet的
pod-management-policy配置为Parallel——因为默认的OrderedReady策略会严格按照Pod序号从高到低反向删除Pod,是写死的固定顺序,无法适配动态变化的Master身份;切换为Parallel管理模式后,Pod的创建、删除顺序就会完全参考podDeletionCost值执行,和Deployment的逻辑保持一致。
- 适配Deployment:Deployment默认的滚动升级流程天然支持
注意:不要采用“固定序号Pod承担Master角色”的硬编码实现,比如固定将StatefulSet的序号为0的Pod设为Master,这种方式在Pod发生漂移、Master角色切换到其他序号的Pod时,升级顺序会和实际Master身份错位,反而会导致Master Pod被提前删除的问题。
内容的提问来源于stack exchange,提问作者DT.
相关产品推荐
相关产品推荐

