
说到Linux负载均衡LVS的NAT、DR、TUN三种模式是绕不开的话题。很多刚接触的人容易被一堆名词和参数劝退其实这三种模式的核心差异就一条请求包怎么发出去响应包怎么回来。我在生产环境里三种模式都实际部署过也踩过不少坑这篇文章打算把原理、配置、选型逻辑和典型故障一次讲清楚适合刚接手LVS、准备做负载均衡方案或者正在排障后想系统补课的人参考。1. 三种模式的核心思路与选型逻辑1.1 数据转发的本质区别先打个比方。LVS里的VIP虚拟IP就像公司的统一对外门牌所有客户端请求先打到VIP再由调度器决定把请求转给哪台真实服务器RS。三种模式的区别在于“转交”和“回话”的方式。NAT模式最直观客户端访问VIP的包到了LVSLVS把包的目标IP从VIP改成某台RS的IP必要时还能把端口一起改掉然后发给RS。RS处理完回包的目标是客户端IP但它自己发出去的包源地址是RS的IP客户端不认所以回包必须先回到LVS由LVS把源IP改回VIP再发出去。这个模式里LVS既是入口又是出口请求和响应都从它走。DR模式则是另一套玩法LVS收到包后不改IP层的东西只把以太网帧里的目标MAC地址改成选中的RS的MAC地址然后数据包通过二层网络直接送给RS。RS本身在环回接口上配置了VIP所以收到包后看到目标IP是VIP会觉得这就是发给自己的。处理完响应源IP直接写成VIP目标IP是客户端IP用自己的路由表就能发回客户端完全不用再经过LVS。TUN模式把DR的思路再往前推一步LVS收到请求后给原始IP包外面再套一个新IP头外层源IP是LVS自己的真实IP外层目标IP是RS的真实IP就像一个加密信封。RS拆开外层封装后看到内层目标IP是VIP本地又配置了这个VIP就收下处理。响应包同样由RS直连客户端LVS只负责入口分发。一句话总结NAT改IPDR改MACTUN加一层IP封装。1.2 三种模式适用场景与选型参考NAT模式最省事后端RS可以是任意操作系统只要IP通就行RS不需要知道VIP的存在也不需要额外配置。这非常适合RS数量少、业务流量不大、希望快速上线的场景。缺点是调度器要扛住所有进出流量流量一大网卡和CPU都会先成为瓶颈。DR模式是我在自建机房场景里最常用的模式。它不修改IP报文响应直接从RS回到客户端LVS只处理入站请求性能最好。但前提是LVS和所有RS必须在同一个二层广播域内RS还要在lo接口上配置VIP并做好ARP抑制不然VIP会被多台机器抢答。TUN模式解决的是DR不能跨网段的问题。LVS和RS之间只需要三层路由可达因此可以把不同机房的机器拉进同一个集群。当然代价是每包都要做IPIP封装和解封装RS必须支持IPIP隧道MTU这类问题也要处理。生产里TUN用得相对少但在某些跨机房容灾场景下它是LVS体系里唯一能打的方案。选型时我一般先问三个问题RS和LVS是不是同一二层网络入口和响应流量比例大概是多少后端服务要不要做端口映射如果同机房、端口一致、追求性能DR。如果只是小规模集群、后端端口不统一NAT。如果确实要跨机房统一调度再考虑TUN。2. NAT模式原理与配置实录2.1 数据流向拆解我拿一个具体例子来拆NAT模式的完整链路。假设客户端IP是192.168.1.10VIP是192.168.1.100LVS的内网IP是192.168.1.101RS的IP是10.0.0.2后端服务监听8080端口。请求阶段客户端发一个TCP SYN到192.168.1.100:80。LVS收到后按调度算法选择了10.0.0.2这台RS于是把包的目标IP改成10.0.0.2目标端口改成8080源IP保持192.168.1.10不变。LVS开启IP转发后这个被改写的请求包走三层路由到达RS。响应阶段RS处理完后回包的目标IP是客户端192.168.1.10源IP是10.0.0.2:8080。因为RS的默认网关配置成了LVS的内网IP这个回包会回到LVS。LVS查到IPVS里维护的连接跟踪记录知道这是之前那条访问VIP:80连接的回包于是把源IP改回192.168.1.100:80再发给客户端。客户端看到的始终是VIP在跟自己通话完全感知不到后端RS。这个连接跟踪表是NAT模式能正常工作的核心。如果RS的默认网关没指到LVS或者中间路由器把回包从别的路径直接送回客户端客户端就会收到一个源IP为10.0.0.2的响应包跟它请求的VIP对不上连接直接失败。2.2 NAT模式配置要点与完整示例配置流程不复杂但有几个关键点容易漏。第一步是在LVS节点开启IP转发不然改写后的包不会往RS方向走。sysctl -w net.ipv4.ip_forward1然后用ipvsadm定义虚拟服务和真实服务器。-m参数表示使用NAT模式masquerade。ipvsadm -A -t 192.168.1.100:80 -s rr ipvsadm -a -t 192.168.1.100:80 -r 10.0.0.2:8080 -m -w 1 ipvsadm -a -t 192.168.1.100:80 -r 10.0.0.3:8080 -m -w 1 ipvsadm -Ln这里可以看到端口从80映射到了8080NAT模式天然支持VIP端口和RS端口不一致后端服务根本不需要知道外面暴露的是什么端口。RS侧最关键的一步是把默认网关指到LVS。以CentOS风格简单示意ip route add default via 192.168.1.101 dev eth0实际生产环境建议直接用发行版的网络配置文件固化避免重启后丢失。如果RS和LVS不在同一网段则需要让路由表里所有回客户端的流量都经过LVS这个下一跳。还要注意iptables的FORWARD链。NAT模式下请求和响应都走LVS转发如果FORWARD策略是DROP即使转发已开启流量也会被防火墙拦住。排查时可以先查看iptables -L -n -v如果规则太多先临时放行内网段测试确认通了再收敛成业务规则。2.3 优缺点和典型问题NAT的优点我前面提过RS零感知、支持端口映射、任意操作系统都能接入。缺点也很明显调度器需要承担请求和响应的双向流量。我见过一个下载业务请求包很小响应包动辄几MBLVS网卡被下行流量打满后端RS的CPU还有大量空闲。这种场景用NAT模式就是典型的选型问题。常见故障里最频繁的是RS默认网关配置错误。现象是客户端curl VIP一直超时LVS上用ipvsadm -Lnc看连接状态卡在SYN_RECV说明请求转发到了RS但回包没回到LVS。另一个常见问题是连接跟踪表被打满。NAT模式每一条连接都会消耗一张conntrack表项高并发时如果默认表项不够新连接会被丢弃。可以调大sysctl -w net.netfilter.nf_conntrack_max1048576同时降低某些协议的过期时间比如TCP的ESTABLISHED超时。不过更根本的方案还是评估是否该换成DR模式。还有一个小细节NAT模式下后端RS能看到真实客户端IP吗能。因为LVS只改了目标IP源IP一直是客户端IP。对需要做日志分析和来源封禁的业务来说这一点很友好。3. DR模式原理与配置实录3.1 MAC改写机制DR模式最让人困惑的是“为什么RS上也要配VIP”。其实这正是它能高性能回包的根基。LVS收到请求后查IPVS表找到RS但IP层的源IP、目标IP都不动只把帧头的目标MAC改成RS网卡的MAC。这时RS必须认为自己拥有这个VIP才能把包收下来。由于RS也配了VIP如果不做额外处理整个二层网络里的ARP请求就会出问题客户端问“谁是192.168.1.100”LVS和RS都有这个IP大家都抢着响应ARP表就会乱。解决办法是把RS上的VIP绑到环回接口lo上并且设置内核参数让RS不对VIP的ARP请求做响应。这样整个广播域里只有LVS的VIP是对外可见的RS只是默默收包。回包路径跟NAT完全不同。RS处理完请求后源IP直接写成VIP目标IP是客户端因为RS的默认路由通常是指向机房网关而不是LVS响应包就会绕过LVS直接回到客户端。这就是DR模式高性能的关键所在入口流量过一次LVS出口流量完全由RS自己发。3.2 DR模式配置要点与完整示例先看LVS侧的配置。以VIP 192.168.1.100、LVS物理IP 192.168.1.101、RS1 192.168.1.11、RS2 192.168.1.12为例。ipvsadm -A -t 192.168.1.100:80 -s wrr ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.11 -g -w 1 ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.12 -g -w 1-g参数表示Gateway模式也就是DR。注意没有指定端口因为DR不改IP层通常要求RS端口和VIP端口保持一致。RS侧需要做三件事配置VIP、抑制ARP、确保回包路由正确。我建议把下面这段写成一个开机启动脚本按顺序执行。sysctl -w net.ipv4.conf.all.arp_ignore1 sysctl -w net.ipv4.conf.all.arp_announce2 sysctl -w net.ipv4.conf.lo.arp_ignore1 sysctl -w net.ipv4.conf.lo.arp_announce2 ip addr add 192.168.1.100/32 dev lo:0 ip link set lo:0 up这里要特别强调VIP掩码必须写成255.255.255.255也就是/32。如果写成24位掩码RS会认为自己拥有整个192.168.1.0/24网段对这个网段里的所有ARP请求都响应VIP冲突会非常严重。为什么把VIP绑在lo而不是物理网卡上因为lo接口不会主动参与二层ARP响应再配合arp_ignore参数就能做到“本地有VIP但不对外宣称”。这个设计是DR模式一切性能优势的前提。3.3 ARP问题的避坑经验我在初期切换DR模式时犯过一个经典错误只给RS加了VIP没加ARP抑制。结果和预期一样客户端访问时好时坏。有时候第二次刷新就超时后台看都没异常最后在客户端上执行arp -n发现VIP对应的MAC地址在几台机器之间跳来跳去。后来才理解arp_ignore和arp_announce这两个参数必须配合使用。arp_ignore1的意思是只回答目标IP属于本接口地址的ARP请求。VIP在lo接口上物理网卡收到的ARP请求虽然目标是VIP但物理网卡接口地址里并没有VIP所以不响应。arp_announce2的意思是发送ARP报文时尽量使用能匹配目标网段的源地址避免用VIP去应答外界对LVS的ARP请求。这两条缺一不可。还有一个容易被忽略的坑有些发行版默认开启了反向路径过滤rp_filter如果网络环境特殊可能需要在RS上临时关掉某个接口的rp_filter否则收到的请求包可能被当成“源地址不可达”而丢掉。另外在云平台或者SDN环境里部署DR模式要格外小心。很多虚拟网络不允许RS在环回接口上私自宣告VIP也不保证二层广播域可控。这种情况下我一般会先用NAT顶着或者改用七层负载均衡而不是花大量时间去跟云平台网络策略较劲。4. TUN模式原理与配置实录4.1 IP隧道封装细节TUN模式的全称其实是IPIP隧道模式。它的核心是在原IP包外面再套一个新IP头。举个例子客户端发了一个目标IP为VIP的请求包到LVSLVS选择了一台RS然后把整个原始包封进新的外层包外层源IP是LVS自己的出口IP外层目标IP是RS的真实IP。这个外层包可以走普通的三层路由所以LVS和RS不需要在同一个二层网段。RS上有tunl0隧道接口专门接收IPIP封装包。收到后内核把外层头剥掉剩下的内层包目标IP还是VIP如果RS本地配置了这个VIP就正常收包处理。响应包从RS直接回客户端源IP为VIP整个路径跟DR一样绕开了LVS。这种设计最大的好处就是跨网段。只要RS的真实IP能被LVS路由到远端机房里的Linux机器也可以加入当前集群。但代价是每个请求多一层IP头MTU会变小。默认情况下以太网MTU是1500原始包如果已经接近1500再加上20字节外层IP头就会超过链路MTU产生分片。很多TUN模式“大包不通”的问题都出在这里。4.2 TUN模式配置要点与完整示例LVS侧的配置和前面差不多只是-m换成-i表示tunnel模式。modprobe ipip sysctl -w net.ipv4.ip_forward1 ipvsadm -A -t 192.168.1.100:80 -s rr ipvsadm -a -t 192.168.1.100:80 -r 10.0.0.2 -i -w 1 ipvsadm -a -t 192.168.1.100:80 -r 10.0.0.3 -i -w 1RS侧需要加载ipip模块、启用tunl0接口并配置VIP。modprobe ipip ip link set tunl0 up ip addr add 192.168.1.100/32 dev tunl0 ip link set tunl0 mtu 1480 sysctl -w net.ipv4.conf.all.arp_ignore1 sysctl -w net.ipv4.conf.all.arp_announce2 sysctl -w net.ipv4.conf.tunl0.rp_filter0 sysctl -w net.ipv4.conf.all.rp_filter0这里把VIP绑到tunl0同时还是要做ARP抑制。很多人以为隧道接口不参与ARP就没事但VIP一旦配到了本机物理网卡在收到目标为VIP的ARP请求时仍然可能响应所以参数不能省。MTU问题我习惯用两端配合的方式解决。隧道接口MTU设成1480然后TCP握手时强制MSS小一些iptables -t mangle -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360这样TCP层产生的报文不会超过1450左右封装后还能留在常规MTU范围内。实测下来对下载类大包业务很有效。如果不方便改MSS至少要保证链路各段都支持大于1500的MTU比如MSS上4500字节之类但没有多少人会为LVS单独调整整个交换网络。另外如果LVS和RS之间有防火墙必须放行协议号为4的IPIP流量而不是普通的TCP/UDP端口。我们曾经在RS的iptables里放行了80端口但没放IPIP协议结果LVS侧连接一直在SYN_SENTRS侧tcpdump完全没包。4.3 与DR/NAT的关键差异先用一张表把三种模式的关键属性列出来。维度NATDRTUN请求处理方式改目标IP和端口改目标MAC地址增加一层IP封装响应路径必须经过LVS直连客户端直连客户端跨二层网段支持不支持支持RS是否需要配置VIP不需要需要需要端口映射支持一般不支持一般不支持对外部系统要求任意OSLinux或可抑制ARPLinux且支持IPIP调度器压力高低中额外网络问题conntrackARPMTUTUN和NAT的差异主要在于回程路径。NAT模式调度器要处理全部回包TUN模式回包直连客户端所以同样流量规模下TUN的调度器压力远小于NAT。TUN和DR的差异在于跨网段能力DR依赖二层MAC改写跨不了路由器TUN用外层IP封装天然可以跨三层网络。但在服务器数量少、同机房部署时DR没有封装开销性能仍然优于TUN。5. 模式对比与生产环境选型建议5.1 性能、成本与可维护性对比性能上DR是最好的。它只改MAC不封装LVS只处理入站流量后端响应走各自路由整体转发链路的额外损耗几乎可以忽略。TUN次之封装和解封装会消耗一些CPU和内存而且MTU问题让运维成本变高。NAT最弱所有流量都要过LVS尤其响应远大于请求的业务调度器的网络带宽很快会成为天花板。成本上NAT最便宜RS不需要特殊配置只需要内网能通。DR需要维护二层网络和ARP抑制脚本RS上要管VIP生命周期。TUN需要每个节点支持IPIP协议跨机房时还要考虑专线带宽和MTU配置和网络排障成本都更高。可维护性方面NAT规则简单适合快速搭建DR的坑集中在ARP参数固定后会非常稳定TUN的坑更分散tunl0接口、rp_filter、MTU、防火墙协议放行任何一个环节出错都会表现为“连接不稳定”。我的经验是能DR就DR不能用DR再用NAT或TUN不要为了追求“高级”而强行上TUN。5.2 我的一次选型实战记录之前某个文件下载项目RS只有三台都在同一个机房。最初接的需求很简单看起来用NAT最快因为不用在后端做任何VIP配置。上线后果然踩了性能门槛下载响应包大LVS网卡流量轻松跑满后端CPU还不到30%。后来改成DR模式RS上写了个一键配置脚本把VIP和ARP参数固化进去同一个LVS设备扛住了之前三倍的下载流量调度器负载反而下降了。还有一次跨机房容灾想把两个机房的Linux服务器纳入同一个LVS集群。当时考虑TUN模式隧道配置也调通了但实际压测发现机房之间公网链路不稳定时TCP连接和数据包重传明显增多最后放弃了把远端RS直接挂进一个集群的想法改成各机房独立集群再在上层用DNS解析或四层网关做地域调度。这个案例说明技术可行不等于业务合适跨机房场景的网络质量永远是第一位的。6. 常见问题排查与避坑速查6.1 三种模式的典型故障现象可能原因排查思路VIP ping不通keepalived未启动或VIP没绑定LVS上ip addr show确认VIP检查keepalived状态访问超时后端没收到任何请求调度规则缺失、RS权重为0ipvsadm -Ln查看规则是否在RS上tcpdump抓包NAT模式连接卡在SYN_RECVRS默认网关错误、FORWARD链拦截RS上查默认路由LVS上看iptables FORWARDDR模式时好时坏VIP被多台RS响应ARP客户端arp -n看VIP对应的MAC检查RS的arp_ignore设置TUN模式小包通大包不通MTU超过链路承载用ping -M do -s 1472测试调整隧道MTU和TCPMSSTUN模式RS完全抓不到包防火墙没放行IPIP协议两端防火墙放行协议号4tcpdump -i tunl0确认6.2 排查工具与思路我平时排查LVS问题有四步。第一步看规则。用ipvsadm -Ln确认虚拟服务和RS都存在调度算法、权重、模式参数都对。这一步能解决大多数“规则没同步”的问题。第二步看连接。用ipvsadm -Lnc看当前连接状态。如果所有连接都停在SYN_RECV说明包已经进到LVS但没完成握手问题多半在转发路径上。如果状态是ESTABLISHED说明转发基本正常。第三步抓包。在LVS上抓VIP流量确认入站包到了在RS上抓对应源IP的流量确认RS有没有收到如果RS收到了但客户端收不到还要在RS的出口方向抓包确认响应包有没有发出去。# LVS上看VIP和80端口的入站包 tcpdump -i eth0 host 192.168.1.100 and tcp port 80 # RS上看是否有来自客户端的请求 tcpdump -i eth0 host 192.168.1.100 and tcp port 80第四步看路由和回收。NAT模式重点查RS默认路由是否指向LVSDR/TUN模式重点看RS本地是否配了VIP以及响应包是否走默认路由直出。还有一个新手容易误会的地方DR和TUN模式下LVS上只会看到客户端的入站连接看不到完整的双向流量。这是正常现象因为回包根本不经过LVS。如果拿NAT的思维去要求DR/TUN反而会误判为丢包。另外可以把ipvsadm -Ln --stats加进监控定期采集转发报文数和字节数。某台RS的报文数长期为0说明调度器可能把权重调成了0或者RS已经被摘除报文数在涨但业务成功率下降通常要考虑后端应用本身的问题而不是LVS。我个人在实际操作中的体会是三种模式没有绝对的好坏关键是先把“回程流量走哪条路”画出来再选型。NAT回程走调度器DR回程走后端TUN回程也走后端但多了封装。只要把这条曲线想清楚很多问题都能一眼看穿。最后再分享一个小习惯每次配置完DR或TUN我都会把sysctl参数和VIP绑定写成一个启动脚本放在RS上一并固化反复重启也不会丢。这个习惯帮我省掉了不少半夜排障的时间。