Skip to content

控制平面高可用

生产 Kubernetes 集群不会只放一个控制平面节点。单控制平面宕机后,已有 Pod 可能还在跑,但 API Server、调度、控制器、变更发布和节点状态更新都会受影响。高可用控制平面的重点是四个层面:API Server 入口、多个控制平面节点、etcd quorum 和证书配置。

高可用控制平面的四层

层次作用
API Server 入口给 kubectl、kubelet、控制器提供稳定地址,单点 IP 挂掉不影响访问
多控制平面节点多个 kube-apiserver、scheduler、controller-manager 实例
etcd 高可用多成员 Raft 集群保证状态不丢
证书和配置controlPlaneEndpoint、SAN、admin kubeconfig 全部指向入口地址

API Server 多副本无状态,scheduler 和 controller-manager 通过 leader election 保证同一时间主要由一个实例执行控制动作。etcd 依赖 Raft quorum——三成员允许坏一个,五成员允许坏两个。

stacked etcd 和 external etcd

kubeadm 官方高可用主要分两类:

方式结构优点代价
stacked etcdetcd 和控制平面组件跑在同一批节点机器少,部署简单控制平面节点压力集中
external etcdetcd 单独一组节点隔离好,故障域清楚机器更多,证书和运维更复杂

中小规模自建集群常用 stacked etcd。规模大、控制平面压力高、对 etcd 有单独运维要求时用 external etcd。普通机房环境用三控制平面 stacked etcd,把 etcd 磁盘、备份和告警做好就够。

API Server 高可用入口

controlPlaneEndpoint 是 kubeadm 高可用的核心配置,它会写进所有 kubeconfig 和节点连接地址。入口可以是:

方案说明
HAProxy + Keepalived裸机常见,VIP 漂移,HAProxy 四层转发到多个 API Server
kube-vip以静态 Pod 方式提供 VIP,K8s 场景更贴近
云负载均衡云上集群常见,SLB/ELB/NLB 指向 API Server
硬件负载均衡已有设备时使用

HAProxy 配置示例——注意是四层 TCP 转发,不需要 HTTP 检查:

haproxy
frontend kube-apiserver
    bind *:6443
    mode tcp
    option tcplog
    default_backend kube-apiserver-backend

backend kube-apiserver-backend
    mode tcp
    option tcp-check
    balance roundrobin
    server cp1 192.168.10.11:6443 check
    server cp2 192.168.10.12:6443 check
    server cp3 192.168.10.13:6443 check

Keepalived 提供 VIP:

conf
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass k8s-ha
    }
    virtual_ipaddress {
        192.168.10.100/24
    }
}

如果 HAProxy 和 Keepalived 放在控制平面节点上,要确认 6443 端口没有冲突——HAProxy 监听 VIP 的 6443,转发到各控制平面节点自己的 6443。

kubeadm 高可用初始化

第一台控制平面初始化时最关键的就是写 controlPlaneEndpoint

yaml
# kubeadm-ha.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.36.0
controlPlaneEndpoint: "192.168.10.100:6443" # VIP 或负载均衡地址
imageRepository: registry.aliyuncs.com/google_containers
networking:
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
bash
kubeadm init --config kubeadm-ha.yaml --upload-certs

--upload-certs 把证书加密上传到集群 Secret,后续控制平面节点加入时不再需要手动拷贝证书。输出里的 --certificate-key 要保存好,第二、三台控制平面加入时用。

第二、三台控制平面加入:

bash
kubeadm join 192.168.10.100:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash> \
  --control-plane \
  --certificate-key <certificate-key>

工作节点加入时不带 --control-plane

etcd quorum

三成员 etcd 最常见。超过半数成员存活才能正常写入:

etcd 成员数可容忍故障数说明
10实验环境
31常见生产最小规模
52更高容错,但写入延迟和维护成本更高

查看成员:

bash
kubectl -n kube-system exec etcd-k8s-master01 -- \
  etcdctl member list \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

etcd 不是越多越好。成员越多,写入需要复制到更多节点,网络和磁盘延迟对控制平面的影响更明显。多数普通集群三成员已经够用。

验证高可用

验证 API 入口:

bash
curl -k https://192.168.10.100:6443/readyz
kubectl get nodes -o wide

验证控制平面组件:

bash
kubectl -n kube-system get pods -o wide | grep -E 'apiserver|scheduler|controller|etcd'
kubectl get endpoints kubernetes -o wide

模拟单个控制平面节点故障:

bash
systemctl stop kubelet  # 停掉一台控制平面

观察:

bash
kubectl get nodes
kubectl get pods -A
curl -k https://192.168.10.100:6443/readyz

只停一个控制平面节点时,kubectl 通过 VIP 仍然能访问其他 API Server。业务 Pod 是否受影响取决于它们是否正好运行在这台节点、以及工作负载副本和调度策略。

常见问题

现象常见原因处理方向
join 控制平面失败certificate-key 过期或错误重新 kubeadm init phase upload-certs --upload-certs
kubelet 仍连单节点 IP初始化时没写 controlPlaneEndpoint重建或谨慎修改 kubeconfig
VIP 能 ping 但 6443 不通HAProxy 未监听或后端检查失败看 HAProxy 日志和后端端口
etcd member 异常节点故障、证书、磁盘慢看 etcd 日志、member list、磁盘延迟
kubectl 偶发超时负载均衡后端有坏节点健康检查和后端列表

高可用不是只把节点数量加到 3——API 入口、etcd quorum、证书、备份、负载均衡健康检查要一起成立,任何一环是单点都不算真正的高可用。