☰
HAProxy+KeepAlived构建K8s高可用集群入口实战指南
2026/10/19 14:55:10 网站建设 项目流程

1. 架构思路:为什么偏偏是 haproxy + keepalived

做过生产级 Kubernetes 集群的人基本都绕不开一个问题:API Server 的入口到底怎么高可用。很多人一开始会用 Nginx 做反代,后端挂几个 master 节点,测下来发现单点还是没解决。因为 Nginx 本身挂在那里,如果这台机器挂了,整个集群入口全断,kubectl 和 kubelet 全都连不上,这比某个 worker 挂了严重得多。

所以我个人在构建高可用 K8s 集群时,最稳的组合就是 HAProxy + KeepAlived。一个负责四层负载均衡,一个负责 VIP 漂移,两者配合把 API Server 入口变成一套“永远在干活”的浮动机器。HAProxy 用 TCP 模式转发 6443 端口流量,KeepAlived 用 VRRP 协议抢占一个虚拟 IP,当主负载均衡节点宕机时,备用节点自动顶上,VIP 跟着漂过去,后面所有组件无感知。

从成本角度来说,这套方案不需要额外的硬件负载均衡设备,两台普通的 ECS 或者物理机就能跑,性能足够打满中小型集群的请求量。从维护角度看,HAProxy 配置简单、状态页直观,KeepAlived 规则清晰、故障切换在毫秒级完成,整体学习曲线也不高。

适合谁?只要你的 K8s 集群是自建的,不管是裸金属、虚拟机还是私有云环境,三个 master 或五个 master 的情况下,前端都需要这样一个稳定的入口。如果只是测试环境只有一个 master,那没必要上这整套,跑个单机 HAProxy 就够了。但凡是生产环境,我强烈建议把 haproxy + keepalived 作为标配。

另外要说明的是,这套方案解决的是控制平面的高可用,不影响 Etcd 自身的集群高可用。Etcd 是 K8s 集群的“数据库”,它自己的高可用靠的是 Raft 协议和集群内的多个节点,跟前端入口不是一个层面。文章后面每一步我都会把两个层面的东西区分开来讲,避免混淆。

2. 环境规划与组件原理

2.1 角色分配与网段设计

先说我最近一次实际搭建的配置,大家可以以此为模板调整。我用了 5 台机器,其中 3 台跑 master 节点,2 台专门跑负载均衡组件:

  • 负载均衡节点 1:安装 HAProxy + KeepAlived,角色为 MASTER
  • 负载均衡节点 2:安装 HAProxy + KeepAlived,角色为 BACKUP
  • 3 个 master 节点:安装 kubeadm、kubelet、kubectl 以及 etcd 成员

这里关键点在于负载均衡节点可以是独立的两台机器,也可以复用 master 节点。如果 master 节点是 3 台,完全可以在每台 master 上都装 HAProxy + KeepAlived,一台变成主负载均衡,另外两台变成备用,这样可以省两台机器。但我不太推荐在 master 上复用,原因是 master 本身承载着控制平面的压力,如果再跑一层负载均衡,遇到恶劣的故障场景会互相影响。而且 keepalived 的 VRRP 报文和 master 上的各种服务放在一起,排查问题时会多很多干扰项。有钱上独立两台机器最省心,预算紧张再考虑复用。

网段规划上有一个容易忽略的点:VIP 要和负载均衡节点处在同一个二层网络内。KeepAlived 的 VIP 漂移本质上是发送免费 ARP 通告,让交换机把自己的 MAC 地址表更新到新的节点。如果 VIP 和节点不在同一个广播域,ARP 不知道该发给谁,漂移就完全失效了。我之前见过有人把 VIP 放在别的网段导致切换后流量完全黑掉,就是这个原因。

IP 规划我建议用静态地址,不要 DHCP,因为 VIP 本身要手动配置在 keepalived.conf 里,节点 IP 如果频繁变动会让 HAProxy 的 server 配置形同虚设。具体示例:

  • 节点 A:10.10.10.11(主负载均衡)
  • 节点 B:10.10.10.12(备负载均衡)
  • VIP:10.10.10.10
  • Master 1:10.10.10.21
  • Master 2:10.10.10.22
  • Master 3:10.10.10.23

提示:实际生产环境请向网络管理员确认二层互通范围,避免 VIP 跨网段问题。

2.2 HAProxy 为什么适合做 K8s 入口

HAProxy 是一个老牌的负载均衡软件,工作在四层和七层都能用。K8s 的 API Server 是 HTTPS 流量,我们在入口做四层 TCP 转发,保留原始 TLS 报文,不在这里终止证书。这样后端的多个 API Server 都可以各自用 Kubelet 的证书和客户端认证,HAProxy 自身不需要持有 K8s 证书,配置面简单很多。

你可能会问,为什么不用 Nginx?Nginx 的 stream 模块也能做 TCP 转发,但 HAProxy 在负载均衡策略和连接处理的效率上更硬核一些。HAProxy 支持多种均衡算法,比如leastconn、source、roundrobin,并且天然支持每台后端 server 的主动健康检查,失败自动摘除,恢复自动加回。Nginx 的 stream 模块健康检查功能相对弱一些,需要商业版本才能做得更细。

API Server 的流量特征是什么?kubectl 命令发出后,控制器和 informer 会建立长连接,ApiServer 需要维持大量长连接不断开。如果负载均衡的算法不合适,比如用 roundrobin,可能导致连接在某台后端上堆积不均衡。所以我通常使用leastconn算法,让新连接尽量发给当前活跃连接数最少的后端,实测下来效果比 roundrobin 平滑很多。

HAProxy 的状态页也是我特别喜欢的点,浏览器打开后能看到每台后端的连接数、健康检查状态、字节吞吐量,排查问题时候一眼定位到哪台 API Server 状态异常。生产环境中我强烈建议开启 stats 页面,并且用 IP 白名单绑死访问来源。

2.3 KeepAlived 的 VRRP 到底在做什么

KeepAlived 的核心是 VRRP 协议,虚拟路由冗余协议。现在很多网络工程师看到这两个词就想到网络设备上的 HSRP,其实原理一致。一组路由器(这里是一组服务器)共享一个虚拟 IP,谁优先级高谁是 MASTER,周期性地向组内发送 VRRP 通告报文,BACKUP 节点收到通告就确认 MASTER 活着,一切正常。

当 MASTER 节点挂掉,BACKUP 节点超过一个时间阈值没收到通告,就开始竞选成为新的 MASTER,并把 VIP 绑定到自己网卡上,同时向交换机发送免费 ARP,告诉交换机“这个 IP 的 MAC 地址变了”。之后的流量就会切换到这新节点,整个过程对客户端完全透明。

需要注意 VRRP 的关键参数是priority和nopreempt。priority 数值越大优先级越高,通常主节点配 100,备节点配 90。如果设置了nopreempt,那么当主节点恢复后不会自动抢回 VIP,这个在生产上有时候是故意的,因为主备来回切换会产生抖动。但是如果你希望 VIP 永远在主节点上,就别开 nopreempt。

另外一个很多人忽略的细节:主节点跟备节点的 preempt 行为默认是开启的,意味着只要主节点恢复,VIP 立刻抢回来。这样做的好处是流量始终由主节点承载,坏处是一次切换必然导致 API Server 入口短暂中断,哪怕只有几十毫秒。生产上建议根据业务容忍度来决定是否保留抢占。

3. 配置实操:从安装到验证

3.1 基础环境与软件版本

我这次的搭建环境是 CentOS 7.9,Kubernetes 用的 1.26 版本。HAProxy 直接用的系统源里的 1.8 版本,KeepAlived 用的 1.3.5。这两个版本都比较老,但胜在稳定,生产环境里我习惯了跑系统自带的版本,不追求最新,因为操作系统的包管理器会自动处理依赖。

第一步,两个负载均衡节点上安装软件:

yum install -y haproxy keepalived

安装完成后先别急着改配置,确认一个系统层面的事:把内核参数net.ipv4.ip_nonlocal_bind打开。这个参数的作用是允许 KeepAlived 在 VIP 还没绑定到网卡上的时候,其他程序先对这个地址做 bind。特别是在 KeepAlived 启动后、VIP 尚未漂移过来的空窗期,如果 HAProxy 已经监听 0.0.0.0:6443,那没问题;但如果你监听了 VIP 地址,就必须开这个内核参数,否则 HAProxy 启动会直接报错地址不可用。

echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf sysctl -p

顺手把防火墙和 SELinux 检查一遍。KeepAlived 的 VRRP 协议使用多播地址 224.0.0.18,如果防火墙挡住了,KeepAlived 之间看不到对方的健康状态,会同时认为自己是 MASTER,这就是脑裂的开端。我通常在测试阶段直接关闭防火墙跟 SELinux:

systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

生产环境不允许关,那就放行必要端口,主机上防火墙放通 6443、10255,以及 VRRP 用的多播或单播端口。

3.2 HAProxy 配置解构

HAProxy 的核心配置在/etc/haproxy/haproxy.cfg。这里的配置分三段:global、defaults、listen。我的完整配置如下:

global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /var/lib/haproxy/stats mode 600 level admin stats timeout 30s user haproxy group haproxy daemon defaults log global mode tcp option tcplog option dontlognull retries 3 timeout connect 5s timeout client 30s timeout server 30s listen k8s-api-server bind 0.0.0.0:6443 mode tcp balance leastconn server master1 10.10.10.21:6443 check inter 3s fall 3 rise 2 server master2 10.10.10.22:6443 check inter 3s check fall 3 rise 2 server master3 10.10.10.23:6443 check inter 3s check fall 3 rise 2

逐个参数解释一下,方便大家理解我为什么这么选:

bind 0.0.0.0:6443表示监听所有网卡地址的 6443 端口。这样当 VIP 绑到这台机器上时,VIP 的 6443 也能正常进来。如果你 bind 指定到 VIP 地址,就要注意上面提到的内核参数问题。

mode tcp很关键,这是四层转发模式。K8s 的 API Server 走的是 TLS,四层模式直接把 TCP 包原样透传,不做 TLS 解密。这保证后端的 kubelet 和 controller-manager 能直接用自己配置的证书完成双向认证,负载均衡这层只是个纯管道。

balance leastconn是我个人偏好。生产环境里 API Server 之间存在连接分布不均的情况,有些组件会保持超级长的连接,leastconn 能把新连接导向连接数较少的后端,避免某一台 master 压力过大。

健康检查参数inter 3s fall 3 rise 2意思是每 3 秒探测一次后端,连续失败 3 次标记为宕机,连续成功 2 次标记为恢复。这个频率对 API Server 来说足够快,又能避免抖动导致频繁切换。

配置完成后启动 HAProxy:

systemctl start haproxy systemctl enable haproxy systemctl status haproxy

可以确认一下 haproxy 的 socket 是否正常监听:

ss -ltn | grep 6443

正常情况下应该看到0.0.0.0:6443处于 LISTEN 状态。

3.3 KeepAlived 配置细节

KeepAlived 的配置在/etc/keepalived/keepalived.conf。主节点和备节点只有优先级和角色标识不同,其他配置基本一致。我的主节点配置如下:

global_defs { router_id LVS_K8S_MASTER vrrp_skip_check_adv_addr vrrp_strict } vrrp_script check_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 weight -20 fall 3 rise 2 } vrrp_instance VI_K8S { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass K8s_HA_2024 } track_script { check_haproxy } virtual_ipaddress { 10.10.10.10/24 dev ens33 } }

备节点配置几乎相同,只需改两处:state BACKUP和priority 90。另外router_id可以改成 LVS_K8S_BACKUP。

重点讲讲vrrp_script部分。这个脚本是防止“故障但不切换”的关键。默认情况下 KeepAlived 只检查节点本身死活,只要 KeepAlived 进程还活着,主节点即使 HAProxy 已经挂了,也不会把 VIP 让出来,整个集群入口就断了。所以我写了一个脚本,探测 HAProxy 进程是否健康,如果宕掉,weight -20直接降低这台节点 20 的优先级,让备节点有机会上位。

脚本内容如下:

#!/bin/bash if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then exit 1 else exit 0 fi

这个脚本本质上是检查进程存在性,更严格的还可以检查端口,比如用netstat -ltnp | grep 6443,但进程检查在生产上已经够用。HAProxy 挂了,进程肯定没了;如果端口起不来,进程也会退出,所以两者结果基本一致。

写完之后赋权:

chmod +x /etc/keepalived/check_haproxy.sh

启动 KeepAlived:

systemctl start keepalived systemctl enable keepalived

启动后先检查 VIP 是否漂移到了主节点上。在主节点执行:

ip addr show ens33

正常输出里能看到 ens33 上多了一个10.10.10.10/24的地址,scope global。到备节点执行同样命令,应该看不到这个 VIP。

验证 VRRP 状态可以用:

systemctl status keepalived journalctl -u keepalived -f

主节点日志会显示Entering MASTER state,备节点显示Entering BACKUP state。

3.4 把 VIP 配置进 K8s 集群

负载均衡这层配置完了,得让 K8s 所有组件都认这个 VIP。

首先,三个 master 节点上 kubelet 的配置里需要指向 VIP。初始化集群时,kubeadm 配置文件中的controlPlaneEndpoint要填:

apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.26.0 controlPlaneEndpoint: "10.10.10.10:6443" apiServer: certSANs: - "10.10.10.10" - "10.10.10.21" - "10.10.10.22" - "10.10.10.23"

certSANs要把 VIP 加进去,因为 API Server 的证书需要包含所有可能访问它的地址,包括虚拟 IP。如果不加,客户端用 VIP 访问时证书校验会失败,kubelet 和 kubectl 都会报证书错误。

已经初始化过的集群改起来麻烦一些,需要改/etc/kubernetes/manifests/kube-apiserver.yaml里的相关参数,然后 kubelet 自动拉起新的 API Server pod。新集群就直接在初始化时配置好,省得后续返工。

工作节点的 kubelet 连接配置同样改到/etc/kubernetes/kubelet.conf,把 server 地址从具体 IP 改成 VIP。这样以后任意 master 挂了,kubelet 都能通过 VIP 找到新的可用 API Server。

3.5 完整验证流程

配置完成后,验证不能只敲一遍ip addr就完事。我一般按照下面的顺序做全量测试:

先测试负载均衡是否正常工作。任意一台能访问 VIP 的机器上执行:

kubectl get nodes --server=https://10.10.10.10:6443

能正常返回节点列表,说明 HAProxy 转发和 API Server 认证都通了。

再测试健康检查摘除能力。手动停掉其中一台 master 的 kubelet:

systemctl stop kubelet

过 5 秒左右,刷新 HAProxy 状态页,能看到对应的后端节点状态从绿色变红色。此时继续用 kubectl 执行命令,返回正常,因为流量被切到了另外两台 master 上。

最后测试 KeepAlived 的 VIP 漂移。在主负载均衡节点上强制关闭 KeepAlived:

systemctl stop keepalived

这时候注意观察备节点,应该在几秒内出现 VIP:

ip addr show ens33

同时用 kubectl 连续执行命令,可能会遇到一两个报错,因为切换过程中 API Server 入口断了极短时间,但对于已经建立的长连接,K8s 组件会自动重连,不需要人工干预。

提示:做故障切换测试前,建议先在非生产环境演练,并且在窗口期操作。切换期间如果集群元数据在写入,可能出现短暂异常,等切换完成后自动恢复。

4. 真实踩坑记录与排查思路

4.1 常见问题速查表

将我在多次搭建中遇到的典型问题和解决思路整理成表,建议收藏起来反复对照:

现象可能原因排查思路
VIP 不漂移VRRP 报文被防火墙拦截或组播不通tcpdump vrrp看报文是否到达备节点,检查防火墙放行
主备同时持有 VIP脑裂,VRRP 通信中断检查 keepalived 日志,核对单播/多播配置
kubectl 连接超时HAProxy 配置了错误的监听端口ss -ltn检查 6443 是否监听,查看 haproxy 日志
API Server 证书报错certSANs 没有加 VIP重新生成证书或使用正确的--cert-san参数
健康检查脚本误报脚本权限不足或路径不对手动执行脚本看返回码,确认 chmod +x
VIP 切换后连接全部重置HAProxy 的 timeout 设置太短调大timeout client和timeout server
KeepAlived 启动失败vrrp_strict模式和系统防火墙冲突检查/var/log/messages,必要时去掉 strict 模式

4.2 脑裂问题:最容易踩的坑

脑裂是 keepalived 部署最常见的高危故障。简单说,就是主备之间 VRRP 通信中断,两台机器都认为自己是 MASTER,都绑定了同一个 VIP。此时客户端访问 VIP 会随机到达其中一台,流量完全不可控,集群状态混乱。

造成脑裂的场景通常是网络问题:主节点和备节点之间的 UDP 224.0.0.18 报文被防火墙悄然丢弃,或者机房网络隔离导致组播失效。另外一个场景不太容易注意到,就是virtual_router_id冲突。如果同一网段里还有其他 keepalived 组用了相同的 ID,VRRP 报文互相干扰,也会触发异常。

规避脑裂我有几个习惯,第一个是在两个节点之间配置单播 VRRP,而不是依赖组播。keepalived 新版支持unicast_peer参数,我可以直接把对端 IP 写进去:

vrrp_instance VI_K8S { state MASTER interface ens33 virtual_router_id 51 priority 100 unicast_src_ip 10.10.10.11 unicast_peer { 10.10.10.12 } }

单播模式不依赖组播,在网络环境复杂的机房更稳。

第二个习惯是在脚本里增加仲裁逻辑。条件允许的话,可以定期检查对端是否存活,比如 ping 对端 IP,ping 不通但自己 VIP 还在,就主动把 keepalived 停掉,避免双主。这个逻辑我用过几次,效果很好,但需要注意脚本复杂度也别太高,否则自身变成故障源。

4.3 健康检查脚本的几个细节

check_haproxy.sh虽然只有几行,但里面有几个细节值得琢磨。

第一点是执行频率。interval 2表示每 2 秒跑一次脚本,weight -20表示脚本失败时降低 20 点优先级。主备 priority 差值通常是 10,脚本失败降 20,足够让备节点超过主节点。但是要注意,如果脚本执行开销太大,高频跑会消耗 CPU。这里只是 ps 查进程,开销忽略不计。

第二点是脚本必须给 root 执行权限,因为 keepalived 在 vrrp_script 里默认是用 root 身份调用脚本,但如果脚本里用了 sudo 之类的方式,反而会出各种乱七八糟的问题。我前面配置的路径是/etc/keepalived/check_haproxy.sh,确保 keepalived 用户能读能执行。

第三点是脚本里的探测对象。如果只检测进程存在性,可能探测不出“进程在但服务端口不响应”的假死情况。更严格的检查可以写成这样:

#!/bin/bash if /usr/bin/curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:6443/healthz --connect-timeout 3 --max-time 5 | grep -q 200; then exit 0 else exit 1 fi

这个方案更贴近真实可用性,因为 API Server 的/healthz端点一旦返回非 200 就说明服务异常。但要注意,curl 请求本身就有一层 TLS 握手和认证成本,如果频繁调用会占用 API Server 的资源。我建议在生产中可以用 HTTP 探测,但要适当拉长探测间隔到 5 到 10 秒,降低对 API Server 的额外负载。

4.4 HAProxy 日志与排错技巧

HAProxy 的日志默认通过 rsyslog 写入/var/log/messages。如果想要更独立的日志管理,可以在 rsyslog 配置里单独分文件。我在/etc/rsyslog.d/haproxy.conf里加了一段:

local0.* /var/log/haproxy.log

然后重启 rsyslog 和 haproxy:

systemctl restart rsyslog systemctl restart haproxy

排查 HAProxy 问题的时候,tail -f /var/log/haproxy.log是最直接的手段。日志会把每一条连接记录下来,包括来源 IP、后端节点、状态码。比如某个客户端反复连接超时,日志里会显示后端的 connection refused,这时第一反应就是看对应 master 的 API Server 是否还活着。

HAProxy 状态页也是排查利器。我在配置里加了 stats 监听:

listen stats bind 127.0.0.1:9999 mode http stats enable stats uri /stats stats refresh 5s

通过curl http://127.0.0.1:9999/stats就能看到每台后端的状态,不用每次登录服务器看配置文件。如果想让状态页通过局域网看,把 bind 改成内网地址并加stats auth账号密码,不要裸奔在公网。

4.5 API Server 流量不均的优化经验

balance leastconn虽然比我用过的 roundrobin 好,但在某些特殊场景下仍然会有流量倾斜。比如 kubelet 和 controller-manager 各自建立长连接,某些组件的连接特别长,leastconn可能会把新连接疯狂分发到相对空闲的某台机器上,导致那台机器瞬间涨高。

解决办法有两个。第一,给每台后端服务器设置weight参数,让机器性能强的多接收流量:

server master1 10.10.10.21:6443 check weight 3 server master2 10.10.10.22:6443 check weight 3 server master3 10.10.10.23:6443 check weight 2

性能弱的降低权重,分摊的流量就少一点。第二,可以在 haproxy 配里加option tcpka开启 TCP keepalive,让长时间空闲的连接主动断开,避免无效连接长时间占用后端资源。

我个人在生产环境通常两种方案一起用,效果明显改善。

5. 生产环境必须注意的细节

5.1 配置变更与回滚流程

HAProxy 和 KeepAlived 的配置变更,一定要走规范的流程。我在生产上改 haproxy 配置时,编译检查完先做语法测试:

haproxy -f /etc/haproxy/haproxy.cfg -c

这个命令不启动进程,只检查配置语法。KeepAlived 也有类似方式:

keepalived -t -f /etc/keepalived/keepalived.conf

配置检查通过后,重载服务时不要用systemctl restart,因为 restart 会打断当前所有连接,生产上会造成 API Server 入口瞬时中断。HAProxy 支持优雅重载:

systemctl reload haproxy

或直接发给 HAProxy 主进程 SIGHUP 信号:

kill -HUP $(cat /var/run/haproxy.pid)

这个过程会先起一个新进程,等旧进程的连接全部结束后再回收旧进程,真正做到无缝切换。

回滚操作也同样简单,把配置文件恢复到上一个版本,再 reload 一次就完成。所以我强烈建议在修改配置前先cp haproxy.cfg haproxy.cfg.bak,回滚时一秒搞定。

5.2 日志和监控联动

只搭完服务不接入监控,等于埋了一颗雷。HAProxy 状态页数据可以被 Prometheus 抓取,KeepAlived 的日志也能通过 node_exporter 的 textfile collector 上报。我习惯的做法是:

  • HAProxy 的 stats 页面绑定内网地址,配好 basic auth,让 Prometheus 通过 haproxy_exporter 采集连接数、会话数、健康检查状态。
  • KeepAlived 状态用 shell 脚本把 VRRP 当前状态写入一个文本文件,再让 node_exporter 读取并暴露指标。这样 Grafana 面板上能直接看到哪台是 MASTER、VIP 在哪台机器。

实践中最有价值的监控指标有三个:VIP 的当前持有者、HAProxy 后端每台 API Server 的健康状态、以及 API Server 的请求延迟。这三个指标能覆盖绝大多数控制平面高可用问题。

5.3 升级路径与维护窗口

软件版本升级上,不要随便动。我的原则是:如果不是安全漏洞,不升 keepalived 和 haproxy 的大版本。底层系统自带的版本经过了大量生产验证,稳定性最重要。真要升级,先在负载均衡备节点上升级,确认一切正常后手动切换 VIP 到新节点,再升级另一台。整个过程要求备节点先更新,主节点保持旧版本,切换后新版本承载流量,然后再对旧节点升级。

维护窗口选择也很重要。我一般选在业务低峰期做 VIP 切换操作,虽然切换是毫秒级,但 kubelet 和 controller-manager 的重连需要几秒钟的时间,这段时间如果有大量控制器调度任务在跑,可能出现短暂的资源竞争。部署敏感业务的同学务必注意。

6. 从零到一的完整复现清单

最后整理一份可以直接照做的行动清单,帮大家把前面的内容串起来。这套清单是我多次搭建生产集群后总结出的最佳顺序,按顺序执行能少走很多弯路。

  1. 网络规划:确认两台负载均衡节点和三个 master 节点二层互通,规划好 VIP。
  2. 安装软件:两台负载均衡节点装 haproxy 和 keepalived。
  3. 打开内核参数:net.ipv4.ip_nonlocal_bind=1。
  4. 配置 HAProxy:注意mode tcp、balance leastconn、健康检查参数。
  5. 启动并验证 HAProxy:用ss -ltn确认 6443 监听。
  6. 配置 KeepAlived:主节点 priority 100、备节点 90,配置健康检查脚本。
  7. 启动并验证 KeepAlived:主节点能看到 VIP,备节点没有 VIP。
  8. 模拟故障:停掉主节点的 keepalived,确认 VIP 漂移到备节点。
  9. 初始化 K8s 集群:controlPlaneEndpoint填 VIP,certSANs 加上 VIP。
  10. 配置 worker 节点的 kubelet 和 kubeconfig,确保所有通信地址都是 VIP。
  11. 全量验证:kubectl 操作、健康检查摘除、VIP 切换三项都要测。

这套组合到目前为止,我在多个环境里搭过:三台 master 的测试集群、五台 master 的私有云生产环境都有使用。每次出问题的不是 HAProxy 或 KeepAlived 本身的 bug,而是网络层面的互通性和配置细节。只要把 VRRP 的报文通路打通,这层高可用就非常可靠。

要说运维中最深刻的体会,就是别小看那台看似“只转发流量”的 HAProxy 节点。它背后承载的是整个集群控制平面的命脉,值得你花时间把配置打磨好,把监控盯紧,把演练做全。这些在平时看起来不起眼的小事,在真正宕机的那天都会救你一命。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询