在使用 ipvsadm 搭建 LVS-DR 负载均衡集群时,VIP 地址通常需要同时配置在 Director 和所有真实服务器的回环接口上。由于 Linux 内核默认的 ARP 处理逻辑是“只要本机任一接口有目标 IP,就立即应答”,结果就是多台机器同时声明自己拥有 VIP,局域网的交换机 MAC 表不断抖动,来自路由器的请求会被随机分发到真实服务器甚至 Director 以外的节点,导致整个集群工作异常。

要解决这个问题,必须理解两个内核参数:arp_ignore 与 arp_announce。它们直接控制主机对入站 ARP 请求的响应级别以及出站 ARP 通告的源地址选择方式。很多人遇到 VIP 无法 ping 通,或者 VIP 被多台主机同时响应时,第一反应就是去把 arp_ignore 设置为 1,却忽略了 sysctl 中 all 和具体网卡之间的作用域规则,最终配置不生效。本文结合实战经验,从原理到配置逐步说明。
一、LVS-DR 模式中的 VIP 与 ARP 冲突根源
LVS-DR 的工作模式决定了 Director 和真实服务器必须使用同一个 VIP 来接收请求。不同点在于 Director 的 VIP 通常绑定在对外网卡上,真实服务器的 VIP 则绑定在 lo 接口的别名上。这样做可以让真实服务器处理接收到的数据包时,直接在本地回环接口上匹配 VIP,进而正常回包。但这也带来了副作用:当路由器发出“谁是 VIP”的广播 ARP 请求时,每一台绑定了 VIP 的主机都会应答,因为它们都认为 VIP 是自己的地址。
Linux 默认的 arp_ignore 值为 0,意味着不管 ARP 请求从哪个接口进入,只要本机任意接口配置了目标 IP,就会用对应接口的 MAC 地址应答。在 LVS-DR 中,真实服务器的 lo:0 已经绑定了 VIP,所以它会响应路由器的 ARP 请求。此时交换机收到多个相同的 VIP 应答,会更新到最后一个响应者的 MAC,新请求就可能被送到真实服务器而不是 Director,导致负载均衡策略失效。
还有一种现象是 VIP 配置在 lo 接口后,本机访问 VIP 也会出现路由问题。因为 Linux 将 VIP 视为本地地址,默认会走 lo 接口,但 ARP 参数设置不当会干扰这类访问。因此,调整 ARP 参数的目标是:让真实服务器只在内部特殊场景下使用 VIP,绝不对外部路由器发送的 ARP 请求进行应答;同时,在通告自身 IP 时,不使用 VIP 作为源 IP。
二、arp_ignore 与 arp_announce 参数详解
arp_ignore 的取值范围是 0 到 8,但在常规场景中最常用的是 0、1、2、3。值为 0 时,主机对本机所有接口上的目标 IP 请求都进行应答,这是默认行为。值为 1 时,主机只应答目标 IP 地址属于接收请求的接口本身的 ARP 请求。比如说,如果 ARP 请求从 eth0 进入,目标 IP 是 192.168.0.100,而 eth0 的 IP 是 192.168.0.1,即使 lo:0 上有 192.168.0.100,主机也不会应答。这正是 LVS-DR 需要的效果。
值为 2 时,不仅要求目标 IP 属于入站接口,还要求请求方的 IP 地址必须与入站接口位于同一子网,这样能够避免跨子网伪造的 ARP 请求。值为 3 时则会进一步结合路由表判断,规则更严格,但配置也更容易踩坑。在某些内核版本或网络环境下,使用 arp_ignore=2 或 3 反而可能导致 VIP 无法应答合法请求,所以一般不建议直接在生产环境尝试过高的值,优先从 1 开始。
arp_announce 则控制主机在发送 ARP 通告时选择源 IP 的方式。值为 0 时,允许主机使用任意配置在网卡上的 IP,包括 VIP。值为 1 时,内核会尽量选择目标网络内合理的源地址,但在部分场景下仍可能通告 VIP。值为 2 时,内核必须使用与目标网段匹配的最佳本地地址,如果找不到,就不发送 ARP 通告。在 LVS-DR 中,真实服务器应该对外部网络隐藏 VIP,所以将对外网卡的 arp_announce 设置为 2 是推荐做法。
需要注意 /proc/sys/net/ipv4/conf/ 目录下既有 all 子目录,也有每个网卡对应的子目录。Linux 内核对 arp_ignore 和 arp_announce 采用“取最大值”的策略来合并 all 与具体网卡的值。例如,如果 all.arp_ignore=0 而 eth0.arp_ignore=1,最终 eth0 上生效的值是 1;反过来,如果 all.arp_ignore=1 而 eth0.arp_ignore=0,最终 eth0 上生效的值仍然是 1。这就是为什么只修改 all 或者只修改单一网卡都可能得不到预期效果,必须明确设置所有相关接口的值,或者统一设置 all。
三、ipvsadm 场景下的推荐配置与故障验证
对于 LVS-DR 模式,推荐的做法是关闭真实服务器对 VIP 的对外响应,同时保留 lo 接口上的 VIP 供本地处理。首先需要将 VIP 绑定到 lo 的别名接口上,例如执行 ip addr add 192.168.0.100/32 dev lo:0。也可以使用 ifconfig 命令,但推荐使用 ip 命令。之后调整 sysctl 配置,在 /etc/sysctl.conf 中加入以下内容:
# 所有接口统一设置 arp_ignore 为 1 net.ipv4.conf.all.arp_ignore = 1 # 所有接口统一设置 arp_announce 为 2 net.ipv4.conf.all.arp_announce = 2 # 通常还需要设置实际对外网卡,这里以 eth0 为例 net.ipv4.conf.eth0.arp_ignore = 1 net.ipv4.conf.eth0.arp_announce = 2 # lo 接口也参与 VIP 的本地解析,视情况设置 net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.lo.arp_announce = 2
然后执行 sysctl -p 使其生效。注意,真实服务器和 Director 的配置方向不同:Director 的 VIP 是需要对外响应的,所以 Director 上保持默认值 0,不需要修改;只有真实服务器才需要抑制响应。如果某些场景下需要保留一部分响应能力,可以只修改指定网卡,而不是 all。
配置完成后,可以使用 arping 查看 ARP 响应来源。例如在客户端或路由器侧执行 arping -I eth0 -c 4 192.168.0.100,正常情况下应该只收到 Director 的 MAC 地址响应。如果收到多个不同的 MAC 地址,说明还有真实服务器在应答。使用 ip neigh show 可以看到邻居表条目,或者用 tcpdump -i eth0 arp 抓包确认 ARP 请求和响应报文。
如果出现 VIP ping 不通,先检查 sysctl 当前生效值,不要只看 /etc/sysctl.conf。执行 sysctl -a | grep arp_ignore 和 sysctl -a | grep arp_announce,确认 all 和各网卡的值是否符合预期。有些发行版还可能有 network 管理工具在启动时重置 sysctl,导致配置丢失。这时需要确认 /etc/rc.local 或 systemd 服务是否保留了 sysctl 设置。
此外,ipvsadm 本身不处理 ARP,它的作用只是维护 IPVS 规则。ARP 问题必须在 IP 层和链路层解决。所以在排查时,先确认 VIP 是否绑定成功,再用 ping 和 arping 区分是二层还是三层故障。还可以通过 cat /proc/net/arp 查看本机 ARP 缓存中没有正确的网关 MAC。如果使用的是多网卡服务器,还要注意 eth0 和 eth1 等网卡的 arp_ignore 值是否一致,避免出现部分网卡响应、部分网卡不响应的奇怪状态。
最后,建议在修改任何 ARP 参数前先备份原始配置,并用脚本记录修改前后的变化。因为 ARP 参数对网络影响很大,尤其是 arp_ignore 设置为 1 后,本机和其他主机之间的通信可能立刻中断,如果通过远程 SSH 操作,必须小心。最好先在测试环境验证,再推送到生产环境。
ipvsadmarp_ignorearp_announce修改时间:2026-08-21 20:38:22