上一章我们介绍可机器的基础设置,本章我们来介绍配置K8S的高可用特性,在本章你将了解到 RKE2 的“自动故障转移”机制是什么?HAProxy + Keepalived 的作用是什么?以及如何配置HAProxy + Keepalived。
在 RKE2 高可用集群 中,虽然 RKE2 本身带有“自动故障转移”机制(例如 Kubernetes 的 kubectl 客户端会按顺序尝试访问多个 API Server 地址),但这与 HAProxy + Keepalived 的作用 是不同维度的功能补充。
1. RKE2 的“自动故障转移”机制是什么?
RKE2 的自动故障转移(failover)是客户端层面的冗余:
- Kubernetes 客户端(如
kubectl
、kubelet
)会读取kubeconfig
文件中的多个 API Server 地址,并按顺序尝试连接。 - 如果某个 API Server 不可用(例如节点宕机),客户端会自动切换到下一个地址。
- RKE2 会将所有 Control Plane 节点的 API Server 地址写入
kubeconfig
文件(例如/etc/rancher/rke2/rke2.yaml
)。
clusters:
- name: default
cluster:
server: https://10.88.88.71:6443
server: https://10.88.88.72:6443
server: https://10.88.88.73:6443
insecure-skip-tls-verify: true
优点:
- 简单:无需额外部署负载均衡器或虚拟 IP 。
- 客户端自动尝试多个 API Server 地址,保证连通性。
- 适用于 小规模集群或测试环境。
缺点:
- 客户端需要维护多个 API Server 地址(通常位于
kubeconfig
文件中)。 - 故障转移延迟较高(客户端会按顺序逐个尝试地址)。
- 无法提供负载均衡(如轮询、权重分配、健康检查等)。
- 客户端配置复杂性:每次新增或删除 Control Plane 节点时,需要更新
kubeconfig
文件。
2. HAProxy + Keepalived 的作用
HAProxy 和 Keepalived 提供的是网络层和服务发现层面的高可用性,与 RKE2 内置的“客户端自动故障转移”是互补的。
(1)HAProxy 的作用
- 负载均衡:
- 支持 TCP/HTTP 层的负载均衡(RKE2 的 API Server 是基于 TCP 的)。
- 支持轮询(round-robin)、加权轮询、最小连接数等策略。
- 健康检查:
- 自动检测后端 API Server 的状态(如端口 6443 是否可用)。
- 如果某个 API Server 节点宕机,HAProxy 会自动将其从负载池中移除,避免流量打到故障节点。
- 集中管理入口:
- 客户端只需配置一个 VIP(虚拟 IP)作为 API Server 入口,无需手动维护多个地址。
(2)Keepalived 的作用
- 虚拟 IP(VIP)管理:
- 提供一个统一的 API Server 入口(例如
192.168.1.200
)。 - 当主节点故障时,VIP 自动漂移到健康的备用节点,实现无缝故障切换。
- 提供一个统一的 API Server 入口(例如
- 主备容灾:
- 通过 VRRP 协议实现主备切换,确保负载均衡本身的高可用。
- 简化客户端配置:
- 所有客户端(如
kubectl
、kubelet
、外部用户)只需访问 VIP,无需关心后端节点。
- 所有客户端(如
3. HAProxy + Keepalived部署
节点 | IP/hostname | 系统 |
VIP(虚拟IP) | 10.88.88.70 | 虚拟IP |
Master1 | 10.88.88.71/k8sm1 | Ubuntu Server 22.04 LTS |
Master2 | 10.88.88.72/k8sm2 | Ubuntu Server 22.04 LTS |
Master3 | 10.88.88.73/k8sm3 | Ubuntu Server 22.04 LTS |
Worker1 | 10.88.88.74/k8sn1 | Ubuntu Server 22.04 LTS |
Worker2 | 10.88.88.75/k8sn2 | Ubuntu Server 22.04 LTS |
ManageNode1 | 10.88.88.76/k8smgt | Ubuntu Server 22.04 LTS |
3.1 安装HAProxy + Keepalived
在三台master上执行安装命令。
apt install haproxy keepalived -y
编辑配置文件
cd /etc/haproxy/
mv haproxy.cfg haproxy.cfg.bak #备份文件,默认的没用了
vim haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
# log 127.0.0.1 local2
log /var/log/haproxy.log local2 # 日志写入到 /var/log/haproxy.log,使用 local2 设施
chroot /var/lib/haproxy # 将 HAProxy 绑定到 chroot 目录
pidfile /var/run/haproxy.pid # 指定进程 ID 文件路径
maxconn 4000 # 最大连接数限制
user haproxy # 使用 haproxy 用户运行
group haproxy # 使用 haproxy 组运行
daemon # 以后台模式运行
# 启用统计信息的 Unix socket
stats socket /var/lib/haproxy/stats # 用于管理命令和监控的 socket 路径
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http # 默认使用 HTTP 模式
log global # 使用全局日志配置
option httplog # 记录 HTTP 请求日志
option dontlognull # 忽略空请求日志
option http-server-close # 关闭服务器端的连接保持(避免资源浪费)
option forwardfor except 127.0.0.0/8 # 设置 X-Forwarded-For 头(排除回环地址)
option redispatch # 当服务器不可用时,重新分配请求到其他服务器
retries 3 # 最大重试连接后端服务器的次数
timeout http-request 10s # HTTP 请求超时时间
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000 # 每个进程最大连接数
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#---------------------------------------------------------------------
frontend rke2-apiserver
mode tcp # 使用 TCP 模式(适合代理 Kubernetes API Server)
bind *:19345 # 监听所有接口的 19345 端口
option tcplog # 记录 TCP 级别的日志
default_backend rke2-apiserver # 指定默认后端为 rke2-apiserver
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend rke2-apiserver
mode tcp # 使用 TCP 模式
option tcplog # 记录 TCP 日志
option tcp-check # 启用 TCP 健康检查
balance roundrobin # 使用轮询负载均衡算法
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server k8sm1 10.88.88.71:9345 check
server k8sm2 10.88.88.72:9345 check
server k8sm3 10.88.88.73:9345 check
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
bind *:1080 # 监听所有接口的 1080 端口
stats auth admin:QingHaoPassword # 访问统计页面的用户名和密码
stats refresh 5s # 页面自动刷新间隔
stats realm HAProxy\ Statistics # 访问认证的 Realm 名
stats uri /admin?stats # 统计页面的访问路径
#19345 是 HAProxy 的前端端口,客户端通过此端口访问 HAProxy 。
#9345 是 HAProxy 后端后端服务器的端口,即 HAProxy 会将流量转发到后端服务器的 9345 端口。
cd /etc/keepalived
mv keepalived.conf keepalived.conf.bak
vim /etc/keepalived/keepalived.conf
global_defs {
script_user root
enable_script_security
}
vrrp_script chk_apiserver {
script "/etc/keepalived/check_apiserver.sh" # 定义脚本路径和名称
interval 5 # 每 5 秒执行一次检测,注意设置间隔太小会有问题
weight -15 # 权重变化
fall 2 # 检测连续2次失败才算失败
rise 1 # 检测1次成功就算成功
}
vrrp_instance VI_1 {
state MASTER # backup节点设为BACKUP, <看情况调整>
interface ens160 # 服务器网卡接口
virtual_router_id 51 # 这个值只要在 keepalived 集群中保持一致即可,默认值是 51
priority 100 #如:master设为 100,备份服务 50,比备份服务器上高就行了,如:master设为 100,备份服务 50
advert_int 1
authentication {
auth_type PASS
auth_pass K8SHA_KA_AUTH #这个值只要在keepalived集群中保持一致即可
}
virtual_ipaddress {
10.88.88.70 # VIP 地址,<看情况调整>
}
track_script {
chk_apiserver
}
}
脚本:check_apiserver.sh
该脚本通过检查 HAProxy 进程是否存在来判断 HAProxy 服务是否正常。如果 HAProxy 进程异常(连续多次检测失败),脚本会主动停止 Keepalived 服务,促使虚拟 IP(VIP)漂移到健康的节点。
为什么需要这个脚本?
VRRP 的局限性:VRRP 本身只能管理 VIP 的分配,无法直接感知 HAProxy 或 API Server 的状态。此脚本通过主动检查 HAProxy 的运行状态,为 VRRP 提供额外的健康检查信息。
直接控制 Keepalived:当 HAProxy 故障时,主动停止 Keepalived 服务,确保 VIP 能够快速漂移到其他节点。
避免“脑裂”:如果 HAProxy 故障后 Keepalived 仍然持有 VIP,会导致流量无法正常转发。通过强制停止 Keepalived,可以快速释放 VIP,避免资源浪费。
vim /etc/keepalived/check_apiserver.sh
#!/bin/bash
err=0
for k in $(seq 1 3)
do
check_code=$(pgrep haproxy)
if [[ $check_code == "" ]]; then
err=$(expr $err + 1)
sleep 1
continue
else
err=0
break
fi
done
if [[ $err != "0" ]]; then
echo "systemctl stop keepalived"
/usr/bin/systemctl stop keepalived
exit 1
else
exit 0
fi
chmod +x /etc/keepalived/check_apiserver.sh #给与脚本权限
启动服务
systemctl enable haproxy
systemctl restart haproxy
systemctl enable keepalived
systemctl restart keepalived
检查IP:
ip addr
#输出
root@k8sm3:/etc/keepalived# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:63:38:36 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.88.88.73/24 brd 10.88.88.255 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe63:3836/64 scope link
valid_lft forever preferred_lft forever
3.2 测试
停止haproxy 服务,然后过10秒再使用ip addr 查看VIP是否还存在,不存在则判定漂移到另外的两个master节点上。
ip addr
#输出
root@k8sm1:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:09:aa:17 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.88.88.71/24 brd 10.88.88.255 scope global ens160
valid_lft forever preferred_lft forever
inet 10.88.88.70/32 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe09:aa17/64 scope link
valid_lft forever preferred_lft forever
service haproxy restart && service keepalived restart #执行后,VIP漂移到其他节点。
ip addr
#输出
root@k8sm1:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:09:aa:17 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.88.88.71/24 brd 10.88.88.255 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe09:aa17/64 scope link
valid_lft forever preferred_lft forever