
LVS 配合 DR 模式是我在线上一线折腾过很多年的负载均衡组合。LVS 是 Linux Virtual Server思路很朴素把多台后端机器的服务能力聚合成一个统一的虚拟 IP对外提供入口客户端完全不关心背后有几台服务器DR 是 Direct Routing直接路由也是 LVS 三种工作模式里性能最突出、坑也最隐蔽的一种。当你有一堆 Web 服务、并发连接偏高又不想让调度器背上全部响应流量的时候LVSDR 就是非常经典的选择。这篇文章我准备用一次完整的实验配置带你走通整套链路从拓扑规划、调度器规则、真实服务器的 ARP 抑制到反复验证和排障。适合刚接触 LVS 的新手也适合那些想先搭一套 DR 测试环境、之后准备上生产的朋友。你可以照着敲命令也可以只挑原理部分看把网络底子补一补。1. 整体设计与思路拆解1.1 LVS 与 DR 模式的核心原理先统一几个叫法。LVS 里有两类机器一台是 Director调度器承担流量分发若干台是 RealServer真实服务器真正处理业务。Director 上配置一个 VIP虚拟 IP对外提供服务。客户端访问的是 VIP而不是某台真实服务器的 IP。DR 模式的处理流程看下来其实只有四步客户端发起请求目标 IP 是 VIP请求进入二层网络Director 收到后按负载均衡算法选中一台 RealServerDirector 只改写帧头里的目标 MAC 地址把帧发给对应的 RealServerRealServer 因为在本机 lo 接口上绑定了 VIP能正常接收请求处理完的响应直接以 VIP 为源 IP 回给客户端。这个流程里最关键的一点是响应流量根本不会绕回 Director。外部看过去仿佛每台真实服务器都“自己会说话”。所以 DR 模式的吞吐量上限很高Director 往往只承受入口流量不容易成为瓶颈。我习惯用一个比喻去理解Director 像一个快递分拣员他只负责把包裹上写的最终门店地址换成对应门店的交通路线包裹以后怎么送到收件人手里是门店自己的事。和 NAT 模式那种“所有包裹进出都必须回分拣中心盖章”的模式相比DR 省掉了大量回程压力。1.2 为什么选 DR而不是 NAT 或 TUNLVS 三种模式经常放在一起对比。我在不同场景里都试过区别感受很深。模式请求路径响应路径调度器压力适用场景关键技术点NAT客户端 → Director → RealServerRealServer → Director → 客户端所有进出流量都过 Director压力最大后端是私网 IP不能直接暴露开启 ip_forward改目标 IP 和端口TUN客户端 → Director → RealServer隧道封装RealServer → 客户端直接返回只承受入向流量后端跨网段、跨地域部署隧道封装RealServer 支持隧道DR客户端 → Director → RealServer改写 MACRealServer → 客户端直接返回只承受入向流量同一二层网络、环境可控ARP 抑制lo 接口绑定 VIP这个表格看完就清楚了如果后端机器和调度器能放在同一个网段DR 是非常理想的选择。TUN 虽然也能做到响应不经过调度器但封装和解封装有额外开销配置也比 DR 复杂。NAT 模式最省脑子可一旦流量起来Director 的 CPU、网卡、连接表都容易先撑不住。1.3 实验环境怎么搭最省事DR 模式依赖二层网络所以我建议实验环境全部保持在同一网段不要一开始就引入多 VLAN 或跨三层交换否则会把 ARP 问题排查复杂化。我这里规划一份最小实验拓扑你直接用虚拟机的 Host-Only 网络或者一台交换机隔离的实验网来做都行设备角色IP 地址关键配置Client客户端192.168.1.200普通测试机Director调度器eth0: 192.168.1.10额外绑定 VIP: 192.168.1.100/32RealServer1后端节点eth0: 192.168.1.11lo 上绑定 VIP: 192.168.1.100/32RealServer2后端节点eth0: 192.168.1.12lo 上绑定 VIP: 192.168.1.100/32VIP 统一用 192.168.1.100。Director 上把它绑在 eth0 上因为对外入口得让它能收到RealServer 上就要绑到 lo 上并且子网掩码必须写成 /32不能写成 /24。这样 VIP 只属于本机自己不会因为掩码过大造成路由混乱。操作系统我建议用 CentOS 7/8、Ubuntu 18.04 以上都行内核参数名基本一致。后端服务先用 Nginx 或者 Apache 随便跑一个页面能区分出是哪台机器响应就好。2. 核心细节与实操要点2.1 调度器端初始化配置先安装好 ipvsadm这是 LVS 的管理工具# CentOS/RHEL yum install -y ipvsadm # Ubuntu/Debian apt install -y ipvsadm然后在 Director 上配置 VIP 和开启 ip_forwardip addr add 192.168.1.100/32 dev eth0 echo 1 /proc/sys/net/ipv4/ip_forward这里有个细节想多说一句。DR 模式下报文在同一个网段里被调度器转发严格来说不依赖 ip_forward但我在实际配置里仍然习惯顺手打开。原因很简单实验环境里偶尔有其他混合模式的需求开了之后省得后面遇到蹊跷问题来回怀疑。想让配置永久生效的话把它写进 /etc/sysctl.conf 里net.ipv4.ip_forward 1 sysctl -p此时可以用 ip addr show eth0 检查 VIP 是否已经出现。2.2 用 ipvsadm 配置调度规则接下来是重头戏给 Director 添加虚拟服务。ipvsadm -C # 添加 VIP 服务调度算法用 rr轮询 ipvsadm -A -t 192.168.1.100:80 -s rr # 添加两台真实服务器-g 表示 DR 模式 ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.11:80 -g ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.12:80 -g -w 1先解释参数。-A是添加虚拟服务-t表示 TCP 端口-s rr指定轮询算法-a是添加真实服务器条目-r是真实服务器的 IP 和端口-g就是 DR 模式gatewaying直接路由-w指定权重默认也是 1。很多人会把-g和 NAT 模式的-m搞混。-m是 masquerade也就是 NAT-i是 IPIP 隧道TUN 模式。选错了整个实验就天翻地覆报文路径完全不对。配置完看一眼ipvsadm -Ln输出里会看到 Virtual Service 是 192.168.1.100:80下面挂了两台 RealServerRoute 类型就是 DR。如果实验完后想保存规则可以执行ipvsadm-save /etc/sysconfig/ipvsadm将来重启机器了用 ipvsadm-restore /etc/sysconfig/ipvsadm 恢复。生产环境其实不太推荐手动恢复规则后面我会提到用 keepalived 管理规则更稳妥。2.3 调度算法的选择逻辑rr 就是轮流来适合验证“每台后端都收到了请求”。但它有个明显缺陷不考虑机器性能差异。实验中两台机器配置相同rr 够用如果生产环境里一台机器是 8 核、另一台是 4 核rr 会导致两台机器流量一样多性能差的反而先垮。实测下来我比较常用 wlc加权最少连接数。它会根据当前连接数和权重综合决策在线业务里表现更均衡ipvsadm -A -t 192.168.1.100:80 -s wlc需要动态修改真实服务器权重的命令也别忘ipvsadm -e -t 192.168.1.100:80 -r 192.168.1.11:80 -w 5-e表示编辑已存在的条目调度器会很平滑地调整分发比例不需要重启服务。3. 真实服务器端配置与 ARP 抑制3.1 在 RealServer 上绑定 VIP 到 lo每台 RealServer 都需要把 VIP 绑到本地回环接口ip addr add 192.168.1.100/32 dev lo为什么绑到 lo 而不是 eth0因为这是 DR 模式最本质的要求VIP 要被本机识别和接收但不能作为真实服务器的对外通告 IP。如果把 VIP 直接绑到 eth0RealServer 会频繁对外宣告自己拥有这个 IP网络中马上会爆发 ARP 冲突。绑定之后RealServer 就能收到目标 IP 是 VIP 的报文了。但此时还不能直接用于生产因为 ARP 问题不解决整个实验环境会乱成一锅粥。3.2 ARP 抑制的原理与完整配置现在网络中至少有三台机器知道自己有 VIP一台 Director两台 RealServer。客户端要访问 VIP第一步就是发 ARP 广播问“谁是 192.168.1.100请把你的 MAC 告诉我”。如果 RealServer 回复了这个 ARP 请求客户端就会把数据帧直接发给 RealServer最后流量根本不经过 Director负载均衡直接失效。更糟的是如果多台机器同时回复客户端的 ARP 缓存会来回变化时通时不通。解决办法是让 RealServer 上的 VIP 变成“哑地址”只接收发给自己的 IP 包不对外回应任何针对 VIP 的 ARP 请求。标准做法是修改内核参数cat /etc/sysctl.conf EOF net.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2 net.ipv4.conf.lo.arp_ignore 1 net.ipv4.conf.lo.arp_announce 2 net.ipv4.conf.eth0.arp_ignore 1 net.ipv4.conf.eth0.arp_announce 2 EOF sysctl -p强调一下这两个参数的作用arp_ignore 1本机只回应“目标 IP 是本机物理接口 IP”的 ARP 请求。VIP 只存在于 lo 上所以当其他接口收到询问 VIP 的广播时RealServer 会保持沉默。arp_announce 2发送 ARP 通告时选择最佳本地接口 IP 来作为源而不是随意使用包含在路由表里的 VIP。这样能让 RealServer 尽量不向外宣告自己拥有 VIP。我见过一些人只配置 all 项不配置 lo 项。当你 sysctl -p 之后发现 ping VIP 还是时通时不通问题往往就出在这。最稳妥的办法是all、lo、实际业务网卡eth0统统配上。尤其在有多块网卡的机器上默认的 all 参数生效范围可能和你预期不一致逐接口写一遍最保险。3.3 在 RS 上准备后端服务和基础验证以 Nginx 举例apt install -y nginx为了区分流量到底落在哪台机器上把两台 Nginx 的默认页面改一下echo RealServer1 /var/www/html/index.html echo RealServer2 /var/www/html/index.html启动服务后先用本机真实 IP 验证一下curl http://192.168.1.11/ curl http://192.168.1.12/这里有一个很容易踩的坑不要用 curl http://192.168.1.100/ 来验证 RealServer。因为从 RealServer 本机访问 VIP请求会从 lo 出去又回到本机回包和 ARP 行为非常奇怪往往会超时这也根本不能代表真实用户的访问状态白白浪费时间。管理 RS 全部用物理 IP对外入口才用 VIP这个习惯建议尽早养成。4. 实验验证与联动检查4.1 从客户端发起访问确认流量路径现在三端配置基本完成。到 Client 上操作arp -d 192.168.1.100 for i in $(seq 1 10); do curl -s http://192.168.1.100/ sleep 1 done这里删除 ARP 缓存是为了避免客户端之前缓存了错误的 VIP-MAC 映射。如果不删实验环境里之前抓包过程的旧缓存可能带来干扰。正常情况下输出应该是 RealServer1、RealServer2 交替出现。如果 rr 模式轮询正常两台服务应该轮流响应。回到 Director 上看统计数据ipvsadm -Ln --stats注意看 Conns连接数、InPkts入包量、OutPkts出包量。DR 模式下 OutPkts 通常远小于 InPkts甚至趋近于零因为大部分响应直接从 RealServer 回到客户端了。如果 Director 的出包量和入包量几乎一样高就要怀疑是不是配成了 NAT 模式或者请求响应都走了 Director。4.2 用抓包验证“响应不过 Director”这一关键特征空说无凭直接上 tcpdump。在 RealServer1 上执行tcpdump -i eth0 host 192.168.1.100 and port 80 -nn再在 Client 上访问一次 VIP。重点看两个信息入向请求帧目标 MAC 是 RealServer1 的 MAC目标 IP 是 192.168.1.100出向响应帧源 IP 是 192.168.1.100目标 IP 是 Client 的 IP但源 MAC 是 RealServer1 的 MAC。这就证明了 RealServer 自己在直接回包Director 没有参与响应转发。明白这个特征DR 模式就算掌握了一半。有的读者反馈说“明明配置一样为什么在交换机上抓包时看不到入向帧目标 MAC 是 RS 的 MAC”这通常是因为禁用了 VLAN 的组播侦听、或交换机 MAC 表被优化不属于配置问题不影响业务。4.3 调度策略和连接跟踪的实际观察把 Director 的调度算法从 rr 切换成 wlc 或 wrr能体会权重和连接数对分发的具体影响ipvsadm -A -t 192.168.1.100:80 -s wrr修改权重让一台机器多扛一些流量再看统计就非常直观ipvsadm -e -t 192.168.1.100:80 -r 192.168.1.11:80 -w 5 ipvsadm -e -t 192.168.1.100:80 -r 192.168.1.12:80 -w 1这时多访问几次你会发现 RealServer1 的命中数明显多于 RealServer2。在 rr 下看起来“不够均匀”其实很可能是 keep-alive 连接复用在捣乱。想让测试数据干净用 curl 时加--http1.0或者Connection: close。查看连接跟踪表ipvsadm -Lnc可以看到每条连接从哪个 Client 来、分给了哪台 RealServer、当前状态是什么。这排障时很有用。有人说生产环境里连接表动辄几十万条用这命令会卡吧确实会所以生产上一般只配合 keepalived 检查服务器健康状态不会高频人工刷这个命令。4.4 从手动配置向 keepalived 过渡实验最后我建议你再往前走一步把 Director 从单点升级成高可用。keepalived 是 LVS 最常用的搭档它通过 VRRP 协议让两台 Director 共享一个 VIP默认情况下只有主节点响应主节点挂了备用节点接管 VIP同时重新加载 ipvs 规则。一个最小配置框架如下global_defs { router_id LVS_DR_HA } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 virtual_ipaddress { 192.168.1.100/32 dev eth0 } } virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo wlc lb_kind DR protocol TCP real_server 192.168.1.11 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.1.12 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }生产环境里这套配置可以省去手工 ipvsadm 规则维护还可以自动做后端健康检查。实验时先手动敲一遍理解每个命令是什么含义再迁移到 keepalived 就很顺。5. 常见问题与排查技巧实录5.1 高频问题速查表下面这些是我在 DR 实验里遇见最多的问题整理成一张速查表方便你直接对照。现象可能原因排查方向访问 VIP 时通时不通RealServer 抢答 ARP检查 sysctl 配置和 lo 掩码完全不通防火墙挡了 80 端口关闭 firewalld 或放行端口请求总落在同一台机器算法、keep-alive 连接复用看连接表换 wlc 测试RS 本机访问 VIP 超时这是正常现象别用它验证外部 Client 访问 VIP重启后规则全部丢失没有持久化配置用 ipvsadm-save 或 keepalived抓包显示 Director 出包量很大模式配成了 NAT 或 TUN检查 -g 参数5.2 几个典型错误复盘第一个错误是只配置了arp_ignore没配置arp_announce。这种半截配置在客户端 ARP 缓存刷新后RealServer 仍可能周期性对外通告 VIP。排查时很隐蔽因为大多数时间看起来正常偶尔就是会有那么几秒访问超时。我的建议是all、lo、eth0三处都配上保持完整。第二个错误是把 VIP 的子网掩码写成了 24。比如ip addr add 192.168.1.100/24 dev lo这会让内核认为 lo 接口拥有整个 192.168.1.0/24 网段产生非常邪门的路由问题甚至导致真实服务器之间互相无法通信。修复方法就是删掉重新绑ip addr del 192.168.1.100/24 dev lo ip addr add 192.168.1.100/32 dev lo第三个错误是直接在 RealServer 上访问 VIP。前面说过这是无效测试但很多人栽在这里。宿主机或虚拟机里如果开了代理也会让 curl 访问 VIP 时走了一圈代理结果怎么看都不对。测试前确认 curl 是直连或者干脆关掉环境变量里的 http_proxy。5.3 一套完整的排障操作顺序如果你踩了坑别东一下西一下地猜。我通常按下面的顺序排查基本两轮内就能定位。在 Client 上清空 VIP 的 ARP 缓存重新 ping VIP看稳定不稳定在 Director 上执行ipvsadm -Ln --stats看 InPkts 和 OutPkts 比例判断是否走错了模式检查 RealServer 上的 VIP 绑定是否还在ip addr show lo检查 sysctl 配置是否完整sysctl -a | grep arp_ignore在 Client 上确认 80 端口通不通telnet 192.168.1.100 80在 Director、RealServer1、RealServer2 三端同时抓包对比 MAC 和 IP判断链路是否按预期走。整套流程里最核心的原则是“一次只改一个变量”。配置网络本来就够复杂了同时改三四个参数出了问题根本不知道是谁引起的。最后分享一点我的实际操作体会LVSDR 这套东西我第一次上手时也被 ARP 搞得头大后来我把整套思路压缩成一句话调度器拿到包只改 MAC 不改 IPRealServer 用 lo 收包、用真实网卡回包。任何验证都围绕这句话来判断就不会跑偏。如果你准备从零开始做实验我建议从最小双机环境开始先把两台 RealServer 跑通轮询再去研究权重和 keepalived。抓包看到响应包的源 IP 是 VIP、源 MAC 却是 RealServer 的那一刻DR 的原理你就真正吃透了。之后再上生产心里就踏实很多。