在两台 CentOS 7 服务器上使用 Keepalived 实现主备容灾(双网卡方案)
一、VRRP 核心原理
Keepalived 基于 VRRP(虚拟路由冗余协议) 工作,其核心机制如下:
- 虚拟路由器:多台物理服务器组成一个虚拟路由器,并共享一个虚拟IP(VIP)
- 主备角色:一台为主(MASTER),负责处理业务;其余为备(BACKUP),随时准备接管
- 心跳机制:主服务器定期发送VRRP通告包,宣告自己存活
- 接管流程:当备服务器在预设时间内未收到心跳,认为主服务器故障,接管VIP继续提供服务
- 优先级仲裁:多个备服务器时,根据配置的优先级(priority)决定谁接管VIP
双网卡方案优势:将业务流量和心跳流量物理隔离,即使业务网络拥堵也不影响心跳检测的稳定性。
二、实现效果
- 无缝切换:主服务器故障时,VIP自动漂移到备服务器,业务零中断,切换时间1-3秒
- 故障检测:可监控服务状态(如HTTP),当服务异常时触发切换,而不仅限于服务器宕机
- 心跳隔离:专用网卡处理VRRP心跳,避免业务流量干扰,提高可靠性
- 自动恢复:主服务器恢复后可自动或手动将VIP切回,根据配置灵活调整
三、环境与网络拓扑
服务器配置:
- 服务器A(主):业务IP 192.168.1.10,心跳IP 10.0.0.1
- 服务器B(备):业务IP 192.168.1.20,心跳IP 10.0.0.2
- 虚拟IP:192.168.1.100(绑定在业务网卡上)
+---------------+ +---------------+
| 服务器A (主) | | 服务器B (备) |
| | | |
| eth0:192.168.1.10 -业务网络- eth0:192.168.1.20|
| VIP:192.168.1.100 | |
| | | |
| eth1:10.0.0.1 ---心跳网络--- eth1:10.0.0.2 |
+---------------+ +---------------+
关键设计:
- 业务网卡(eth0):处理实际业务流量,绑定VIP
- 心跳网卡(eth1):仅用于Keepalived心跳通信,实现物理隔离
四、实现步骤
1. 安装 Keepalived
sudo yum install -y keepalived
2. 配置主服务器(A)
1. 主服务器(A)配置
编辑 /etc/keepalived/keepalived.conf:
1. 全局配置段
global_defs {
router_id MASTER_SERVER # 路由器标识,集群内应唯一
notification_email { # 告警邮件接收地址
admin@example.com
}
notification_email_from keepalived@example.com # 发件人地址
smtp_server 127.0.0.1 # 邮件服务器地址
smtp_connect_timeout 30 # 连接超时时间
script_user root # 脚本执行用户
enable_script_security # 启用脚本安全模式
vrrp_skip_check_adv_addr # 跳过检查通告包源地址
vrrp_strict # 严格遵守VRRP协议
vrrp_garp_interval 1 # GARP报文发送间隔
vrrp_gna_interval 1 # 免费ARP报文发送间隔
log_facility local0 # 使用local0设施记录日志
}
1. 服务健康检查脚本
vrrp_script chk_httpd {
script "/etc/keepalived/check_httpd.sh" # 检查脚本路径
interval 2 # 检查间隔(秒)
weight -5 # 检查失败时的优先级调整值
fall 2 # 连续失败多少次才算真失败
rise 1 # 连续成功多少次才算真成功
user root # 执行用户
timeout 2 # 脚本执行超时时间
}
1. VRRP实例配置
vrrp_instance VI_1 {
state MASTER # 初始状态为MASTER
interface eth0 # 绑定VIP的网卡
virtual_router_id 51 # 虚拟路由器ID,集群内必须相同
priority 100 # 优先级,值越大越优先成为MASTER
advert_int 1 # VRRP通告间隔(秒)
authentication {
auth_type PASS # 认证类型,PASS或AH
auth_pass Ha7kQp9L # 认证密码,集群内必须相同
}
1. 使用单播方式进行VRRP通信(适用于跨VLAN环境)
unicast_src_ip 10.0.0.1 # 本机心跳网卡IP
unicast_peer {
10.0.0.2 # 备服务器心跳网卡IP
}
1. 虚拟IP配置
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip # VIP地址配置及标签
}
1. 健康检查关联
track_script {
chk_httpd # 关联上面定义的检查脚本
}
1. 优先级变动通知脚本(可选)
notify_master "/etc/keepalived/notify_master.sh" # 成为MASTER时执行
notify_backup "/etc/keepalived/notify_backup.sh" # 成为BACKUP时执行
notify_fault "/etc/keepalived/notify_fault.sh" # 发生故障时执行
1. 抢占模式设置
nopreempt # 不启用抢占模式,避免频繁切换
preempt_delay 300 # 抢占延迟(秒,仅在未设置nopreempt时有效)
1. GARP设置
garp_master_delay 1 # 成为MASTER后发送GARP的延迟
garp_master_repeat 3 # GARP报文发送次数
1. 调试日志级别
debug # 启用调试日志
}
2. 备服务器(B)配置
编辑 /etc/keepalived/keepalived.conf:
1. 全局配置段
global_defs {
router_id BACKUP_SERVER # 路由器标识,集群内应唯一
notification_email { # 告警邮件接收地址
admin@example.com
}
notification_email_from keepalived@example.com # 发件人地址
smtp_server 127.0.0.1 # 邮件服务器地址
smtp_connect_timeout 30 # 连接超时时间
script_user root # 脚本执行用户
enable_script_security # 启用脚本安全模式
vrrp_skip_check_adv_addr # 跳过检查通告包源地址
vrrp_strict # 严格遵守VRRP协议
vrrp_garp_interval 1 # GARP报文发送间隔
vrrp_gna_interval 1 # 免费ARP报文发送间隔
log_facility local0 # 使用local0设施记录日志
}
1. 服务健康检查脚本
vrrp_script chk_httpd {
script "/etc/keepalived/check_httpd.sh" # 检查脚本路径
interval 2 # 检查间隔(秒)
weight -5 # 检查失败时的优先级调整值
fall 2 # 连续失败多少次才算真失败
rise 1 # 连续成功多少次才算真成功
user root # 执行用户
timeout 2 # 脚本执行超时时间
}
1. VRRP实例配置
vrrp_instance VI_1 {
state BACKUP # 初始状态为BACKUP
interface eth0 # 绑定VIP的网卡
virtual_router_id 51 # 虚拟路由器ID,集群内必须相同
priority 90 # 优先级,值低于主服务器
advert_int 1 # VRRP通告间隔(秒)
authentication {
auth_type PASS # 认证类型,PASS或AH
auth_pass Ha7kQp9L # 认证密码,集群内必须相同
}
1. 使用单播方式进行VRRP通信(适用于跨VLAN环境)
unicast_src_ip 10.0.0.2 # 本机心跳网卡IP
unicast_peer {
10.0.0.1 # 主服务器心跳网卡IP
}
1. 虚拟IP配置
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip # VIP地址配置及标签
}
1. 健康检查关联
track_script {
chk_httpd # 关联上面定义的检查脚本
}
1. 优先级变动通知脚本(可选)
notify_master "/etc/keepalived/notify_master.sh" # 成为MASTER时执行
notify_backup "/etc/keepalived/notify_backup.sh" # 成为BACKUP时执行
notify_fault "/etc/keepalived/notify_fault.sh" # 发生故障时执行
1. GARP设置
garp_master_delay 1 # 成为MASTER后发送GARP的延迟
garp_master_repeat 3 # GARP报文发送次数
1. 调试日志级别
debug # 启用调试日志
}
3. 健康检查脚本
创建 /etc/keepalived/check_httpd.sh,内容如下:
#!/bin/bash
1. 服务检查脚本 - 监控Apache HTTP服务
1. 返回0表示成功,非0表示失败
1. 记录日志的函数
log_msg() {
local message="$1"
logger -t keepalived_check_httpd "$message"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> /var/log/keepalived_scripts.log
}
1. 检查httpd进程是否运行
if ! pgrep httpd > /dev/null; then
log_msg "HTTP服务未运行,尝试启动..."
systemctl start httpd
sleep 2
1. 再次检查是否成功启动
if ! pgrep httpd > /dev/null; then
log_msg "HTTP服务启动失败,将触发Keepalived切换!"
exit 1
else
log_msg "HTTP服务成功重启"
fi
fi
1. 尝试访问本地web服务
if ! curl -s --max-time 2 http://localhost/ > /dev/null; then
log_msg "无法访问HTTP服务,将触发Keepalived切换!"
exit 2
fi
1. 一切正常
log_msg "HTTP服务运行正常"
exit 0
4. 状态变更通知脚本(可选)
创建主状态通知脚本 /etc/keepalived/notify_master.sh:
#!/bin/bash
1. 当节点成为MASTER时执行的脚本
1. 记录事件
logger -t keepalived "节点已成为MASTER状态,VIP已接管"
1. 发送邮件通知
echo "服务器$(hostname)已成为Keepalived的MASTER节点,接管VIP $(date)" | mail -s "Keepalived: $(hostname) 成为MASTER" admin@example.com
1. 执行其他自定义操作,如启动特定服务等
1. systemctl start some-service
exit 0
创建备状态通知脚本 /etc/keepalived/notify_backup.sh:
#!/bin/bash
1. 当节点成为BACKUP时执行的脚本
1. 记录事件
logger -t keepalived "节点已成为BACKUP状态,VIP已释放"
1. 发送邮件通知
echo "服务器$(hostname)已成为Keepalived的BACKUP节点,释放VIP $(date)" | mail -s "Keepalived: $(hostname) 成为BACKUP" admin@example.com
1. 执行其他自定义操作,如停止特定服务等
1. systemctl stop some-service
exit 0
创建故障通知脚本 /etc/keepalived/notify_fault.sh:
#!/bin/bash
1. 当节点检测到故障时执行的脚本
1. 记录事件
logger -t keepalived "节点检测到故障,可能进入FAULT状态"
1. 发送邮件通知
echo "服务器$(hostname)的Keepalived检测到故障,可能进入FAULT状态 $(date)" | mail -s "Keepalived: $(hostname) 检测到故障" admin@example.com
1. 可以尝试一些故障自修复操作
1. systemctl restart network
exit 0
5. 脚本权限设置
为所有脚本添加执行权限:
chmod +x /etc/keepalived/check_httpd.sh
chmod +x /etc/keepalived/notify_master.sh
chmod +x /etc/keepalived/notify_backup.sh
chmod +x /etc/keepalived/notify_fault.sh
5. 启动服务
两台服务器均执行:
systemctl start keepalived
systemctl enable keepalived
五、工作原理详解
1. 初始状态
- 主服务器启动后,进入MASTER状态,绑定VIP并开始提供服务
- 备服务器启动后,进入BACKUP状态,监听主服务器的VRRP通告
2. 故障检测机制
Keepalived有三种故障检测方式:
- 心跳中断检测:备服务器未收到主服务器VRRP通告
- 服务检测:
track_script检测到本地服务异常 - 接口监控:
track_interface检测到网卡故障
3. 故障转移过程
当主服务器发生故障时:
- 备服务器等待3×
advert_int时间未收到心跳 - 备服务器将自身状态提升为MASTER
- 发送免费ARP(Gratuitous ARP)广播,更新网络中的ARP表
- 在自己的eth0上绑定VIP
- 接管业务流量,整个过程对客户端透明
4. 心跳网络的重要性
- 普通配置:心跳和业务共用一个网卡,业务高峰可能导致心跳丢包,引发误切换
- 双网卡配置:心跳走专用网卡,与业务完全隔离,即使业务网络拥堵,心跳依然稳定
六、防火墙配置
为了确保Keepalived正常工作,需要在两台服务器的防火墙中放行VRRP协议和业务服务端口。
使用firewalld(CentOS 7默认防火墙)
1. 允许VRRP协议(IP协议112)通信
sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 \
--in-interface eth1 --protocol 112 --destination 224.0.0.18 --jump ACCEPT
1. 允许单播VRRP通信(如果使用unicast模式)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" \
source address="10.0.0.0/24" protocol value="112" accept'
1. 允许HTTP服务(根据实际业务需要调整)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
1. 重新加载防火墙规则
sudo firewall-cmd --reload
使用iptables
如果使用iptables作为防火墙,可以执行:
1. 允许VRRP协议
sudo iptables -A INPUT -i eth1 -p 112 -d 224.0.0.18 -j ACCEPT
1. 允许单播VRRP通信
sudo iptables -A INPUT -s 10.0.0.0/24 -p 112 -j ACCEPT
1. 允许HTTP服务
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
1. 保存规则
sudo service iptables save
关闭防火墙(测试环境可选)
在测试环境中,如果遇到问题,可以暂时关闭防火墙进行测试:
1. 临时关闭
sudo systemctl stop firewalld
1. 永久关闭
sudo systemctl disable firewalld
七、启动并验证服务
1. 启动Keepalived服务
在两台服务器上分别启动Keepalived服务:
1. 启动服务
sudo systemctl start keepalived
1. 设置开机自启
sudo systemctl enable keepalived
1. 检查服务状态
sudo systemctl status keepalived
2. 检查VIP绑定状态
在主服务器上执行以下命令,确认VIP已正确绑定:
ip addr show eth0
应该能看到类似以下输出,表明VIP已绑定到eth0接口:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:a8:b8:c4 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.1.100/24 scope global secondary eth0:vip
valid_lft forever preferred_lft forever
3. 查看Keepalived日志
检查日志以确认Keepalived的运行状态:
1. 查看Keepalived专用日志
sudo cat /var/log/keepalived.log
1. 查看系统日志中的Keepalived信息
sudo grep keepalived /var/log/messages
4. 测试VIP访问
从其他客户端机器上测试是否可以通过VIP访问服务:
1. Ping测试VIP连通性
ping 192.168.1.100
1. 如果运行Web服务,测试HTTP访问
curl http://192.168.1.100/
八、故障切换测试
进行以下测试,验证高可用功能是否正常:
1. 模拟主服务器故障
在主服务器上执行:
1. 停止Keepalived服务
sudo systemctl stop keepalived
1. 或者关闭网卡
sudo ifconfig eth0 down
2. 观察VIP漂移
在备服务器上查看IP地址,确认VIP是否成功漂移:
ip addr show eth0
3. 模拟业务服务故障
在主服务器上停止HTTP服务:
sudo systemctl stop httpd
等待几秒钟,观察VIP是否因为健康检查失败而漂移到备服务器。
4. 模拟心跳网络故障
在主服务器上禁用心跳网卡:
sudo ifconfig eth1 down
观察VIP是否成功漂移到备服务器。
5. 恢复测试
在完成上述测试后,恢复服务并观察VIP行为:
1. 重新启动Keepalived
sudo systemctl start keepalived
1. 或启用网卡
sudo ifconfig eth0 up
sudo ifconfig eth1 up
1. 启动业务服务
sudo systemctl start httpd
九、故障排查
当Keepalived出现问题时,可以按照以下步骤进行故障排查:
1. 检查服务状态
1. 查看Keepalived运行状态
sudo systemctl status keepalived
1. 查看Keepalived进程
ps -ef | grep keepalived
2. 检查日志信息
1. 查看Keepalived日志
sudo tail -f /var/log/keepalived.log
1. 查看系统日志
sudo tail -f /var/log/messages
3. 检查网络配置
1. 查看网卡状态
ip addr show
1. 查看路由表
ip route show
1. 检查网络连通性
ping -I eth0 192.168.1.20 # 业务网卡连通性测试
ping -I eth1 10.0.0.2 # 心跳网卡连通性测试
4. 检查防火墙规则
1. 检查防火墙状态
sudo systemctl status firewalld
1. 查看防火墙规则
sudo firewall-cmd --list-all
5. 常见问题及解决方案
问题1:VIP无法正常漂移
- 检查两台服务器的virtual_router_id是否一致
- 检查authentication密码是否一致
- 检查心跳网络是否正常通信
- 检查防火墙是否允许VRRP协议通行
问题2:两台服务器同时拥有VIP(脑裂)
- 检查心跳网络是否正常
- 验证unicast_peer配置是否正确
- 增加额外的监控机制,如添加track_interface监控心跳网卡
问题3:服务检测脚本不生效
- 检查脚本权限是否正确
- 验证脚本路径是否正确
- 检查脚本中的命令是否可以在系统中执行
- 使用debug参数增加日志信息进行排查
问题4:VIP能ping通但业务无法访问
- 检查业务服务是否正常运行
- 验证防火墙是否允许业务端口通行
- 检查SELinux是否阻止了服务访问
十、配置参数详解
全局配置参数
| 参数名称 | 说明 | 示例值 |
|---|---|---|
| router_id | 路由器标识,应在集群内唯一 | MASTER_SERVER |
| notification_email | 告警邮件接收地址 | admin@example.com |
| smtp_server | 邮件服务器地址 | 127.0.0.1 |
| vrrp_garp_interval | GARP报文发送间隔(秒) | 1 |
| log_facility | 日志设施 | local0 |
VRRP实例参数
| 参数名称 | 说明 | 示例值 |
|---|---|---|
| state | 初始状态,MASTER或BACKUP | MASTER |
| interface | 绑定VIP的网卡名称 | eth0 |
| virtual_router_id | 虚拟路由器ID,集群内必须相同 | 51 |
| priority | 优先级,值越大越优先成为MASTER | 100 |
| advert_int | VRRP通告间隔(秒) | 1 |
| unicast_src_ip | 本机心跳源IP地址 | 10.0.0.1 |
| unicast_peer | 对端心跳IP地址列表 | 10.0.0.2 |
| nopreempt | 是否禁用抢占模式 | (不设置为启用抢占) |
| preempt_delay | 抢占延迟(秒) | 300 |
检查脚本参数
| 参数名称 | 说明 | 示例值 |
|---|---|---|
| script | 检查脚本路径 | /etc/keepalived/check_httpd.sh |
| interval | 检查间隔(秒) | 2 |
| weight | 检查失败时的优先级调整值 | -5 |
| fall | 连续失败多少次才算真失败 | 2 |
| rise | 连续成功多少次才算真成功 | 1 |
十一、优化与最佳实践
-
心跳网络冗余
- 考虑为心跳网络配置双线路或绑定两个物理接口,避免单点故障
- 可以考虑添加第三条网络链路作为心跳检测的备份通道
-
调整切换灵敏度
- 根据业务重要性调整advert_int、fall和rise参数
- 重要业务可以降低fall值提高响应速度,非关键业务可以提高fall值避免误切换
-
预防脑裂问题
- 使用多条心跳线路
- 在健康检查脚本中增加外部判断条件(如网关可达性)
- 配置fence设备强制隔离故障节点
-
监控与告警
- 配置邮件、短信或第三方监控系统对Keepalived状态变化进行告警
- 记录详细的日志用于故障分析
-
安全加固
- 使用强密码或AH认证方式增强VRRP安全
- 限制心跳网段的访问控制
- 定期更改认证密码
十二、总结
Keepalived双网卡主备方案通过以下机制保障业务高可用:
- 物理隔离:业务与心跳分离,提高检测可靠性
- 快速切换:基于VRRP协议实现1-3秒内的故障转移
- 多级检测:支持心跳检测、服务检测等多重机制
- 简单高效:配置简单,无需复杂集群管理,维护成本低
这种架构特别适合对可靠性有较高要求、但又不希望过于复杂的中小型业务系统。对于更高可用性需求,可以考虑在此基础上扩展到多节点集群方案。
sudo systemctl restart network