做后端和运维的,迟早会和负载均衡打交道。网站流量一涨,后端服务一扩,第一反应就是加一层反向代理,比如Nginx。但Nginx跑在用户态,几万并发下来CPU软中断很难看,再往上顶就得在TCP层做文章。LVS(Linux Virtual Server)就是这一层的经典方案,它直接在内核态处理报文,纯转发的效率和吞吐量都不是用户态代理能比的。这篇文章我打算把LVS三种模式搭建这件事讲透,重点不是背命令,而是把NAT、DR、TUN的模式原理、适用场景、配置过程和踩坑点都过一遍,让看完的人能自己动手复现一套可用的四层负载均衡。
适合谁看呢?后端开发、运维工程师、刚接触负载均衡的架构师,都适用。如果你只是想临时分流量,那Nginx就够了;如果你在多台RS(RealServer)前需要一个高吞吐的统一入口,或者要扛几万甚至几十万并发,LVS这套东西值得花半天时间好好摸一遍。
1. LVS三种模式到底解决什么问题
1.1 从一个真实需求说起
先说一个我接过的小项目:某内部系统有三台Web后端,PHP和Java都在跑,需要一个统一入口把请求分发出去,还要能在某一台后端宕机时自动摘掉。第一版直接上了一台Nginx做七层代理,日常流量不大,看着没什么问题。后来做活动,瞬时连接数冲到几万,Nginx所在的机器软中断爆了,CPU飙到90%多,监控疯狂报警。
当时第一反应是Nginx调优,调了一轮还是不到一千的CPS(每秒新建连接数)就撞墙。后来换思路,把接入层往下压,四层负载交给LVS,入口只做一个VIP,后端三台机器通过调度算法分摊流量。这个方案跑起来之后,Director机器CPU占用基本个位数。这里的关键就不是“用什么命令”,而是先搞清楚LVS三种模式各自是怎么转发数据的,选错就是白搭。
1.2 三种模式的核心差异一张表看懂
LVS最常见的三种模式是NAT、DR、TUN。它们的共同点是都必须有一个Director作为LVS的核心调度器,都要有VIP(虚拟IP)和一组RS。真正的差异在数据包怎么被改、回包怎么走。
| 对比项 | NAT模式 | DR模式 | TUN模式 |
|---|---|---|---|
| 流量路径 | 请求和响应都经过Director | 请求经过Director,响应直接回客户端 | 请求经隧道转发,响应直接回客户端 |
| Director改包动作 | 改目标IP和端口 | 只改目标MAC | 原包外再封装一层IP包 |
| RS是否要配VIP | 不需要 | 必须配置在lo:0或类似接口 | 必须配置在tunl0隧道接口 |
| 网络要求 | RS网关指向Director即可,可跨网段 | Director和RS必须在同一二层网络 | 通过IPIP隧道,可跨网段 |
| 转发效率 | 较低 | 最高 | 中等 |
| 配置复杂度 | 简单 | 中,ARP抑制容易踩坑 | 中高,依赖系统支持隧道 |
| 适用场景 | 小规模、隔离网段 | 同机房大流量Web集群 | 跨机房、跨地域调度 |
注意,这三者并不是哪个一定比哪个好。NAT模式虽然转发路径长,但是RS不需要额外绑VIP,也不需要在RS上做ARP相关配置,天然就是“后端藏起来”的拓扑;DR模式性能最猛,但二层网络限制很死,要求调度器和RS之间能通ARP;TUN模式能跨网段,代价是IP封装的额外开销以及云环境对IPIP协议的支持度。
2. 环境准备与通用配置要点
2.1 资源规划与IP地址设计
动手之前先把网络拓扑想明白。这里我用一套虚拟环境示例,生产环境照这个思路替换成自己的IP就行。先看角色清单:
| 角色 | 网卡 | IP地址 | 说明 |
|---|---|---|---|
| LVS Director(调度器) | eth0 / eth1 | 外网VIP 192.168.100.100 / 内网DIP 192.168.122.10 | NAT模式需要双网卡 |
| RS1 | eth0 | 192.168.122.11 | 实际业务服务器 |
| RS2 | eth0 | 192.168.122.12 | 实际业务服务器 |
| RS3 | eth0 | 192.168.122.13 | 实际业务服务器 |
DR和TUN模式中,Director和RS大概率都在同一段内网,VIP可以设计为192.168.122.100。但为了让NAT模式更贴近真实场景,我会在NAT部分单独用外网VIP网段做演示。规划时最忌讳的是VIP和DIP地址段混在一起导致路由不清晰,宁可先多列几张表,也不要一边敲命令一边想。
2.2 安装IPVS与基础工具
所有操作基于CentOS 7/RHEL系列系统,Ubuntu会略有差异。先在Director上安装管理工具:
yum install -y ipvsadm keepalived内核模块通常是编译进内核的,如果提示找不到,手动加载:
modprobe ip_vs modprobe ip_vs_rr modprobe ip_vs_wrr modprobe ip_vs_sh验证是否支持:
lsmod | grep ip_vsipvsadm是用户态管理工具,keepalived后面做高可用时会用到。如果只做纯LVS搭建,ipvsadm就够。
另外,打开内核转发。LVS的NAT模式和TUN模式都依赖这个参数:
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf sysctl -p2.3 后端服务与测试脚本准备
RS上先起一个能区分节点的HTTP服务,方便验证负载均衡效果。最简单的是用Python自带模块:
# 每台RS上执行,端口统一用80,内容分别写RS1/RS2/RS3 echo "I am RS1" > /var/www/html/index.html python3 -m http.server 80或者用Nginx做后端也完全可以,只要保证每台RS返回的内容不同即可。在Director上用curl跑一轮,能明显看到不同RS的响应,就说明调度生效了。
3. NAT模式搭建全过程
3.1 NAT模式原理与数据流转
NAT模式全称地址转换模式,核心动作是Director在收到客户端请求后,通过LVS算法选一台后端RS,然后把数据包的目标IP从VIP改成那台RS的IP。RS处理完,把响应扔回给Director,Director再把源IP改成VIP,然后送回客户端。所以无论请求还是响应,都绕不开Director。
这个模式用一个生活类比解释:Director就是个前台座机总机,所有外部电话先进总机,总机转给分机,分机要联系外部时,还得先打给总机,再由总机代打电话出去。分机自己没法直接联系外部。
数据流转可以用下面这段文本表示:
客户端 -> VIP -> Director(S_NAT/D_NAT) -> RS -> Director -> 客户端优点很明显:后端RS完全不用处理VIP,也不需要在RS上配置任何特殊内核参数,只需要把默认网关指向Director的内网IP。缺点就是Director的入流量和出流量全都跑满,带宽、CPU、连接表都有可能成为瓶颈,所以这套模式一般用在RS规模不大、流量可控的场景。
3.2 配置步骤与命令详解
假设Director有两块网卡,eth0接外部网络,配VIP;eth1接内部网络,配DIP。RS都在内部网络,网关指向DIP。
第一步,配置Director的IP地址:
# eth0 外部IP/VIP ifconfig eth0 192.168.100.100 netmask 255.255.255.0 up # eth1 内部DIP ifconfig eth1 192.168.122.10 netmask 255.255.255.0 up第二步,把RS的默认网关改到DIP上。每台RS执行:
route add default gw 192.168.122.10如果RS之前有默认网关,先删掉旧的再添加,否则回包还是会走原来的网关。
第三步,Director上配置LVS规则。用轮询算法做演示:
# 添加虚拟服务 ipvsadm -A -t 192.168.100.100:80 -s rr # 添加后端RS,-m 表示NAT模式 ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.11:80 -m -w 1 ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.12:80 -m -w 1 ipvsadm -a -t 192.168.100.100:80 -r 192.168.122.13:80 -m -w 1参数解释:-A是添加虚拟服务,-a是向后端添加RS,-t使用TCP,-s rr指定调度算法为轮询,-r是RS地址,-m表示masquerade,也就是NAT模式,-w设置权重。
查看规则:
ipvsadm -L -n ipvsadm -L -n --stats3.3 验证与常见配置坑
在客户端机器上访问VIP:
curl http://192.168.100.100/多执行几次,应该能看到RS1、RS2、RS3轮番出现。再到Director上看连接统计:
ipvsadm -L -n --stats重点看ActiveConn和InActConn,有数据说明流量确实经过LVS。
NAT模式最容易踩的坑有三个:
第一,RS默认网关没指对。如果不把网关指向Director,RS处理后会把响应直接发给客户端,但此时源IP是RS自己的内网IP,客户端根本不会认这个包,结果就是请求发出去了但一直等不到响应。
第二,Director没开ip_forward。这会导致包到Director内网口后无法往下送,RS收不到请求。
第三,防火墙干扰。如果Director或RS开了iptables/firewalld,默认规则没有放行对应端口,就会出现自己在Director上curl VIP是通的,但客户端访问不通。排查时可以临时清一下规则:
iptables -F注意,生产环境别直接这么干,先加放行规则。
4. DR模式搭建全过程
4.1 DR模式原理与数据流转
DR模式全称直接路由模式,也是生产中用得最多的高性能LVS模式。它的核心逻辑是:Director收到客户端请求后,不改动IP头,只把数据链路层的目标MAC改成选中的RS的MAC,然后通过二层网络把帧发给RS。因为目标IP还是VIP,RS收到后用自己的lo:0上的VIP地址处理请求,响应时直接以VIP为源IP返回客户端。
这套链路里,只有入站流量走Director,出站流量完全由RS直连客户端。Director的负载大幅降低,能支撑的并发规模和吞吐量都远高于NAT模式。但要换来这个性能,必须满足一个硬条件:Director和所有RS必须在同一个二层广播域内,ARP协议要能生效。
数据流转:
客户端 -> VIP -> Director(改MAC) -> RS -> 客户端这里有个容易混淆的点:NAT模式下RS无需配VIP,DR模式下RS必须在回环接口上绑VIP,同时还要抑制ARP响应。因为VIP在任何RS上也有,如果RS响应了客户端的ARP请求,那么客户端可能会把流量直接发到某台RS,Director的调度就形同虚设了。
4.2 VIP在RS上的配置细节
RS上配置VIP时,不是直接绑在eth0上,而是绑到lo接口的别名lo:0上。原因也很简单:如果VIP绑在物理网卡上,RS对外会广播这个IP,会和Director抢ARP响应;绑在lo上再配合ARP抑制,可以让RS在收到内有VIP的数据包时能正确处理,但对外不宣称自己拥有VIP。
RS上完整配置:
ifconfig lo:0 192.168.122.100 netmask 255.255.255.255 up route add -host 192.168.122.100 dev lo:0这里netmask必须写255.255.255.255,不是默认的255.255.255.0。因为VIP作为主机地址,不应广播到整个子网,否则会造成本机路由表混乱,也可能再次引入ARP问题。
接着修改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 net.ipv4.conf.eth0.arp_ignore = 1 net.ipv4.conf.eth0.arp_announce = 2 EOF sysctl -parp_ignore = 1:只有目标IP是本机某接口IP时才响应ARP请求,避免用VIP去响应。arp_announce = 2:尽量使用能够与目标IP匹配的本地接口IP作为ARP请求源地址,防止用VIP去发起ARP。
提示:如果你后续新增网卡,需要把对应网卡名也加到sysctl.conf里,否则新网卡可能又暴露VIP。
4.3 配置步骤与验证
Director上配置VIP和LVS规则:
ifconfig eth0:0 192.168.122.100 netmask 255.255.255.255 up ipvsadm -A -t 192.168.122.100:80 -s wrr ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.11:80 -g -w 1 ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.12:80 -g -w 1 ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.13:80 -g -w 1注意这里的-g代表gateway模式,也就是DR模式。Director上的VIP netmask也建议用32位,否则可能引来不必要的ARP广播。
验证方法和NAT模式差不多,客户端curl VIP,反复请求应该能在三台RS之间轮换。额外要看ARP表现:
ip neigh | grep 192.168.122.100正常情况下VIP对应的是Director网卡或子接口的MAC,而不是某个RS的MAC。如果RS的MAC出现在VIP条目里,就说明ARP抑制没配好。
再分享一个生产环境的排查思路:RS上不要轻易用ping来测试VIP,因为VIP在RS的lo:0上,ping回包会走lo接口,发出和收包看起来都通,但没法验证真实业务数据链路。最好用curl去看内容。
5. TUN模式搭建全过程
5.1 TUN模式原理与适用场景
TUN模式通过IP隧道转发流量。Director收到客户端请求后,在原始IP报文外面再封装一层IP头,外层目标地址是RS的真实IP,然后走三层网络发给RS。RS收到后拆掉外层IP头,看到内层目标IP是VIP,就知道这是发给自己的包,之后处理请求并把响应直接返回客户端。
这个模式和NAT、DR最大的区别就是不受二层网络限制。只要RS和Director之间能通过三层路由互通,支持IPIP协议,就能做负载均衡。所以TUN模式特别适合跨机房、跨地域场景,比如把不同物理机房的节点组合成一个逻辑集群。
数据流转:
客户端 -> Director(IPIP封装) -> 三层网络 -> RS(解封装) -> 客户端代价也很实在:IP封装带来额外CPU开销,数据包的MTU也可能出问题。另外一个现实问题是,很多虚拟化环境和公有云默认禁止IPIP协议或GRE隧道,如果你是在云上做实验,先确认底层网络是否放行这个协议,不然流量根本到不了RS。
5.2 隧道配置与内核参数
RS上需要加载IPIP模块,隧道接口一般叫tunl0。
modprobe ipip加载后配置tunl0:
ifconfig tunl0 192.168.122.100 netmask 255.255.255.255 up route add -host 192.168.122.100 dev tunl0RS上同样建议配置ARP抑制,防止物理网卡对外抢答VIP:
cat >> /etc/sysctl.conf <<EOF net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.tunl0.arp_ignore = 1 net.ipv4.conf.tunl0.arp_announce = 2 net.ipv4.ip_forward = 1 EOF sysctl -pip_forward在这里很有必要。虽然RS接收隧道包后目标IP就是本机VIP,解封装后交给上层协议栈,但如果系统默认没开启转发,某些情况下隧道包处理会不流畅。
5.3 配置步骤与验证
Director上几乎不用做隧道相关配置,直接使用ipvsadm的TUN模式:
ipvsadm -A -t 192.168.122.100:80 -s rr ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.11:80 -i -w 1 ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.12:80 -i -w 1 ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.13:80 -i -w 1其中-i表示tunnel模式。
验证步骤:
- RS上检查tunl0接口,看VIP是否绑定成功。
- 客户端curl VIP,观察三台RS轮询。
- Director上用tcpdump抓包,确认发出的包带外层IP头和VIP内层头:
tcpdump -i any -nn 'host 192.168.122.11'看到类似IP 192.168.100.1 > 192.168.122.11: IP 192.168.100.1 > 192.168.122.100: ...的抓包,说明IPIP封装生效了。
TUN模式常见的坑主要是两个:
第一,MTU。隧道封装会让单包变大,如果后端链路MTU是1500,封装后接近或超过这个值,大包会被丢弃,表现就是小流量正常、大文件传输超时。解决办法是降低RS和客户端链路的MTU,比如在Director的物理网卡上设ifconfig eth0 mtu 1450。
第二,内核没加载ipip模块,tunl0接口不存在,配置命令直接报错。先用modprobe ipip确认模块加载,再往后配。
6. 三种模式对比与生产选型建议
6.1 性能、规模、改造成本对比
从性能上看,DR模式通常是最优解,因为它只改MAC,不回包,Director开销最小。TUN模式虽然也不回包,但封装和解封装会额外消耗CPU,性能居中。NAT模式由于双向流量都过Director,在大流量下最容易成为瓶颈。
从网络限制看,NAT模式最“随和”,后端RS只需要改网关;DR模式必须在同一个二层网络;TUN模式需要IPIP三层互通,跨网段能力强但依赖协议支持。
从后端改造成本看,NAT模式对RS几乎零侵入,DR模式需要绑VIP和改sysctl,TUN模式需要装内核模块、配隧道接口。如果RS数量特别多,NAT模式最省心,但它同时是性能最差的那个,这就是必定的取舍。
| 需求场景 | 推荐模式 | 原因 |
|---|---|---|
| 小规模、RS无法改VIP,网络隔离严格 | NAT | 后端隐蔽,RS零配置 |
| 同机房大规模Web服务,追求吞吐量 | DR | 性能高,配置成熟 |
| 跨机房/跨地域,RS分散在不同网段 | TUN | 三层隧道可以打通异地节点 |
| 公有云环境,且底层屏蔽IPIP协议 | DR | 云内二层能力一般足够,避免协议限制 |
6.2 与Keepalived结合的高可用方案
生产环境里Director单点是不可接受的,通常会把LVS和Keepalived配合使用,两台Director一主一备,共享一个VIP。Keepalived通过VRRP协议做VIP漂移,同时它可以管理LVS的RealServer健康检查,一旦发现后端RS不可用,自动从LVS规则中摘除。
简单给个Keepalived的配置片段,基于DR模式:
global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.122.100/32 dev eth0 } } virtual_server 192.168.122.100 80 { delay_loop 6 lb_algo wrr 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 } } real_server 192.168.122.13 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }备用Director上改state BACKUP,priority调低即可。Keepalived启动后会自动把LVS规则加载到内核里,同时接管VIP,比手动执行ipvsadm要可靠得多。
6.3 我踩过的坑和最终建议
坦白说,三种模式里我试过的坑从多到少排序是:DR > NAT > TUN。DR的ARP问题最多,NAT的网关问题次之,TUN主要死在不支持IPIP的环境上。
DR模式里有一回,某台RS的sysctl配置文件里只写了all,没写具体网卡,重启后新启用的接口还是会响应VIP ARP,结果流量被打到那一台机器上,其他后端几乎没负载。后来排查半天才发现是新网卡没有对应的arp_ignore和arp_announce配置。现在我的习惯是写一个for循环,遍历所有物理网卡把参数都写上,宁多勿缺。
NAT模式踩过最坑的一次是后端RS有自己原来的网关,我加新默认网关时没有注意覆盖,导致回包还是走老网关,客户端连不上。改完默认网关后,记得ip route确认一下。
TUN模式在物理机环境下效果还是不错的,但如果你用虚拟机做实验,很多虚拟化网络栈对IPIP协议支持很差,配置完完全不转发。这种情况别硬调,直接用DR模式替代更省心。
关于调度算法选择,如果后端机器配置差不多,用rr最简单;配置差异大就用wrr;需要会话保持,可以加-p 300,让同一来源IP在一定时间内固定到同一台RS。高并发场景若需要一致性哈希,可以用sh算法。这些都可以在ipvsadm里灵活组合。
我个人在实际搭建里最常用的还是DR模式,性能好、方案成熟、踩坑资料多。配置RS的ARP抑制是重中之重,把这个搞定,DR模式基本就成功了一大半。最后分享一个小技巧:配置完LVS规则后,用ipvsadm -S把规则导出存到文件里,重启后通过ipvsadm -R恢复,省得每次重启后重新敲一长串命令。这三套模式各自的坑都不少,但只要你先把网络拓扑图画清楚,再一条条对应着配置,问题基本都能提前堵死。