在 Kubernetes 生产集群里,控制平面的稳定性直接决定了工作负载能否持续自愈与合理分布。控制器管理器(kube-controller-manager)与调度器(kube-scheduler)作为控制平面的核心常驻组件,默认以单实例模式运行在节点上。当承载它们的节点发生宕机或者进程崩溃时,集群将失去副本维持与 Pod 排程能力。为了避免单点故障,我们需要让这两个组件以多副本形式部署,并通过选主机制保证同一时刻只有一个实例真正对外提供服务。

一、控制器管理器与调度器的职责及高可用基本原理
控制器管理器内部包含多个控制器循环,例如 ReplicationController、Deployment、StatefulSet 等控制器,它们持续比对 etcd 中资源的实际状态与期望状态,并触发调谐操作。调度器则监听未绑定的 Pod 对象,依据资源请求、亲和性、污点容忍等策略计算出最优节点,随后写入 Pod 的 nodeName 字段。二者都重度依赖与 API Server 的 watch 通信,逻辑上属于无状态服务,但操作 etcd 时必须避免多个实例同时下发冲突指令。
Kubernetes 借助 Leader Election 机制解决这一问题。当进程启动时携带 --leader-elect=true 参数,它们会通过 API Server 在 kube-system 命名空间下创建或更新一个 Lease 对象(早期版本使用 Endpoints 或 ConfigMap)。获得租约的实例成为 Leader,定期续租;其他实例处于 Standby 并不断尝试抢占。一旦 Leader 心跳超时,备用实例便能平滑接管,整个过程对上层用户基本无感。
从实现上看,选主逻辑封装在 client-go 的 leaderelection 包中。它利用资源版本号与更新时间做 CAS 操作,天然适应 API Server 的并发控制。我们在部署多副本时,不必额外引入 ZooKeeper 或 etcd 独立集群,直接使用 Kubernetes 自身元数据库即可,大幅降低了运维复杂度。
二、静态 Pod 与独立二进制两种部署方式的高可用差异
最常见的方式是将控制器管理器和调度器以静态 Pod 形式交由 kubelet 管理, manifests 目录中放入多个节点的同名 yaml,并开启选主。这种方式的优势在于组件随节点开机自启,无需 systemd 额外编排;缺点是如果所有静态 Pod 都落在同一个物理机柜,仍然可能因电力或网络分区集体失效。因此在高可用拓扑中,应当把至少三个控制节点分散在不同故障域,每个节点都运行一份副本。
另一种做法是脱离 kubelet,将组件作为独立二进制由 systemd 托管,或者打包进自建的容器编排中。这种方案灵活性更高,便于定制监控与资源限制,但要求运维人员自行保证进程存活与配置同步。无论哪种形态,核心配置中都必须显式声明 --leader-elect 及相关超时参数,否则多副本会各自为政,造成资源对象被重复修改。
下面给出一个静态 Pod 中调度器开启选主的片段示例,展示了关键启动参数:
apiVersion: v1
kind: Pod
metadata:
name: kube-scheduler
namespace: kube-system
spec:
containers:
- command:
- kube-scheduler
- --leader-elect=true
- --leader-elect-lease-duration=15s
- --leader-elect-renew-deadline=10s
- --leader-elect-retry-period=2s
- --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
- --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
image: k8s.gcr.io/kube-scheduler:v1.28.0
name: kube-scheduler
上述参数中,租约时长与续租截止时间需要根据网络抖动情况调整。如果集群跨地域,可以适当放大 lease-duration 以防误切;若是同机房低延迟环境,缩短重试周期能加快故障转移。
三、生产环境中常见的误配置与排查思路
一个典型误区是认为只要跑多个副本就天然高可用,却忘了检查 --leader-elect 是否开启。曾出现团队用负载均衡把流量分给三个调度器,但三者都未选主,同时调度同一批 Pod,导致节点资源被超额分配。正确做法是由组件自身选主,外部 LB 仅作健康探测或干脆不暴露这两个组件端口。
另一个隐蔽问题是证书与 kubeconfig 权限不足。选主需要在 kube-system 下读写 Lease,若 ServiceAccount 或证书缺少对应 RBAC,副本会不断报 403 并频繁易主。此时可通过 kubectl get lease -n kube-system 观察 holderIdentity 变化,并结合 API Server 审计日志定位拒绝来源。
我们还应当为组件配置独立的监控告警。例如抓取 leader_election_master_status 指标,当某个实例在周期内未成为 Leader 且无法接管时,说明集群可能发生了网络隔离。配合节点级别的 kubelet 健康检查,能够在控制平面异常时第一时间触发人工介入或自动重调度。
四、结合 kubeadm 与外部负载均衡的落地建议
使用 kubeadm 初始化控制平面时,可以通过 Manifest 补丁统一注入选主参数。对于已经存在的集群,修改 /etc/kubernetes/manifests 下的 yaml 后,kubelet 会自动重建 Pod。需要注意的是,kubeadm 默认已经开启选主,但部分离线环境会被二次打包脚本误关,升级前务必 diff 配置。
在多个控制节点前通常架设一层 VIP 或 HAProxy 指向 API Server,而控制器管理器与调度器并不需要被用户流量直接访问,因此不必纳入前端代理。它们只与本地或远端 API Server 通信,网络策略上应限制源 IP,减少攻击面。若采用私有云,可借助实例组伸缩策略保证控制节点数始终为奇数,从而让选主结果更稳定。
最后,建议定期做故障演练:主动停掉当前 Leader 所在的 Pod 或节点,观察备用实例能否在十秒内完成接管,以及业务 Pod 是否出现调度延迟堆积。只有经过真实杀进程验证的高可用,才算在运维手册里真正落地。
Kubernetescontroller_managerscheduler修改时间:2026-08-16 06:06:31