keepalived 启动失败因 ip_vs 模块未加载,需手动执行 modprobe ip_vs 等命令并写入 /etc/modules;vrrp_instance 与 virtual_server 必须顺序配对;dr 模式需在 rs 上绑定 vip 到 lo 并配置 arp_ignore=1 和 arp_announce=2;健康检查失败可能因 tcp 探测误判或路由/接口配置不当。

Keepalived 启动失败:找不到 ip_vs 模块怎么办
直接运行 systemctl start keepalived 报错 “FATAL: Module ip_vs not found”,说明内核未加载 IPVS 模块。LVS 依赖内核态的 ip_vs 及其子模块(如 ip_vs_rr、ip_vs_wrr),不是装了 Keepalived 就自动可用。
执行以下命令检查当前加载状态:
lsmod | grep ip_vs
若无输出,手动加载(多数现代发行版已内置,但默认不加载):
modprobe ip_vs-
modprobe ip_vs_rr(轮询调度必需) -
modprobe ip_vs_wrr(加权轮询可选) - 为避免重启失效,写入
/etc/modules:ip_vsip_vs_rr
注意:某些云主机(如 AWS EC2、腾讯云 CVM)使用定制内核,可能彻底移除了 ip_vs 支持,此时无法启用 LVS,需改用 Nginx 或 HAProxy 做四层代理。
Keepalived 配置里 vrrp_instance 和 virtual_server 的顺序与作用边界
Keepalived 配置中,vrrp_instance 负责 VIP(虚拟 IP)漂移和主备选举,virtual_server 才真正定义 LVS 规则——它必须依附于一个已声明的 vrrp_instance,且只能出现在该 instance 块之后(顺序错误会导致解析失败,keepalived -t 会报 “unknown block”)。
典型错误配置:
vrrp_instance VI_1 { ... }
virtual_server 192.168.1.100 80 { ... }
vrrp_instance VI_2 { ... } # 错:VI_2 后面没跟它的 virtual_server,但 VI_1 的 virtual_server 却在中间
正确结构应是:
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
...
}
virtual_server 192.168.1.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR # 注意:DR 模式要求真实服务器配置 ARP 抑制
...
real_server 192.168.1.11 80 { ... }
real_server 192.168.1.12 80 { ... }
}
多个 VIP 对应多个 vrrp_instance + 对应的 virtual_server 块,不能复用或跨块引用。
LVS-DR 模式下真实服务器收不到请求:ARP 相关配置漏了哪几处
DR 模式要求所有 RS(Real Server)在本地回环接口(lo)上绑定 VIP,并禁用该 VIP 的 ARP 响应,否则主备 Keepalived 的 VIP 会和 RS 的 VIP 冲突,导致流量被 RS 自己吞掉,不转发给后端服务。
缺一不可的三步操作(在每台 RS 上执行):
- 绑定 VIP 到
lo:0:ip addr add 192.168.1.100/32 dev lo label lo:0 - 禁止
lo接口响应 VIP 的 ARP 请求:echo "net.ipv4.conf.lo.arp_ignore = 1" >> /etc/sysctl.confecho "net.ipv4.conf.lo.arp_announce = 2" >> /etc/sysctl.confsysctl -p - 确认
net.ipv4.conf.all.arp_ignore和all.arp_announce不覆盖 lo 设置(它们优先级更低,但设成 0 更安全)
常见误操作:只配了 arp_ignore=1,忘了 arp_announce=2,结果 RS 在发包时仍用物理网卡 MAC 作为源,LVS 转发失败;或者把 VIP 绑到 eth0 而非 lo,触发 ARP 冲突。
健康检查失败但 real_server 服务明明正常:检查点在哪
Keepalived 默认用 TCP 连接探测(tcp_check),只验证端口通不通,不校验 HTTP 状态码或内容。如果后端是 Nginx,但配置了 return 444 或连接限制,TCP 握手成功但应用层拒绝,Keepalived 仍判为“存活”。
更可靠的检查方式是启用 http_get,但要注意:
- 路径必须存在且返回 2xx/3xx(默认只认 2xx):
url { path /healthz status_code 200 } - 超时参数要显式设小,避免拖慢故障转移:
connect_timeout 3,nb_get_retry 3,delay_before_retry 1 - RS 上的健康检查路径不能依赖域名或 Host 头(除非用
http_get的host参数指定)
另一个隐藏坑:Keepalived 的健康检查由本机发起,走的是默认路由。若 RS 有多网卡、多路由表,或启用了策略路由,检查包可能被发错出口,导致探测失败。建议用 tcpdump -i any port 80 在 RS 上抓包确认是否收到探测请求。
DR 模式下尤其要注意:健康检查包目的 IP 是 VIP,而 RS 的 VIP 绑在 lo,所以检查必须能到达 lo 接口——这意味着本机路由表里必须有 192.168.1.100/32 dev lo,否则包会被丢弃。











