实现 IPVS 的高可用性(LVS + Keepalived + DR 模式)

本文档说明如何用 Keepalived + IPVS(LVS)实现高可用负载均衡(DR 模式),包含 RS(Real Server)上配置 VIP 的办法、内核 ARP/路由设置、Keepalived 的 virtual_server 配置、测试与常见问题排查。
1 拓扑与说明(示例)
- 两台 LB(KA1、KA2)��运行 keepalived + ipvsadm,负责创建 IPVS 策略并接收 VIP 流量。
- 两台 RS(RS1、RS2):真实后端 Web 服务器,需在本机 loopback 上配置 VIP(/32),并抑制 ARP 响应(避免与 LB 冲突)。
- 负载均衡方式:DR(Direct Routing),即 VIP 由 LB 接收并直接把请求二层转发给 RS,RS 用本地 loopback 接收并返回源地址(不经过 LB)。
关键点:
- RS 必须配置 VIP 到
lo(/32),并设置 arp_announce/arp_ignore 以避免响应 ARP。 - LB 上启用 virtual_server(lb_kind DR),并用 ipvsadm 查看/调试规则。
- 若使用 NAT 模式则需要开启 IP 转发;DR 模式 RS 不需要 ip_forward(但可能需要关闭 rp_filter)。
2 在 RS1和RS2 上配置 VIP(NetworkManager 示例)
把现有 eth0 连接复制为 lo 连接并设置 /32 VIP:
bash
cd /etc/NetworkManager/system-connections/
ls
# 假设存在 eth0.nmconnection
cp eth0.nmconnection lo.nmconnection -p
vim lo.nmconnection
lo.nmconnection 示例内容:
ini
[connection]
id=lo
type=loopback
interface-name=lo
[ipv4]
method=manual
address1=127.0.0.1/8
address2=172.25.254.100/32
应用并激活:
bash
nmcli connection reload
nmcli connection up lo
ip addr show lo
# 确认有 172.25.254.100/32 在 lo 接口
3 调整内核 ARP/路由相关参数(RS 上)
在 /etc/sysctl.conf 中添加(示例,适用于 DR 模式):
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.lo.arp_ignore=1
# 可选:若出现 RPF 问题,考虑关闭 rp_filter(按需)
# net.ipv4.conf.all.rp_filter=0
# net.ipv4.conf.default.rp_filter=0
生效:
bash
sysctl -p
说明:
- arp_ignore/arp_announce 用于让 RS 在收到对 VIP 的 ARP 请求时不响应(避免与 LB 冲突)。
- rp_filter(反向路径过滤)在某些网络可能导致包被丢弃,遇到无法连通时可排查并按需调整。
查看RS1和RS2上IP
[root@rs1+2 system-connections]# ip a


4 在 KA1和KA2上安装 ipvsadm
在所有 Keepalived 主机上安装 ipvsadm(用于查看/调试 IPVS):
bash
dnf install -y ipvsadm
# 验证内核模块
lsmod | grep ip_vs || modprobe ip_vs
常用查看命令:
- 列出 IPVS 表项: ipvsadm -Ln
- 结合服务端口: ipvsadm -Ln --virtaddr 172.25.254.100:80
- 显示统计: ipvsadm -s
5 Keepalived 中的 IPVS 配置(virtual_server 示例)
在 Keepalived 配置文件中增加 virtual_server 段(在运行 IPVS 的节点上,通常与 vrrp_instance 同文件):
bash
#在keepalived的所有主机中
[root@KA1和KA2 ~]# vim /etc/keepalived/keepalived.conf
virtual_server 172.25.254.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
real_server 172.25.254.10 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
retry 3
delay_before_retry 1
}
}
real_server 172.25.254.20 80 {
weight 1
TCP_CHECK {
connect_timeout 5
retry 3
delay_before_retry 3
connect_port 80
}
}
}
说明:
- lb_kind DR:Direct Routing 模式。
- health checks(HTTP_GET、TCP_CHECK)能让 LVS 自动剔除不可用 RS。
- virtual_server 配置放在 Keepalived 的配置文件中,Keepalived 成为 IPVS 的管理者,主节点会在激活时创建相应 ipvs 规则。
重启 keepalived:
bash
[root@KA1和KA2 ~]# systemctl restart keepalived.service
6 测试步骤
- 在独立测试主机(非 KA1/KA2/RS1/RS2)上用 curl 或浏览器访问 VIP: http://172.25.254.100 ,确认能访问并命中 RS。
在 KA2上实时监控 IPVS(在KA1模拟宕机):
bash
watch -n 1 ipvsadm -Ln

模拟 宕机:停止 KA1 的 keepalived(或整个节点),观察另一台 KA 是否自动生成 ipvs 表项并继续提供服务。
bash
systemctl stop keepalived.service # 在 KA1
# 在 KA2 上检查 ipvsadm 是否出现 virtual_server
ipvsadm -Ln

模拟 RS 故障:在 RS1 上停止 web 服务,观察 IPVS 对该 real_server 的状态是否从 UP -> DOWN(或被剔除),并确认流量到其他 RS。
bash
[root@RS1 ~]# systemctl stop httpd

bash
查看ka1中是否自动生成新的lvs策略[root@KA1 ~]# watch -n 1 ipvsadm -Ln

- 注意:在 KA1/KA2 本机直接访问 VIP 可能因路由/loopback 行为而看不到真实效果,建议用第三台测试机。
7 常见问题与排查建议
-
ipvsadm 没有规则
- 检查 keepalived 是否启动并没有报错: journalctl -u keepalived
- 确认 virtual_server 段语法正确并在 master 节点上(vrrp master)生效
- 检查内核模块 ip_vs 是否加载: lsmod | grep ip_vs
-
RS 收到包但服务不响应
- 确认 RS 上已把 VIP 配到 lo(/32),且 web 服务监听正确(0.0.0.0:80 或 VIP)
- 检查 arp 配置(arp_ignore/arp_announce)是否生效: sysctl net.ipv4.conf.lo.arp_ignore
-
ARP 冲突 / Split ARP 响应
- 确认 RS 不对 VIP 响应 ARP(arp_ignore=1);如果仍然冲突检查网络设备或交换机 ARP 缓存
-
连接被丢弃或不对称路由
- 检查 rp_filter(反向路径过滤)设置,按需关闭(设置为 0)
- 在 NAT 模式下需确保 ip_forward=1;DR 模式不需要 ip_forward
-
health check 无效
- 检查 Keepalived 的 health check 类型是否配置正确(HTTP_GET 需确保 URL 与端口可达)
- 在脚本中使用绝对路径并把输出重定向以便排查
常用排错命令:
bash
# 查看 ipvs 表
ipvsadm -Ln
# 显示更详细(含权重/连接数、穿透方式)
ipvsadm -L -n --stats
# 查看 keepalived 日志
journalctl -u keepalived -n 200
# 检查 RS 的 lo 地址
ip addr show lo
# 查看 sysctl 当前值
sysctl net.ipv4.conf.lo.arp_ignore
sysctl net.ipv4.conf.all.arp_announce
显示更详细(含权重/连接数、穿透方式)
ipvsadm -L -n --stats
查看 keepalived 日志
journalctl -u keepalived -n 200
检查 RS 的 lo 地址
ip addr show lo
查看 sysctl 当前值
sysctl net.ipv4.conf.lo.arp_ignore
sysctl net.ipv4.conf.all.arp_announce