做负载均衡这些年LVS DR模式是我在生产环境里用得最多、也最愿意推荐给别人的一种转发模式。Direct Routing 这个词看起来简单但真要能把它跑顺要弄明白的细节远比敲几条命令多。DR模式的核心就一句话Director只改写目标MAC地址把数据包送到RealServerRealServer处理完直接把回包绕过Director发给客户端。这一条特性让它在吞吐量上比NAT模式强一大截也是很多大流量业务的负载均衡首选。这篇文章适合刚接触LVS的人也适合已经搭过环境但总会碰到ARP问题的老手我会从原理、配置、调度到排障完整讲一遍。1. LVS DR模式是什么解决什么问题很多人第一次听说LVS时会先看到三种模式NAT、DR、TUN。它们解决的是同一个问题——把客户端请求分散到多台后端服务器上但解决方式完全不同。DR模式的全称是Direct Routing中文一般叫直接路由它充分利用了以太网交换机的二层转发能力在同一个广播域内通过改写MAC地址完成请求分发。跟NAT模式最大的区别在于DR模式不改变数据包的IP头只动MAC头所以回包不需要再走一遍Director。1.1 三种模式对比为什么DR会成为生产环境主力我把LVS的三种常用模式放在一张表里对比过差别很明显对比项NAT模式DR模式TUN模式请求经过Director进和出都经过只有入向经过只有入向经过改写内容改写目标IP和源IP只改写目标MAC新增IP隧道封装后端服务器要求需要内网通信回包网关指到Director与Director同一二层网络支持IP隧道协议即可后端服务器数量增长受限于Director带宽可扩展性好可跨网段部署典型瓶颈Director出入双向流量Director入向流量Director入向流量和隧道封装CPU开销从表里能看得很清楚NAT模式的Director要承担全部进出流量带宽和连接跟踪能力很容易成为瓶颈。DR模式把出向流量甩给了RealServerDirector只需要承担入向流量和转发判断压力陡降。TUN模式虽然能跨网段但需要在RealServer上把隧道包解封装配置和维护成本更高。对于绝大多数业务都部署在同一机房的场景DR模式是性价比最高的选择。有人会问那Director不是还要承担全部入向流量吗没错入向流量确实是单点入口但入向流量通常要比出向小不少比如视频、文件下载这类业务。就算下载请求大Director也只是转发请求包不需要兜底回包同样的网卡规格能扛住的并发连接数要高得多。1.2 DR模式的适用场景与限制DR模式最适合的场景是所有LVS节点都在同一个局域网内客户端访问的是VIP后端服务以HTTP、HTTPS、TCP四层接入为主。比如典型的Web集群、API服务网关、数据库读写分离前的负载均衡入口都很适合。限制也很明确。第一后端RealServer必须能和Director通过二层网络互通跨VLAN、跨网段就不能直接用DR强行用还要搞交换机的策略路由复杂度直接起飞。第二RealServer上必须配置VIP因为Director转发的数据包目标IP是VIPRealServer只有自己带上VIP地址内核才会收下这个包。第三客户端和RealServer的通信是“绕过Director”的所以如果业务有“源IP白名单”或者防火墙规则绑定客户端IP在RealServer上要特别注意回包源IP是VIP不是Director的IP。2. 核心原理拆解数据流、ARP与VIP的关系这一节是DR模式的重中之重。很多人配置不成功不是因为命令写错而是没搞懂数据包到底是怎么走的以及为什么RS上必须处理ARP问题。我把原理拆成三个小块来讲理解了这三块后面配置就是顺水推舟的事。2.1 一次完整请求的数据流全景假设客户端IP是192.168.100.50VIP是192.168.100.100Director、RealServer都在192.168.100.0/24这个广播域里。完整的请求过程如下客户端发起TCP连接目标IP是VIP 192.168.100.100目标MAC是VIP所在的Director网卡MAC地址。因为客户端要访问VIP会先发ARP请求询问“谁是192.168.100.100”这个ARP请求只会由Director回应。数据包到达Director网卡后Director发现目标IP是本机VIP地址于是把它交给IPVS处理。IPVS根据配置的调度算法选中一台RealServer比如192.168.100.11。Director把数据包的目标MAC地址改成RealServer的MAC地址源MAC地址改成Director出接口的MAC地址但IP层完全不改源IP还是客户端IP目标IP还是VIP。然后数据包从Director的物理网卡重新发出在交换机上被转发给RealServer。RealServer收到这个二层帧后先看目标MAC是不是自己再看目标IP是不是本机地址因为我们在RS的lo接口上绑定了VIP所以RealServer会认为这就是发给自己的包交给上层应用处理。RealServer处理完毕生成响应数据包。响应包的源IP是VIP目标IP是客户端IP。RealServer查路由表发现目标客户端IP不是本网段会交给默认网关处理这个包直接绕过Director发出去了。整个过程看下来Director只在入站方向“借路”了一下回包路径完全由RealServer自己走。这也是DR模式能打高吞吐量的核心原因Director不必处理一半以上的网络流量。2.2 为什么必须处理ARP问题这里有一个很隐蔽但致命的坑。如果我们在每台RealServer上都绑定了VIP那么当客户端或网关发ARP请求“谁是192.168.100.100”的时候所有绑定了VIP的机器都会应答包括所有RealServer。这样客户端拿到的ARP表就会飘忽不定一会儿指向Director一会儿指向某台RealServer。一旦ARP解析到了RealServer客户端会直接尝试通过二层访问VIP绕过Director负载均衡就失效了。更严重的是RealServer上虽然有VIP但并没有完整的LVS转发规则最终结果是大量请求超时、连接失败。解决思路非常经典让RealServer上的VIP“只收包不应答ARP”。具体做法就是把VIP绑到RealServer的loopback接口上并配置内核参数arp_ignore1和arp_announce2。arp_ignore1的意思是对本机收到的ARP请求只有请求的目标IP正好落在接收网卡的本地地址上时才回应。因为VIP在lo接口上外部网卡上的目标IP并不匹配所以RS不会回应外部ARP请求。arp_announce2的意思是在发送ARP请求或回应ARP请求时尽量使用发送网卡上的IP作为源IP避免系统自动选了VIP作为源地址导致ARP应答混乱。还要注意Director上的VIP配置。Director的VIP是在外部网卡上以“从IP”形式存在的比如eth0:0这样Director才会正常应答客户端对VIP的ARP请求。如果也把VIP放到Director的lo接口上并开启抑制Director就可能不响应外来ARP客户端根本找不到VIP的MAC地址一样是全盘崩溃。2.3 RS上配置VIP的核心细节RealServer上配置VIP时最常见的写法是ip addr add 192.168.100.100/32 dev lo这里有个关键点掩码必须是/32不能按物理网段的掩码配成/24。为什么因为如果配成192.168.100.100/24系统内核会认为整个192.168.100.0/24网段都挂在lo接口上路由表会发生变化。RealServer在处理回包时可能认为目标客户端192.168.100.50属于本机直连网段直接把回包从lo口发出导致丢包。就算没丢包也可能引发对本地网段的ARP广播破坏整个网络。所以VIP掩码一律用/32这是DR模式的标准姿势。另外很多老资料会让配置lo:0这个子接口用ifconfig lo:0 192.168.100.100 netmask 255.255.255.255 up。在现代Linux发行版上直接用ip addr add ... dev lo效果完全一样。区别只是设备名显示为lo而不是lo:0。我建议用ip命令更直观也更好维护。内核参数也需要固化到sysctl配置里否则重启后ARP抑制失效。建议在每台RS上写入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 EOF sysctl -p如果你机器上有多块外部网卡我建议对每一块实际承载流量的网卡名也加上相同参数比如eth0、eth1分别设置。虽然all.*可以覆盖全部接口但在某些内核版本里接口配置优先级会高于all配置单独设置更保险。3. 从零搭建一套DR模式负载均衡集群理论说完了直接上手。下面这套环境是我在一台测试交换机上常用的标准拓扑所有节点都用最小化安装的LinuxIP规划也写清楚方便你照着复现。3.1 拓扑设计、IP分配与基础准备我规划了一套三节点环境Directoreth0 192.168.100.10/24同时设置VIP 192.168.100.100/32挂在eth0上RealServer1eth0 192.168.100.11/24VIP 192.168.100.100/32挂lo上RealServer2eth0 192.168.100.12/24VIP 192.168.100.100/32挂lo上默认网关192.168.100.1客户端192.168.100.50需要强调的是所有这些节点必须在同一个二层广播域里。如果你用的是物理交换机需要确认端口没有开“端口隔离”或“私有VLAN”之类的功能如果是在云环境里的VPC内大多数虚拟网络支持ARP广播但有些安全组会拦截ARP必须提前测试。在Director上先安装IPVS相关工具# Debian/Ubuntu apt update apt install -y ipvsadm # RHEL/CentOS yum install -y ipvsadm安装完成后立刻检查内核是否加载了IPVS模块lsmod | grep ip_vs如果输出为空用modprobe加载modprobe ip_vs modprobe ip_vs_wrr modprobe ip_vs_wlc3.2 Director端IPVS配置我先在Director上配置DIP和VIPip addr add 192.168.100.10/24 dev eth0 ip addr add 192.168.100.100/32 dev eth0然后开启数据包转发。虽然DR模式严格来说不像NAT模式那样依赖ip_forward但生产实践里我还是建议打开避免因为路由判断问题导致转发失败sysctl -w net.ipv4.ip_forward1接下来配置IPVS规则。目标是创建一个TCP VIP服务端口80使用加权轮询调度算法两台RS权重分别设为1和2ipvsadm -A -t 192.168.100.100:80 -s wrr ipvsadm -a -t 192.168.100.100:80 -r 192.168.100.11:80 -g -w 1 ipvsadm -a -t 192.168.100.100:80 -r 192.168.100.12:80 -g -w 2 ipvsadm -L -n这里的-g表示使用Gatewaying也就是DR模式非常重要。如果你写成-m就成了NAT模式请求会进到RS后因为目标IP还是VIP、RS又没有正确的网关配置而直接失败。查看当前连接统计ipvsadm -L -n --stats我应该能看到类似下面的输出表示两台RS已经加入调度池IP Virtual Server version 1.2.1 Prot LocalAddress:Port Scheduler Flags - RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.100.100:80 wrr - 192.168.100.11:80 Route 1 0 0 - 192.168.100.12:80 Route 2 0 0Forward这一列显示Route说明DR模式生效了。3.3 RealServer端VIP与ARP参数配置每台RealServer上都需要做三件事绑定VIP到lo配置ARP抑制确认服务监听正常。第一件事绑定VIPip addr add 192.168.100.100/32 dev lo第二件事配置ARP抑制参数确保RS不对外应答VIP的ARP。我建议通过sysctl配置文件写入方便重启后保留cat /etc/sysctl.d/99-lvs-dr.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 EOF sysctl --system第三件事确认后端服务真的在监听。这里的细节是很多服务默认只监听0.0.0.0或具体业务IP如果它只监听了192.168.100.11那么请求的目标IP是192.168.100.100时内核虽然接受包但应用进程不监听这个IP连接依然会失败。所以要么让服务监听0.0.0.0要么在服务配置文件里把监听地址改成VIP或者同时监听多个地址。我一般测试时直接用nc -l -p 80或者一个简单HTTP服务监听0.0.0.0来验证。测试时我习惯先在RS上直接验证VIP连通性ping -c 3 192.168.100.100 curl -H Host: 192.168.100.100 http://127.0.0.1/通过本机回环验证VIP能通至少说明在内核层面VIP是存在的。3.4 效果验证从连接表到业务测试配置完成之后从客户端发起访问for i in $(seq 1 10); do curl -s http://192.168.100.100/ | head -n 1; done然后在Director上查看连接调度结果ipvsadm -L -n --stats如果一切正常两台RS的ActiveConn会随着权重比例增长。权重1和权重2理论上RS2接收的连接数大约是RS1的两倍。如果完全没流量先检查客户端能否ping通VIPping -c 1 192.168.100.100如果ping不通大概率是Director没有正确应答ARP或者是交换机学习了错误的MAC地址。这时在客户端查看ARP表arp -n | grep 192.168.100.100VIP对应的MAC应该是Director物理网卡的MAC而不是RS的MAC。如果是RS的MAC说明RS的ARP抑制没有生效回包路径和入口路径都乱了。4. 调度算法与高可用组合使用DR模式跑通只是第一步。真正的生产环境要考虑的不只是“能转发”还有“怎么转得聪明”和“Director挂了怎么办”。这一节我主要讲调度算法选型以及用Keepalived把VIP做漂移。4.1 生产环境常用的调度算法选型常被问到的调度算法有rr、wrr、lc、wlc、sh、dh。我简单说说在DR模式下的效果rr轮询每台RS轮流接收新连接。适合所有RS配置差不多的场景调度开销小。wrr加权轮询在轮询基础上给不同RS分配权重适合后端机器配置不同、或者希望按比例分配的场景。lc最少连接记录每台RS当前活跃连接数新连接分给活跃连接最少的RS。适合请求处理时间差异大的业务。wlc加权最少连接在最少连接基础上叠加权重是很多发行版默认算法。如果你的业务没有明确偏好用wlc通常不会出大错。sh源地址哈希按客户端源IP做哈希同一源IP的请求固定打到同一台RS。适合需要Session保持的简单场景但要注意一旦RS宕机哈希仍然会把它的一部分流量分给其他RS会短暂打乱会话。dh目标地址哈希按目标地址哈希多用于广域网的负载均衡场景普通服务里用得少。我自己的习惯是后端能力非常均衡时用rr有明显能力差异用wrr如果是长连接、在线用户数波动明显的服务用wlc更好。比如消息推送网关在线连接数差异很大RR可能导致某台RS连接堆积WLC就能平滑分配。在IPVS里修改算法很简单ipvsadm -E -t 192.168.100.100:80 -s wlc-E表示编辑已存在的虚拟服务配置。这个命令会保留RS列表只修改调度算法。4.2 权重模型与连接数观察权重并不直接等于流量比例它影响的是“新连接分配权重”而不是带宽权重。想像一下两个RSweight分别是1和2意味着一轮完整分配里RS1接收1个新连接RS2接收2个新连接。但如果某个连接是长连接占据了很久的活跃连接数后面进来的新连接还是会按权重轮流分配不会自动避开“已经很忙”的RS。所以真正的生产环境要结合算法来理解权重wrr只看权重wlc看权重和活跃连接数两个因素。查看实时连接率可以用ipvsadm -L -n --rate ipvsadm -L -n --stats--rate显示每秒速率--stats显示累计值。我通常在压测时开两个窗口一边压一边盯stats里的ActiveConn和InActConn。如果发现某台RS的InActConn一直很高说明大量半开连接堆积在它上面需要检查健康检查策略、后端应用响应速度而不是急着调权重。4.3 用Keepalived实现VIP漂移与健康检查单台Director如果宕机VIP就丢了。最常见的高可用方案是部署两台Director用Keepalived做VRRP协议VIP会在主备之间漂移。Keepalived还能兼任后端RS的健康检查发现RS异常后自动摘除IPVS规则。我给出一个精简的Keepalived配置模板Master和Backup两台Director都要安装Keepalivedapt install -y keepalived主节点的keepalived.confglobal_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.100.100/32 dev eth0 } } virtual_server 192.168.100.100 80 { delay_loop 6 lb_algo wrr lb_kind DR protocol TCP real_server 192.168.100.11 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.100.12 80 { weight 2 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }Backup节点只需要把state改成BACKUPpriority改成低于100的值比如90virtual_router_id、VIP、RS列表和算法保持一致。Keepalived会自动维持vtp状态当Master故障或网络不可达时Backup接管VIP并重新配置IPVS规则。这里有几个容易踩的坑lb_kind必须写成DR如果沿用NAT默认配置Keepalived生成的IPVS转发类型会不对。virtual_router_id在同一组高可用节点里必须一致两边的实例ID不一样的话VRRP包没法互通。如果Keepalived和手工配置的IPVS规则冲突要先清理掉旧的ipvsadm规则让Keepalived自己管理。不要在Master和Backup上同时手工绑定VIPVIP交给Keepalived统一管理否则两边都响应ARP客户端会随机选到错误节点。5. 常见故障排查与避坑实录我在维护DR模式集群时遇到过的故障并不少。很多问题表面是网络不通根子却在对ARP理解不到位。下面把典型问题整理成一张速查表再挑几个高频问题展开讲讲。5.1 故障现象速查表现象可能原因快速定位/解决客户端ping不通VIPDirector上VIP未绑定或ARP不应答在Director上确认VIP在物理网卡上ip addr showtcpdump抓ARPVIP能ping通但业务连接失败RS上服务没监听VIP或RS上VIP绑定缺失在RS上ip addr show确认VIP在loss -lnt确认服务监听地址业务时好时坏RS的ARP抑制配置没生效客户端ARP表指向了RS在客户端arp -n查看VIP的MAC在RS上检查sysctl参数某台RS流量严重偏高权重配置不合理或调度算法不适合长连接用ipvsadm -L -n --stats看ActiveConn分布调整权重或算法Director重启后IPVS规则消失没有持久化或交给Keepalived管理用ipvsadm-save /etc/sysconfig/ipvsadm保存或直接用Keepalived连接建立报文到RS了回包却丢RS上VIP用了非/32掩码路由表混乱改回192.168.100.100/32 dev lo健康检查显示RS异常业务却正常TCP_CHECK端口或超时设置不合理检查实际监听端口把connect_timeout适当调大或改用HTTP_GET跨网段客户端访问不通DR模式要求同二层跨网段未处理路由改用TUN模式或先打通二层/VLAN5.2 典型问题深入排查第一个高频问题是“VIP能ping通但curl就是不通”。我会先在各节点上抓包思路是分段验证在Director上抓入向包tcpdump -i eth0 -n tcp port 80 and host 192.168.100.50在RS1上同时抓包tcpdump -i eth0 -n tcp port 80 and host 192.168.100.50如果Director看到SYN包但RS1什么都没收到说明转发环节出了问题。来确认转发类型ipvsadm -L -n看到Forward列是不是Route。如果之前误配成了Masq转发逻辑就变成了NAT但RS上并没有把网关指向Director回包会走缺省网关于是连接建立失败。如果RS1能收到SYN包但客户端始终没收到SYN-ACK那问题多半在回包路径。在RS1上ip route get 192.168.100.50看看出接口是不是走eth0、下一跳是不是正确网关。如果结果里出现dev lo并且源IP是192.168.100.100多半是RS的VIP掩码配错了改回/32就能解决。第二个高频问题是“ARP抑制配了但RS还是会应答VIP”。这通常是因为sysctl参数没有落到具体网卡。我建议把eth0也加一遍sysctl -w net.ipv4.conf.eth0.arp_ignore1 sysctl -w net.ipv4.conf.eth0.arp_announce2如果还是不生效检查是否开启了NetworkManager的“接口接管”逻辑它可能在网络重启时把sysctl配置重置掉。最简单的做法是使用/etc/sysctl.d/下的独立配置文件并执行sysctl --system重载。另外注意有些内核版本下对lo接口的arp_ignore设置要用net.ipv4.conf.lo.arp_ignore不要只设置all。第三个问题是“Keepalived主备状态正常但漂移后VIP访问不了”。这种情况十有八九是Backup节点上没有正确加载IPVS规则或者RS上的VIP与Director漂移后的ARP表冲突。先看Keepalived日志tail -n 50 /var/log/syslog | grep Keepalived确认是否真正抢占了VIP。然后在Backup上ipvsadm -L -n如果没有规则说明Keepalived的virtual_server配置没有正确加载优先检查lb_kind DR是否生效以及real_server配置格式是否正确。5.3 几个容易被忽略的性能调优点DR模式虽然吞吐量高但入口流量还是全部经过Director。所以我通常建议关注这几个点第一Director的物理网卡不能太差。因为入向请求包虽然小但PPS包速率可能很高一块网卡要处理所有连接请求的ARP、TCP三次握手和转发。建议使用多队列网卡并配合RPS/RFS把数据包分散到多个CPU核心处理。系统层面可以开启irqbalance服务也可以手工把网卡中断绑定到不同CPU。第二IPVS连接表本身是全局表会保存每条连接的元数据。连接数非常多时可以观察cat /proc/net/ip_vs_conn如果这个文件上亿行说明连接表压力大。需要合理配置ip_vs_conn_tab_bits参数在加载模块时通过modprobe设置但这属于内核级调优生产环境改动前一定要压测。第三RealServer上的回包路径要确保没有额外占用。因为回包不经过Director所以不需要在RS上设置指向Director的特殊路由。相反如果RS有多张网卡务必确认默认路由走的是对外通信的网卡否则回包可能从一张“业务内网卡”发出导致客户端拿不到响应。第四对TCP连接状态做合理调优。RS直接和客户端建连容易积累大量TIME_WAIT连接特别是短连接场景。可以根据业务情况调整sysctl -w net.ipv4.tcp_tw_reuse1 sysctl -w net.ipv4.tcp_fin_timeout30注意不要盲目开启tcp_tw_recycle新内核已经移除且NAT环境下容易导致连接失败。6. 我的实战体会与几个建议做LVS DR模式这几年我最大的感受是这方案本身不复杂但每个细节都像是“一票否决制”的关卡稍有不慎就从“能通”变质为“时好时坏”。这里分享几个我总结的体会。6.1 最容易翻车的几个认知误区第一个误区是“DR模式可以跨网段”。我在刚开始搭建时也这么想过但实测会告诉你必须保证二层可达。后来做跨机房方案我直接换了TUN或别的负载均衡方案再也没有纠结过。第二个误区是“只要在RS上绑了VIP就行”。实际上如果ARP抑制没做RS会抢答VIP的ARP请求整个集群会莫名其妙地间歇性不可用排查起来非常难。我现在每次配置完都会在客户端反复检查VIP对应的MAC地址。第三个误区是“Keepalived负责所有事”。Keepalived只负责VIP漂移和RS健康检查它并不知道RS上的软件业务是否真实可用。如果服务端口活着但响应已经卡死TCP_CHECK依然可能返回正常这时就需要自定义健康检查脚本比如HTTP_GET并匹配返回内容。还有一点DR模式的RS上直接暴露了VIP回包源IP也是VIP。这意味着如果后端应用日志里按客户端IP做限流看到的都是真实客户端IP这点比NAT模式好用但如果业务代码里强制校验“源IP必须是某个网段”就需要注意VIP不在源IP白名单里可能产生误拦截。6.2 从测试到上线的稳健路径如果你是第一次搭DR集群我建议的路径是先用最小化拓扑在测试网络里跑通再用压测工具模拟流量最后再接入Keepalived。整个过程中先把纯粹的IPVS转发验证完不要让高可用和业务细节混在一起干扰判断。上线前要做几次“故障演练”拔掉一台RealServer的网线看Keepalived是否摘除它停掉Keepalived主进程看VIP是否漂移再恢复看回切是否正常。这些动作能暴露出配置里隐藏的问题比如健康检查间隔太短导致频繁抖动或者VRRP优先级差太小导致主备频繁切换。最后再分享一个小技巧把部署里的所有命令和参数写成脚本版本化保存。我每套集群都会写两个脚本一个是Director初始化脚本一个是RS初始化脚本。这样下次扩容只要执行脚本就能避免手工操作漏掉某个ARP参数。DR模式的价值在于高性能和简洁但生产环境的稳定性往往来自这些“笨功夫”的积累。