高可用 - Keepalived 解析
官网:https://www.keepalived.org/
HA 集群能解决哪些问题?
当计划使用 HA 集群时,有一个重要问题需要回答:服务放到 HA 集群中,可用性是否会增加?
回答这个问题,需要弄清楚服务的能力以及客户端如何配置。
取决于具体方案。例如 DNS 和 LDAP 自带故障转移或负载均衡,再放入 HA 集群往往收益不大。DNS/LDAP 可使用多实例、master/slave 或多 master,并在多服务器间同步数据;客户端也可配置多个服务器地址,本身已具备冗余,因此再放入 HA 集群通常不会明显增加可用性。
未自带 Failover 或 LB 的服务,配置为 HA 集群则收益明显。例如在 OpenStack 方案中,将 RabbitMQ、Galera 等放入 HA 集群会带来很大好处。
但并不是所有可用性问题都能靠 HA 集群解决:
- 若应用程序因 bug 导致 crash,即使配置了 HA,应用仍会 crash;故障会漂移到其他节点,但其他节点运行相同版本,同样可能 crash。
- HA 集群不提供端到端冗余。集群本身正常,若网络架构存在单点导致集群不可达,客户端仍无法访问。需整体设计,避免集群内外任何组件成为单点。
Keepalived 介绍
Keepalived 是用 C 语言编写的路由软件,主要目标是为 Linux 及基于 Linux 的基础设施提供简单而健壮的负载均衡与高可用能力。
Keepalived 起初为 LVS 设计,用于监控集群中各服务节点状态。它依据 TCP/IP 参考模型第三、四、五层机制检测节点;若某节点异常或故障,Keepalived 会自动将其从集群中剔除,无需人工干预,人工主要负责修复故障节点。
后来 Keepalived 加入 VRRP 功能。VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)用于解决静态路由单点故障,实现网络不间断运行。因此 Keepalived 同时具备:服务健康检测与故障隔离、HA 集群(VRRP) 两类能力。
VRRP 协议
现实中,主机间通信多依赖静态路由或默认网关;网关路由器一旦故障,通信即中断,路由器成为单点瓶颈。VRRP 即用于解决该问题。
VRRP 是一种主备模式协议,可在网络故障时透明切换设备,尽量不影响主机间数据通信。
VRRP 可将两台或多台物理路由器虚拟成一台虚拟路由器,通过虚拟 IP(VIP,可多个)对外提供服务。虚拟路由器内部多台物理路由器协同工作,同一时刻仅一台作为主路由器(Master)对外服务。Master 通常由选举产生,持有 VIP,负责 ARP、ICMP 转发等;其余为 BACKUP,不持有对外 VIP,主要接收 Master 的 VRRP 通告。Master 故障时,BACKUP 重新选举,新的 Master 接管服务,对用户尽量透明。
每个虚拟路由器有唯一标识 VRID;一个 VRID 与一组 IP 构成一个虚拟路由器。VRRP 报文通过 IP 多播发送。Master 持续发送 VRRP 报文,BACKUP 接收并监控 Master;一般 BACKUP 不会抢占,除非其 priority 更高。Master 不可用时,BACKUP 收不到通告即认定 Master 故障,多台 BACKUP 选举,priority 最高者成为新 Master,切换速度很快,从而保证服务持续可用。
工作原理
Keepalived 通过 VRRP 实现高可用,并可监控集群节点运行状态、做故障隔离。其工作涉及 TCP/IP 网络层、传输层、应用层。
网络层
涉及 IP、ICMP、ARP、RARP 等。常见方式是通过 ICMP 向集群各节点发包(类似 ping);无响应则判定节点故障并剔除。
传输层
涉及 TCP、UDP。通过 TCP 端口探测判断节点端口是否正常(如 Web 的 80、SSH 的 22);无响应则剔除对应节点。
应用层
可结合 FTP、SMTP、DNS 等高层协议,或通过自定义脚本检测进程/服务;结果与预期不符则剔除节点。
脑裂(Split-Brain)
在 Keepalived 高可用集群中,脑裂指主从(或双主)节点因通信中断,各自认为对方故障,同时争抢资源(如 VIP),导致集群状态混乱。
脑裂产生的原因
核心是心跳失败但节点实际仍存活,常见原因:
- 网络问题:心跳专线、交换机故障、断网或高延迟。
- 防火墙规则 :节点间 VRRP 协议(默认 UDP 112) 被屏蔽。
- 资源耗尽:CPU/内存/负载过高,无法响应心跳。
- 配置错误 :
vrrp_instance的state、priority、authentication等不一致,无法正常协商。
脑裂的危害
- 双节点同时持有 VIP,客户端请求混乱。
- 若管理数据库、存储等,可能双写、数据不一致。
- 集群失去高可用意义,甚至因资源竞争导致服务崩溃。
如何避免脑裂?
通过 多重检测 与 资源隔离 预防:
增加心跳检测线路
除主网络外,增加备用线路(独立网卡、交叉网线等)。在 keepalived.conf 中指定多网卡检测:
conf
vrrp_instance VI_1 {
state MASTER
interface eth0 # 主网卡
virtual_router_id 51
priority 100
advert_int 1
track_interface {
eth0
eth1 # 备用网卡
}
}
启用 VRRP 认证
conf
vrrp_instance VI_1 {
# ... 其他配置
authentication {
auth_type PASS # PASS 或 AH
auth_pass 123456 # 所有节点必须一致
}
}
配置防火墙规则
bash
# 允许 VRRP 协议(CentOS 示例)
firewall-cmd --add-protocol=vrrp --permanent
firewall-cmd --reload
部署 fence 或 notify 脚本
使用 fence (如 fence_virsh、fence_ipmilan)或脚本,检测到脑裂时隔离异常节点。
conf
vrrp_instance VI_1 {
notify_master "/etc/keepalived/check_split_brain.sh master"
notify_backup "/etc/keepalived/check_split_brain.sh backup"
}
脚本可通过 ping、端口检测确认对端;若脑裂可对异常节点执行 kill 或 reboot(需严格评估风险)。
降低脑裂影响范围
- 数据库:主从 + 读写分离,避免双写。
- 存储:分布式锁(如 Redis)控制独占。
- 仅在确认集群状态正常时对外提供 VIP 服务。
监控与告警
通过 Zabbix、Prometheus 等监控 Keepalived 状态、vrrp_script 检测;发现双主等情况及时告警。
总结
脑裂本质是通信失效与状态判断不一致 。预防核心是 「多重检测 + 自动隔离」:多线路心跳、认证降低误判;脚本与 fence 在脑裂时快速隔离;配合监控及时干预。
Keepalived 高可用技术实践
网络拓扑
| 主机名 | IP 地址 | 服务器角色 |
|---|---|---|
| client2.rich.cloud | 10.1.1.21 | 客户端 |
| client1.rich.cloud | 10.1.8.21 | 客户端 |
| router.rich.cloud | 10.1.1.20, 10.1.8.20 | 路由器 |
| web1.rich.cloud | 10.1.8.11 | Web 服务器 |
| web2.rich.cloud | 10.1.8.12 | Web 服务器 |
网络说明:
- 所有主机:第一块网卡
ens33,第二块网卡ens192。 - 默认第一块网卡 NAT,第二块 Host-only。
- 网关:
10.1.1.0/24网段网关为10.1.1.20;10.1.8.0/24网段网关为10.1.8.20。
基础配置
网关配置命令参考:
bash
# 10.1.1.0/24 网段网关为 10.1.1.20
nmcli connection modify ens33 ipv4.gateway 10.1.1.20
nmcli connection up ens33
# 10.1.8.0/24 网段网关为 10.1.8.20
nmcli connection modify ens33 ipv4.gateway 10.1.8.20
nmcli connection up ens33
配置 router
bash
# 开启 firewalld,配置 SNAT,使不同网段经路由器访问公网
systemctl enable firewalld.service --now
firewall-cmd --add-masquerade --permanent
firewall-cmd --reload
# 开启 IP 转发
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
# 或:sed -i 's/ip_forward=0/ip_forward=1/g' /etc/sysctl.conf
sysctl -p
配置 Web
bash
yum install -y nginx
echo "Welcome to $(hostname)" > /usr/share/nginx/html/index.html
systemctl enable nginx.service --now
访问后端 Nginx:
bash
[root@client1 ~]# curl 10.1.8.11
Welcome to web1.rich.cloud
[root@client1 ~]# curl 10.1.8.12
Welcome to web2.rich.cloud
配置 Keepalived
配置 web2(BACKUP)
bash
yum install -y keepalived
cp /etc/keepalived/keepalived.conf{,.ori}
vim /etc/keepalived/keepalived.conf
conf
! Configuration File for keepalived
global_defs {
router_id web2
}
vrrp_instance nginx {
state BACKUP
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass Rich@123
}
virtual_ipaddress {
10.1.8.100
}
}
参数说明:
| 参数 | 说明 |
|---|---|
router_id |
路由器名称,每节点不同 |
state |
MASTER / BACKUP |
interface |
绑定 VIP 的网卡 |
virtual_router_id |
虚拟路由器 ID,1--255,集群内相同 |
priority |
优先级,越大越优先 |
authentication |
VRRP 心跳认证 |
virtual_ipaddress |
VIP 地址 |
bash
# 查看 IP
[root@web2 ~]# ip -br a show ens33
ens33 UP 10.1.8.12/24 10.1.8.100/24 ...
# 启动服务
[root@web2 ~]# systemctl enable keepalived.service --now
配置 web1(MASTER)
bash
yum install -y keepalived
cp /etc/keepalived/keepalived.conf{,.ori}
vim /etc/keepalived/keepalived.conf
conf
! Configuration File for keepalived
global_defs {
router_id web1
}
vrrp_instance nginx {
state MASTER
interface ens33
virtual_router_id 51
priority 110 # MASTER 优先级应高于 BACKUP
advert_int 1
authentication {
auth_type PASS
auth_pass Rich@123
}
virtual_ipaddress {
10.1.8.100
}
}
bash
systemctl enable keepalived.service --now
[root@web1 ~]# ip -br a show ens33
ens33 UP 10.1.8.11/24 10.1.8.100/24 ...
[root@web2 ~]# ip -br a show ens33
ens33 UP 10.1.8.12/24
高可用验证
bash
[root@client2 ~]# curl 10.1.8.100
Welcome to web1.rich.cloud
# 关闭 web1 的 keepalived
[root@web1 ~]# systemctl stop keepalived.service
[root@client1 ~]# curl 10.1.8.100
Welcome to web2.rich.cloud
# 再次启动 web1
[root@web1 ~]# systemctl start keepalived.service
[root@client1 ~]# curl 10.1.8.100
Welcome to web1.rich.cloud
keepalived 配置文件说明
配置文件:/etc/keepalived/keepalived.conf,主要包括三部分:
- GLOBAL:全局配置
- VRRPD:VRRP 协议配置
- LVS:LVS 服务管理配置
配置示例
conf
! Configuration File for keepalived
# 全局配置
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
# VRRP 协议配置
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16
192.168.200.17
192.168.200.18
}
}
# LVS 服务管理配置
virtual_server 192.168.200.100 443 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.201.100 443 {
weight 1
}
}
详细信息参考:keepalived.conf(5) 手册页。
Keepalived 日志
在 web1、web2 节点执行:
bash
# 配置 rsyslog
vim /etc/rsyslog.d/keepalived.conf
# 添加:local0.* /var/log/keepalived.log
vim /etc/sysconfig/keepalived
# 将 KEEPALIVED_OPTIONS="-D"
# 改为:KEEPALIVED_OPTIONS="-D -d -S 0"
systemctl restart rsyslog
systemctl restart keepalived.service
tail -f /var/log/keepalived.log
Keepalived 心跳(组播源 IP)
参数 mcast_src_ip 示例:
conf
global_defs {
router_id Cluster1
}
vrrp_instance Nginx {
state MASTER
interface ens36
mcast_src_ip 20.0.0.11
virtual_router_id 51
priority 110
advert_int 1
authentication {
auth_type PASS
auth_pass rich@123
}
virtual_ipaddress {
10.1.1.10/24
}
}
Keepalived 高可用技术小结
Keepalived 基于 VRRP 实现高可用,核心通过 VIP 提供统一访问入口,支持主备、双主等部署模式。通过 priority 确定主节点;主节点故障时备节点自动接管 VIP 与服务,实现较快切换;还可配合健康检查脚本监测后端服务。常与 LVS、Nginx 等负载均衡组件联动,解决单点故障,为 Web、数据库等构建稳定的高可用架构。