Appearance
控制平面高可用
生产 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 etcd | etcd 和控制平面组件跑在同一批节点 | 机器少,部署简单 | 控制平面节点压力集中 |
| external etcd | etcd 单独一组节点 | 隔离好,故障域清楚 | 机器更多,证书和运维更复杂 |
中小规模自建集群常用 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 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" # 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: 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
三成员 etcd 最常见。超过半数成员存活才能正常写入:
| etcd 成员数 | 可容忍故障数 | 说明 |
|---|---|---|
| 1 | 0 | 实验环境 |
| 3 | 1 | 常见生产最小规模 |
| 5 | 2 | 更高容错,但写入延迟和维护成本更高 |
查看成员:
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.keyetcd 不是越多越好。成员越多,写入需要复制到更多节点,网络和磁盘延迟对控制平面的影响更明显。多数普通集群三成员已经够用。
验证高可用
验证 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、证书、备份、负载均衡健康检查要一起成立,任何一环是单点都不算真正的高可用。