ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LVS三种模式实战:NAT、DR、TUN原理与配置全解析

LVS三种模式实战:NAT、DR、TUN原理与配置全解析 搞负载均衡的兄弟们应该都听过LVS这三个字母Linux Virtual Server从当年章文嵩博士的开源项目一直活到今天内核里自带IPVS模块稳得一批。这么多年过去了Nginx、HAProxy轮番上场但LVS依然在不少核心链路里稳如磐石尤其是NAT、DR、TUN这三种模式面试是高频考点实战中更是绕不开的硬骨头。这篇文章基于我自己在虚拟机环境里反复折腾三轮实验的完整记录把三种模式的原理差异、配置步骤、踩坑实录一次性讲清楚给你一份能直接抄作业的实践笔记。我第一次正经用LVS是好几年前在一套电商系统的压测环境里当时老架构师坚持用DR模式扛流量确实把后端压得很稳。后来我自己从零搭过NAT、DR、TUN三套集群从ipvsadm命令一路敲到keepalived做高可用把每个细节都摸了一遍才敢说真正理解这三种模式。这篇文章适合两类人一是刚接触LVS、不知道三种模式怎么选的新手二是用过LVS但说不清数据包走向、遇到问题只会重启的同行。看完之后你至少能搞清楚三种模式的核心差异以及生产环境里到底该选哪一种。1. 选型逻辑NAT、DR、TUN到底该怎么挑1.1 先搞清楚LVS在内核里的角色定位LVS全称Linux Virtual Server工作在TCP/IP协议栈的四层也就是传输层。它的核心组件是内核里的IPVS模块可以用ipvsadm这个用户态工具去管理。它做的事情用一句话总结把一组后端真实服务器RealServer简称RS伪装成一个虚拟IPVirtual IP简称VIP对外提供服务外部客户端访问的是VIP实际干活的是后面一堆RS。我习惯把LVS叫“调度器”而不是“负载均衡器”因为它在四层做的是转发调度的活儿——只看IP和端口不关心请求里的URL、Header、Cookie这些七层的东西。这和Nginx有本质区别Nginx是七层反向代理能根据路径、域名做高级路由LVS转发速度更快内核态处理基本不产生用户态拷贝而且不挑协议TCP、UDP都能转发。在动手配置之前必须先和自己确认一个问题你的业务场景到底需要哪种模式这个问题想不清楚后面全是白忙。很多新手上来就抄一段DR模式的配置结果后端服务器在另一个网段流量根本过不去最后只能一头雾水地到处查日志。对于不同基础的人来说我的建议是如果是第一次接触LVS先把三种模式的数据包流向图画明白再动手敲命令如果已经有一定经验直接跳到配置部分对比细节差异就行。1.2 三种模式的适用场景和性能差异先给一张我自己归纳的对比表后面再逐个展开原理和实操。模式核心机制请求路径响应路径后端要求适用场景NAT网络地址转换客户端 → LB → RSRS → LB → 客户端后端可用私有IP网关指向LB后端数量少、无独立公网IP、安全隔离要求高DRMAC地址改写客户端 → LB → RSRS → 客户端与LB同二层网络需抑制ARP大流量集群、吞吐量优先TUNIP隧道封装客户端 → LB → RSRS → 客户端可跨网段需支持IPIP隧道跨机房调度、后端分散部署选型逻辑我总结成一句话能选DR就选DR二层不通才考虑NAT或者TUN。DR模式响应不走LB吞吐量最高但要求调度器和后端在同一个二层网络里而且要对后端做ARP抑制配置这个细节是很多初次上手的人踩坑的地方。NAT模式适合后端服务器没有公网地址的场景调度器作为唯一的入口和出口安全隔离效果好但代价是所有流量都压在LB上到达一定量级后会成为瓶颈。TUN模式适合后端分散在不同机房、不同网段的场景通过IP隧道把请求封装转发过去配置复杂度最高还需要额外考虑MTU问题。2. 数据包流向拆解理解模式的关键一关2.1 NAT模式负载均衡器是唯一入口和出口NAT模式的全称是Virtual Server via Network Address Translation可以理解为调度器做了四层的“地址转换”。客户端请求到达LB的VIP之后LB通过IPVS规则把数据包的目标IP从VIP改成后端RS的IP然后再转发出去。RS处理完请求后把响应包发回给LBLB再把源IP从RS的IP改回VIP最后回给客户端。这个过程里有一个关键点客户端从头到尾只认识VIP它根本不知道后面有RS的存在。RS也以为自己在和LB通信它不回包给客户端而是回给LB。所以RS的默认网关必须指向LB的内网IP否则响应包就不知道往哪儿送了。这个配置看起来简单却是NAT模式最常用的故障点。我之前实验的时候遇到过一种情况RS上面能收到请求curl后端本机地址也正常但从外网访问就是不通。后来抓包一看RS把响应包发到了自己的默认网关——公网路由器上路由器收到一个源IP是私网地址的包直接扔了。把RS的默认路由改成走LB内网后问题立刻消失。NAT模式的另一个细节是要开启内核的IP转发功能echo 1 /proc/sys/net/ipv4/ip_forward这个参数告诉Linux内核允许把从一个网卡收到的包转发到另一个网卡去。如果不开LB收到包后直接丢弃整个集群就瘫痪了。对于NAT模式我还想多说一句客户端的连接状态问题。因为LB要维护NAT会话表所以连接跟踪conntrack模块会记录每一条连接的状态。在高并发场景下如果LB的内存不够大或者conntrack表项超时时间设置不合理可能因为表项爆满导致新连接被丢弃。生产环境里建议调一下net.netfilter.nf_conntrack_max参数。2.2 DR模式只改MAC地址的“暗送”DR模式全称Direct Routing是三种模式里性能最好、应用最广的一种。它的核心思想是LB收到客户端请求后并不修改IP层的信息只把数据链路层的目标MAC地址改成后端RS的MAC地址然后直接在这个二层网络里把包送过去。因为目标IP仍然是VIP而后端RS提前在lo接口上绑定了VIP所以RS能正常收下这个包并处理请求。这里有两个非常关键的前置条件。第一RS上必须绑定VIP通常是绑在lo回环接口上不能用物理网卡。第二RS必须配置ARP抑制不能对外响应关于VIP的ARP请求。如果不抑制ARRP后端服务器会把VIP的MAC地址广播出去路由器可能会把原本应该发给LB的请求直接转到RS上导致调度逻辑完全失控。我总结的DR模式标准RS配置脚本如下# RS上执行 ifconfig lo:0 192.168.100.100 netmask 255.255.255.255 up 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这里有个很多人不理解的地方为什么VIP的掩码要配成255.255.255.255原因是如果配成常规的24位掩码那么lo接口上绑定的VIP会与本地物理网卡产生路由冲突系统会认为这个IP属于本地网段从而触发不必要的ARP广播。配成全1掩码就是明确告诉内核这个IP是本机的但不要对它做任何网段相关的ARP通告。DR模式下响应包直接由RS发给客户端数据包源IP就是VIP客户端自然认为这就是服务器本人回的包。这样就完全绕开了LBLB只处理入站流量单台LB能扛的吞吐量被大大释放。当然啦代价是RS必须和LB在同一二层网络这是很多人一开始容易忽略的硬性约束。2.3 TUN模式IP隧道里的接力赛TUN模式全称IP Tunneling它解决的是DR模式没法跨网段的痛点。原理可以这么理解LB收到客户端请求后把原始数据包整个封装进一个新的IP包里外层源IP是LB的IP外层目标IP是RS的IP然后通过IP隧道发出去。RS收到外层包后拆包看到里面的目标IP是VIP而自己恰好又在lo接口上绑了VIP于是正常处理请求响应直接回给客户端。用生活化的类比来说TUN模式就像一个快递中转站。客户端把包裹寄到中转站VIP中转站拆开看了下发现收件人其实在另一个城市于是重新贴了一张新面单把包裹送到那台RS手上。RS拆开新面单发现实际收件人地址就是VIP自己正好负责这个地址就签收处理了。配置TUN模式需要内核支持IPIP协议并且可能需要加载相应模块# LB和RS都要执行 modprobe ipip在RS上需要建立一个叫tunl0的隧道接口并在这个接口上绑定VIP# RS上执行 ip tunnel add tunl0 mode ipip remote 0.0.0.0 local 0.0.0.0 ifconfig tunl0 192.168.100.100 netmask 255.255.255.255 up然后是LB上的调度规则调度算法我后面细说TUN模式的-t参数指定的是VIP-r指定的是RS的真实IP。TUN模式最大的坑是MTU问题。因为每个包都被额外套了一层IP头原始包大小如果太大隧道封装后可能超过链路的MTU导致分片或者直接丢包。经验做法是调整后端服务的TCP MSS或者把隧道接口的MTU调小再配合客户端和服务端的MSS协商。这个坑我在跨机房压测时踩得很惨大包传输一多就丢调低MTU之后才稳定下来。3. 亲手搭建三套集群完整操作记录3.1 实验环境规划与主机基础设置我在实验环境里用了四台虚拟机一台当客户端做压力测试三台当服务器。操作系统是CentOS 7.9内核版本3.10。生产环境用什么系统无所谓关键是内核自带IPVS和必要的隧道协议。主机名角色IP地址网卡说明client压测客户端192.168.122.50ens3用来发起HTTP请求lb01调度器192.168.122.10ens3承载VIPrs01后端1192.168.122.11ens3运行nginxrs02后端2192.168.122.12ens3运行nginx这个环境的巧妙之处在于四台机器都在同一个网段方便同时演示三种模式。如果要做跨网段实验只需要给rs01和rs02再加一个网段TUN实验就能展示出优势。开始之前要把一些基础问题处理干净不然配置完各种奇怪问题。首先确认内核模块modprobe ip_vs lsmod | grep ip_vs如果输出里有ip_vs字样说明内核已经支持。其次把SELinux关掉或者设置为宽松模式防火墙直接停掉或者只在必要端口放行。我在实验中直接停掉防火墙因为要排除干扰因素systemctl stop firewalld systemctl disable firewalld setenforce 0后端RS上需要安装并启动一个简单的HTTP服务。我用的是nginx主要图省事yum install -y nginx echo h1Server 192.168.122.11/h1 /usr/share/nginx/html/index.html systemctl start nginx后端每台的index.html内容不同方便测试时确认请求到底分发到了哪台机器上。3.2 NAT模式配置全过程NAT模式要规划两个IP一个VIP一个后端RIP。我的实验里VIP用192.168.122.100后端直接用现有的192.168.122.11和192.168.122.12。NAT模式对VIP位置没有特殊要求LB上哪块网卡绑VIP都行后端只要能路由到LB即可。第一步在LB上开启转发并把VIP绑定到物理网卡echo 1 /proc/sys/net/ipv4/ip_forward ifconfig ens3:0 192.168.122.100 netmask 255.255.255.255 up第二步配置IPVS调度规则用轮询算法ipvsadm -C ipvsadm -A -t 192.168.122.100:80 -s rr ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.11:80 -m ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.12:80 -m ipvsadm -L -n这里的参数要看清-A是新增一条虚拟服务规则-a是添加后端真实服务器节点-t指定协议类型为TCP-s rr使用轮询算法-r指定后端RS-m表示NAT模式。第三步把RS的默认网关指向LB的内网IP。这一步是关键一定要做# 在rs01和rs02上执行 route add default gw 192.168.122.10我为什么要把这一步单独拎出来强调因为默认网关这个东西如果你用正常上网的IP规划很可能已经是路由器地址了。如果RS的网关还是公网路由器它回包会直接发给路由器这包就彻底丢了。NAT模式下RS永远别把网关指向别处只能指向LB。配置完就可以在客户端测试访问了curl http://192.168.122.100/多执行几次应该能看到轮询返回不同RS的内容。如果curl不动大概率是RS网关问题先ping一下VIP确认LB上没有丢包再到RS上看默认路由。我在实验中还特意用tcpdump抓过包SYN包到达LB后LB把目标IP改路由RSRS回包源IP是RS自己的地址到了LB又被改回VIP地址。整个过程非常清晰建议你自己也抓一遍比看十篇文章都管用。3.3 DR模式配置全过程DR模式的环境要求和NAT完全不同它要求LB和RS必须在同一个二层网络并且RS不能用默认网关指向LB那一套因为响应包要直接回客户端。这就意味着如果客户端在另一个网段RS的默认网关必须指向实际的路由器保证回包能正常出去。LB部分先把VIP绑定在网卡的别名接口上ifconfig ens3:0 192.168.100.100 netmask 255.255.255.255 up然后配置IPVS规则注意最后面的参数从-m变成了-gipvsadm -C ipvsadm -A -t 192.168.100.100:80 -s rr ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.11:80 -g ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.12:80 -gRS部分需要把VIP绑定到lo接口的别名上同时配置ARP抑制参数ifconfig lo:0 192.168.100.100 netmask 255.255.255.255 up 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_announce2ARP抑制是DR模式的核心一旦配置有误可能会有两类问题。一类是RS对外宣告了VIP导致客户端请求被中途截胡另一类是RS不接收VIP包导致LB转发过去后无人应答。前者表现为请求到达RS后本机nginx报错后者表现为TCP连接建立不了。配置完在客户端同样执行curl多请求几次就能看到轮询效果。想确认数据包路径的话可以在RS上用tcpdump监听任意流量你会发现RS确实收到了目标IP是192.168.100.100的包而物理网卡上并没有这个IP。这正好证明DR模式通过MAC改写和VIP环回绑定实现了转发。注意DR模式下RS的VIP掩码一定也要配置成255.255.255.255不能配成255.255.255.0这是个容易犯又很隐蔽的错误。我刚开始配过一次网段掩码结果RS的路由表直接乱了物理网卡的默认路由被覆盖流量全部异常。3.4 TUN模式配置全过程TUN模式是在DR模式基础上做跨网段扩展的所以RS侧仍然要在lo上绑定VIP并且配置ARP抑制。区别在于LB和RS之间要建立一条IPIP隧道。先看LB配置。假设VIP还是192.168.100.100后端RS1在192.168.122.11RS2在192.168.122.12这两台RS和LB不在同一个二层网络里这时候用DR模式没法做改TUN模式就有戏。LB上把VIP绑到物理网卡并配置IPVS规则注意最后参数变成-iifconfig ens3:0 192.168.100.100 netmask 255.255.255.255 up ipvsadm -C ipvsadm -A -t 192.168.100.100:80 -s wrr ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.11:80 -i ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.12:80 -iRS上加载IPIP模块并建立tunl0接口在tunl0上绑定VIPmodprobe ipip ip tunnel add tunl0 mode ipip remote 0.0.0.0 local 0.0.0.0 ifconfig tunl0 192.168.100.100 netmask 255.255.255.255 up如果内核不支持modprobe ipip可能是内核配置里没编译这个模块需要重新编译内核或者换用包含该模块的系统。我的CentOS 7.9内核自带这个模块没有额外麻烦。TUN模式里RS的默认网关不需要指向LB响应包由RS自己发回客户端这一点和DR一致。但要注意跨网段时RS得保证客户端能路由回来。比如客户端在192.168.50.0网段RS自己在192.168.122.0网段那么RS的默认网关必须能路由到192.168.50.0网段否则响应包发不出去。我在实验里用wrw加权轮询算法目的是模拟生产环境后端性能不均的场景。如果你希望接下来重点看某个权重高的RS运行ipvsadm -L -n --rate能看到每个RS的连接数和权重比例。配置完成后从客户端访问VIP再用ipvsadm -L -n查看连接分布你会看到流量经过LB后被封装成隧道包发给RS。理论上跨机房、跨网段的场景都可以这么实现唯一要重点关注的就是MTU值。4. 高可用、压测对比与排坑经验4.1 keepalived实现VIP自动漂移单台LVS跑生产调度器挂了整个集群就废了这肯定不行。业界标准做法是keepalived做VIP漂移。keepalived通过VRRP协议让两台LB组成一个高可用集群正常情况下VIP在备用LB身上一旦主LB故障VIP自动漂移到备用LB客户端无感知。keepalived.conf的核心配置其实不复杂下面是我实验用的主LB配置global_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface ens3 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.122.100/24 dev ens3 } } virtual_server 192.168.122.100 80 { delay_loop 6 lb_algo rr lb_kind DR protocol TCP real_server 192.168.122.11 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.122.12 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }备LB的state改成BACKUPpriority改成90其余保持一致。注意keepalived配置里的lb_kind要和实际用的LVS模式对应。如果写错会出现VIP正常但流量不打到RS的情况。keepalived自带的健康检查会定期探测后端RS的TCP端口。如果RS的nginx挂了keepalived会自动把这条real_server从规则里摘掉请求就不会打到故障机器上。这个功能实际上是生产环境最刚需的部分比手工执行ipvsadm命令靠谱得多。我在实验中专门测试过一次手动停掉rs01的nginx然后观察ipvsadm输出。大约几秒后rs01就从规则列表里消失了所有流量都到了rs02。重启rs01的nginx后它又自动加回来。这个恢复过程完全不需要人工干预。4.2 常见故障排查速查表搞LVS最烦的就是现象看起来一模一样原因却五花八门。我把实验中遇到的典型问题整理成一张速查表遇到问题直接对号入座。故障现象可能原因解决办法curl VIP超时ping VIP通NAT模式下RS默认网关没指向LB在RS上执行route add default gw LB内网IP请求偶尔通偶尔不通轮询到某一台RS时报错RS的nginx挂了检查每台RS服务状态用ipvsadm -L -n看节点状态客户端能连上但页面白屏RS响应包过大超过链路MTU检查RS到客户端的链路MTU调整nginx的sendfile或调低MTU只有一台RS在接收流量调度算法问题权重配置异常查看ipvsadm -L -n --rate确认lb_algo和weight后续请求全部集中到同一条连接客户端开启HTTP keep-aliveLVS四层模式天然支持连接保持客户端连接不关闭就一直在同一RSDR模式下VIP地址冲突RS的ARP抑制配置没生效检查sysctl参数尤其是conf.lo.arp_ignore是否配置TUN模式大包丢失隧道封装导致MTU超限在RS上把tunl0的MTU调小或调整TCP MSSNAT模式下RS收到包但回不了RS的默认路由指向公网网关在RS上把默认路由指向LBkeepalived启动但VIP不漂移virtual_router_id冲突或者认证不一致检查两台LB的router_id和auth_pass是否匹配ipvsadm提示无权限内核模块没加载modprobe ip_vs后再执行ipvsadm这张表背后每个问题我都实际踩过。尤其是TUN模式MTU问题当时压测脚本一跑就丢包排查了很久才发现是隧道封装把包撑爆了。后来直接在内核参数里调整TCP MSS编辑问题才彻底解决iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu这个命令告诉防火墙自动调整TCP的MSS值让它和链路MTU匹配避免分片。4.3 实测数据与我的最终选型建议我在实验环境里用ab做了简单的HTTP压测单台LB、两台RS并发100总请求数10000。结果很直观DR模式吞吐量最高NAT模式大概是DR的六成TUN模式因为封装开销比DR稍低一些。这个比例在生产环境会受CPU性能、内核版本、网络拓扑影响仅供参考但趋势是一致的NAT模式天然要承担双倍流量性能上限最低。如果让我给一个最终选型建议我会这样说后端和LB在同一个机房同一个二层网络果断选DR这是吞吐量和配置复杂度之间最平衡的选择。后端没有独立公网IP或者你希望屏蔽后端的真实地址选NAT但一定要给LB足够的CPU和带宽并且规划好连接跟踪表的容量。后端分散在多个机房或者需要做跨地域容灾调度选TUN但提前把MTU调通不要等上线了再改。如果只是想做简单的四层负载均衡不想维护这么复杂的配置可以考虑直接用HAProxy或者Nginx的stream模块但LVS在性能上仍然有优势尤其在高并发TCP场景下。我个人在项目里用得最多的是DR模式加keepalived这套组合。配置成熟、坑都被人踩过了文档也全出问题翻社区经验很快就能定位。TUN模式我用的最少只有在跨机房容灾的场景下才动用因为每次调MTU和路由都够喝一壶的。最后分享一个实验里的小技巧在配置完LVS之后不要急着上压测工具先用ipvsadm -L -n --stats看一下每个RS的活跃连接数再用tcpdump抓VIP上的包对比实际转发路径。我见过太多同行把规则配好了curl通了就以为万事大吉结果压测一出并发就暴露问题。每次抓包对比一下数据包流经的接口和IP变化能让你对三种模式的理解深入一大截。这些实验做完之后我最大的感受是LVS这东西原理不下功夫配置抄再熟也只是个工具人把数据包走向吃透三种模式在你眼里就是一层窗户纸。
返回列表