Appearance
控制平面高可用
单控制平面宕机后,kubectl 连不上、新 Pod 无法调度、变更无法提交——虽然已有 Pod 可能还在跑,但集群已经不可管理了。生产集群的高可用控制平面需要四个层面同时成立:API Server 入口、多控制平面节点、etcd quorum 和证书配置。任何一环是单点都不算真正的高可用。
四层结构
| 层次 | 解决的问题 |
|---|---|
| API Server 入口 | 给 kubectl、kubelet、控制器提供稳定地址,单个节点 IP 挂掉不影响访问 |
| 多控制平面节点 | 多个 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 etcd | etcd 和控制平面跑在同一批节点 | 机器少,部署简单 | 控制平面节点压力集中 |
| external etcd | etcd 单独一组节点 | 隔离好,故障域清楚 | 机器更多,证书和运维更复杂 |
中小规模自建集群常用 stacked etcd。规模大、控制平面压力高、对 etcd 有单独运维要求时用 external。普通机房环境用三控制平面 stacked etcd,把 etcd 磁盘、备份和告警做好就够。
API Server 高可用入口
controlPlaneEndpoint 是 kubeadm 高可用的核心配置——它会写进所有 kubeconfig 和节点连接地址。入口方案:
| 方案 | 说明 |
|---|---|
| HAProxy + Keepalived | 裸机常见,VIP 漂移,HAProxy 四层转发到多个 API Server |
| kube-vip | 以静态 Pod 提供 VIP,K8s 场景集成度更高 |
| 云负载均衡 | 云上集群直接用 SLB/ELB/NLB |
| 硬件负载均衡 | 已有设备时使用 |
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 checkKeepalived 提供 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"
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: systemdbash
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
quorum 是“超过半数成员同意”的意思。etcd 用 Raft 保存控制平面状态,写入一条数据时,不是 leader 自己写完就算成功,而是要复制给多数成员。这样 leader 挂掉后,新 leader 仍然能从多数成员里拿到已经确认过的数据。
三成员 etcd 最常见。超过半数存活才能写入:
| etcd 成员数 | 可容忍故障数 | 说明 |
|---|---|---|
| 1 | 0 | 实验环境 |
| 3 | 1 | 常见生产最小规模 |
| 5 | 2 | 更高容错,但写入延迟和维护成本更高 |
3 个成员需要 2 个成员存活,5 个成员需要 3 个成员存活。成员数量通常用奇数,因为 2 个成员仍然需要 2 个都活着才能满足多数派,容错能力没有比单成员强多少;4 个成员需要 3 个存活,比 3 个成员同样只能坏 1 个,但多了一份复制和维护成本。
查看成员:
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成员越多,写入需要复制到更多节点,网络和磁盘延迟对控制平面的影响更明显。多数普通集群三成员够用。
验证高可用
入口可访问:
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观察——kubectl 通过 VIP 仍然能访问其他 API Server:
bash
kubectl get nodes
kubectl get pods -A
curl -k https://192.168.10.100:6443/readyz只停一个控制平面节点时,kubectl 仍可用,但该节点上的 etcd 成员如果跟着停了、quorum 还在,集群写入不受影响。业务 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 偶发超时 | 负载均衡后端有坏节点 | 健康检查和后端列表 |