本文主要记录在 LVS DR 模式的后端 RS(以 CentOS 7 为例)上配置 rp_filter 时,多处 sysctl 来源的生效顺序、all / 网卡 / default 的取值关系,以及为什么参数设错会导致调度“无 ActiveConn”。

LVS DR 场景下,RS 常见路径是:报文从内网口进入、以 VIP 相关地址从另一路径回包,属于典型非对称路由。此时若开启严格反向路径校验(rp_filter=1),内核可能直接丢弃入站包,表现为 VIP 无业务、调度器上看该 RS 连接为空。需要注意的是:发行版默认值、配置文件优先级和 all 与网卡取 max 的规则,经常比“写一句 echo 0”更绕。

问题现象

  • RS 上业务进程正常,但 LVS 调度器对该 RS 的 ActiveConn 长时间为 0 或明显异常。
  • rp_filter 相关项调整正确后,连接重新建立,业务恢复。

示例(IP 已脱敏,连接数仅作示意):

IP Virtual Server version 1.2.1 (size=1048576)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  <vip>:80 wrr
  -> <rs-a>:80                    Route   2      46         197
  -> <rs-b>:80                    Route   20     728        1869

rp_filter 不满足条件,同一 VIP 下目标 RS 的 ActiveConn 可能掉到 0。

环境背景

项目说明(示例)
角色LVS DR 后端 RS
系统CentOS 7.x 虚拟机
网卡多网卡(如 eth0 / eth1 / lo
配置入口/etc/rc.local/etc/sysctl.conf/usr/lib/sysctl.d//etc/sysctl.d/
自动化可能存在配置管理(如 Puppet)覆盖 sysctl

刚装好的 CentOS 7 常见读数示例:

cat /proc/sys/net/ipv4/conf/all/rp_filter      # 常见为 1
cat /proc/sys/net/ipv4/conf/default/rp_filter  # 常见为 1
cat /proc/sys/net/ipv4/conf/lo/rp_filter       # 常见为 0
cat /proc/sys/net/ipv4/conf/eth0/rp_filter     # 常见为 1

排查过程

多处配置入口

线上 RS 往往同时存在多处可改内核参数的位置,与 rp_filter 相关的常见包括:

# rc.local 中直接写 proc(示意)
grep rp_filter /etc/rc.local

# 传统 sysctl 文件
grep rp /etc/sysctl.conf

# 发行版默认 drop-in
grep rp /usr/lib/sysctl.d/50-default.conf

示意内容:

# /etc/rc.local 片段
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/lo/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter

# /etc/sysctl.conf 或发行版默认
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1

重启后若只看到网卡为 0、而 default 仍为 1,说明不同入口生效时机不同,需要先搞清顺序,而不是只改一处。

sysctl 文件加载顺序

在使用 systemd 的系统上,可用:

sysctl --system

输出中会按顺序 Applying 各文件。常见规律:

  1. /usr/lib/sysctl.d/*.conf(按文件名排序)
  2. /etc/sysctl.d/*.conf(按文件名排序)
  3. /etc/sysctl.conf

同名键后加载的覆盖先加载的。示例片段:

* Applying /usr/lib/sysctl.d/50-default.conf ...
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /etc/sysctl.conf ...

rc.local 相对 sysctl 的先后

把最后生效的 /etc/sysctl.conf 设为 all.rp_filter=0,同时在 /etc/rc.local 写入 echo 1 > .../all/rp_filter,重启后:

cat /proc/sys/net/ipv4/conf/all/rp_filter
# 结果为 1

说明 /etc/rc.local 晚于 /etc/sysctl.conf 生效(在 rc.local 仍会执行的环境中)。优先级示意见历史截图:

工程上更稳妥的做法是:以 drop-in(如 /etc/sysctl.d/99-lvs-rs.conf)统一管理,避免 rc.local 与 sysctl 互相打架;若暂时双写,两边取值必须一致。

原因分析

rp_filter 取值含义

内核文档 ip-sysctl.txtrp_filter 的说明可概括为:

含义
0不做源地址校验
1严格模式(RFC 3704 Strict RPF):入站包的反向路径必须是“最佳路径”,否则丢弃
2松散模式(Loose RPF):源地址在任意接口可达即可

某一网卡做校验时,内核使用:

max( conf/all/rp_filter , conf/<iface>/rp_filter )

因此只要 all 或该网卡任一为 1(严格),该网卡实际就会按至少严格模式校验。DR 下报文常从“非最佳反向路径”进入,严格模式容易误杀。

组合测试结论(DR RS)

在测试机上用 sysctl --load=<file> 切换组合并观察 LVS 连接(示意):

all网卡 (lo/eth*)defaultDR 业务表现(观察)
100不正常(ActiveConn 易为 0)
011不正常
001正常

结论:

  • RS 要正常工作,需要 all 与相关网卡上的 rp_filter 均为 0(松散模式 2 是否可用取决于拓扑;本文实测重点在 0/1)。
  • default 不直接决定已有网卡的当前行为,它主要影响之后新建网卡的初始值。

default 的作用验证

default=2、其余为 0 并生效后,热插或新增网卡 eth1,可见:

cat /proc/sys/net/ipv4/conf/eth1/rp_filter
# 为 2,与 default 一致

因此新网卡上线后若未再写网卡级配置,可能带着非 0 的 default 继承值,重新踩坑。DR RS 上建议对所有实际转发网卡显式写 0,并视情况把 default 也设为 0。

发行版默认差异

严格 RPF 与 RFC 3704 相关;RHEL 文档从 RHEL 6 起即强调默认严格模式,参见 Red Hat 相关 solution / Deployment Guide。不同大版本出厂值不完全相同(历史对比截图):

部分环境上 AS6/CentOS 6 的 all 实际为 0,即使未专门配 DR,也可能“碰巧能通”;迁到 CentOS 7 且 all=1 后问题暴露。以本机 cat /proc/... 为准,不要假设全系列默认一致。

解决方法

推荐在 RS 上使用独立 drop-in,例如 /etc/sysctl.d/99-lvs-dr-rs.conf

net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
net.ipv4.conf.eth0.rp_filter = 0
net.ipv4.conf.eth1.rp_filter = 0

网卡名按实际替换。加载并检查:

sysctl --system
# 或
sysctl -p /etc/sysctl.d/99-lvs-dr-rs.conf

cat /proc/sys/net/ipv4/conf/all/rp_filter
cat /proc/sys/net/ipv4/conf/eth0/rp_filter
cat /proc/sys/net/ipv4/conf/eth1/rp_filter

期望相关项均为 0

若仍保留 /etc/rc.local 历史写法,应与 sysctl 保持同一目标值,避免重启后被后执行的脚本改回。配置管理(Puppet 等)侧应以 sysctl drop-in 为单一事实来源更清晰。

验证结果

  1. /procall 与业务网卡 rp_filter 均为 0。
  2. LVS 调度器上该 RS 出现非 0 的 ActiveConn / 业务探测成功。
  3. 重启 RS 后参数与业务仍稳定(确认无被其他 conf 覆盖)。

注意事项

  • 关闭或放宽 rp_filter 会削弱基于 RPF 的伪造源地址防护;仅建议在 DR/非对称路由等确有需要的节点 上按接口收紧策略,而不是全集群无脑全 0。
  • 改内核参数有生效顺序问题:改完务必 cat /proc 复核,不要只看配置文件。
  • 新加网卡会吃 default;自动化装机模板里应包含网卡级配置或 default=0
  • 本文连接数、VIP/RS 地址均为脱敏示意;生产变更前在灰度 RS 上验证。

参考资料