LVS集群NAT模式部署与排错:报文流向、内核转发与conntrack调优
发布时间:2026/10/27 15:42:00 锦皓数字建站

LVS集群、NAT模式部署这套东西网上的文档一抓一大把但绝大多数只告诉你怎么敲几条ipvsadm命令敲完之后为什么能通、为什么不通、下一次扩容该改哪个参数一概不讲。我前阵子给一个内部测试环境做四层入口的时候又把这块从头捋了一遍顺手把踩过的坑记了下来。这篇文章写给两类人一类是刚接触 LVS集群想搞清楚它到底解决了什么问题、NAT 模式的数据包在机器里是怎么走的另一类是已经在用了但遇到过“规则明明在、连接就是不通”或者“压测一上来 Director 就顶不住”的运维同学。下面从原理到落地一条线讲完命令和参数都是可以直接抄的环境是两台 Real Server 加一台 Director 的最小可用拓扑。1. LVS集群到底解决了谁的麻烦1.1 单机撑不住时最先垮的往往不是 CPU很多人对扩容的第一反应是“加配置”但真实业务里最先出问题的经常是别的东西。比如单机 Nginx 跑到两三千并发连接时CPU 可能才 40%但网卡软中断已经打满一个核或者 TIME_WAIT 堆积到端口不够用再或者一次发布重启就让所有在线会话全断。这些问题的共同点是它们不是“机器不够快”而是“入口只有一个”。LVS集群解决的正是入口这一层。它把一台对外暴露 VIPVirtual IP虚拟 IP的机器变成调度器后面挂若干台真正跑业务的服务器。客户端永远只认那一个 VIP感知不到后面有几台机器、哪台挂了、哪台新加了。这一层剥离出来之后业务机器的重启、扩容、灰度都变成后端的事对客户端是透明的。我自己总结的经验是只要你的服务是无状态的或者会话能外置到 Redis 之类的地方并且 QPS 已经逼近单机的三分之一水位就该考虑在入口加四层负载了。等到 CPU 打满再动手通常是被故障推着走的。1.2 LVS 在四层负载均衡里的位置负载均衡按工作层次分七层的有 Nginx、HAProxy四层的有 LVS、F5 这类。区别在于七层要解析 HTTP 报文能根据 URL、Header 做路由但它必须把 TCP 连接“断开再接上”也就是客户端到 Nginx 是一条连接Nginx 到后端是另一条连接四层只认 IP 和端口转发时不做协议解析性能高一个数量级但路由能力弱。LVS 属于后者它工作在内核态。请求进来之后LVS 不建立新的连接而是在内核里直接改写报文头然后转发出去整个过程不经过用户态也没有额外的内存拷贝和连接管理开销。这就是为什么一台普通 8 核机器跑 LVS撑住几十万并发连接不稀奇而同样的机器跑 Nginx 做反向代理几万连接就开始吃力了。所以选型逻辑很清晰如果你的需求是“按 URL 分流”“做 HTTPS 卸载”“改请求头”那用 Nginx如果只是“把流量摊到几台机器上、扛住高并发、别成为瓶颈”LVS 更合适。实际生产里两者常常叠加最外层 LVS 做四层分发里面每台机器再跑 Nginx 做七层路由。1.3 先搞清楚这几个角色名词LVS 的文档读起来累很大一部分原因是名词太多。我按自己的理解把它们归成三类先记住这张表后面看配置就不会晕。名词全称通俗解释Director调度器对外暴露 VIP 的那台机器负责改包转发Real ServerRS真实服务器后面真正跑业务、响应请求的机器VIPVirtual IP客户端访问的地址配置在 Director 上DIPDirector IPDirector 面向内网那块网卡的地址用来和后端通信RIPReal Server IP后端服务器的内网地址CIPClient IP客户端的源地址这里最容易混的是 VIP 和 DIP。一句话区分VIP 是给外面看的DIP 是给里面用的。客户端发请求时目的地址是 VIPDirector 收到之后要把目的地址改成某台 RS 的 RIP改完之后报文得从 DIP 这块网卡发出去所以 DIP 必须和 RS 在同一个二层网络里或者至少路由可达。还有一个词是“虚拟服务”指的是VIP:Port这个组合比如172.16.10.100:80。一个 Director 上可以挂很多个虚拟服务每个虚拟服务下面挂一组 RS彼此独立。这个设计很实用一台 Director 同时承载 Web、数据库代理、缓存入口是很常见的做法。2. 三种转发模式到底该怎么选2.1 NAT 模式进门出门都要过门卫NAT 模式的思路最直白客户端请求到达 Director 后Director 把目的 IP 从 VIP 改成某台 RS 的 RIP转发给 RSRS 处理完回包源 IP 是 RIP、目的 IP 是 CIP这个包必须再回到 DirectorDirector 把源 IP 改成 VIP 再发给客户端。关键在于“回包必须回到 Director”这一条。RS 怎么知道要把包交给 Director靠默认网关。RS 的网关必须指向 DIP否则回包会直接走自己的网关出去客户端收到的源地址就是 RIPTCP 三次握手对不上直接超时。这是 NAT 模式部署里最高频的翻车点没有之一。NAT 模式的好处是配置简单、对网络环境没要求RS 可以是任意操作系统也不需要额外配什么 ARP 参数。坏处也很明显所有进出的流量都要穿过 DirectorDirector 的网卡带宽就是整个集群的上限。而且因为要做地址转换连接跟踪表会跟着涨几十万并发的时候 conntrack 表打满是很典型的事故。所以 NAT 模式适合中小规模、或者后端只需要做几十 Mbps 到几百 Mbps 的场景。2.2 DR 模式回包绕开门卫DRDirect Routing模式的思路是“进来改 MAC出去不经过我”。Director 收到请求后不改 IP只改目标 MAC 地址为某台 RS 的 MAC把包丢到同一个二层网络里。RS 上配置了 VIP 在回环口上它认为自己是 VIP 的持有者处理完之后直接把响应发给客户端源 IP 就是 VIP客户端看起来完全正常。这样做的结果是只有请求流量经过 Director响应流量直接从 RS 出去。Web 服务通常是请求小、响应大这个比例可能是 1:10 甚至 1:50所以 DR 模式的吞吐能力比 NAT 高一个数量级Director 几乎不会成为瓶颈。代价是网络约束Director 和所有 RS 必须在同一个物理二层网络里中间不能有路由器RS 上要做 ARP 抑制arp_ignore1、arp_announce2把 VIP 配在lo上否则整个网络里的 ARP 会乱掉。这套配置网上教程很多但每一条为什么这么配讲清楚的不多我后面单独写。2.3 TUN 模式与三者的选型对照TUN 模式是 IP 隧道Director 把原始报文整个封装进一个新的 IP 包里发给 RSRS 拆开之后看到的就是原始请求。它的优点是 RS 可以和 Director 跨机房、跨网段不受二层网络限制缺点是 RS 要支持 IPIP 隧道Linux 天然支持Windows 要额外装而且封装解封装有开销。三种模式横向对比我一般按这张表来选维度NATDRTUN请求路径经过 Director经过 Director经过 Director响应路径经过 Director直接回客户端直接回客户端Director 带宽瓶颈有且明显基本没有基本没有网络要求无特殊要求同一二层网络支持 IP 隧道即可RS 配置复杂度低中ARP 抑制中是否支持端口映射支持可改端口不支持不支持典型适用规模中小流量大流量跨机房这里有个容易被忽略的点只有 NAT 模式支持端口映射也就是 VIP 的 80 端口可以转发到 RS 的 8080。DR 和 TUN 都不改端口。如果你的后端服务监听的不是标准端口又不想逐个改配置NAT 是唯一选择。3. NAT 模式的报文流向拆解3.1 一次请求在 Director 上被改了哪些字段光看文字描述容易糊我把一次完整的 HTTP 请求拆成四步,把每一步的源目地址列清楚。假设 CIP 是172.16.10.50VIP 是172.16.10.100DIP 是192.168.10.100RIP1 是192.168.10.11。第一步客户端发起请求源 172.16.10.50:51234 - 目的 172.16.10.100:80第二步Director 收到后做 DNAT把目的地址换成 RIP源 172.16.10.50:51234 - 目的 192.168.10.11:80第三步RS 处理完回包时源是自己、目的是客户端这个包根据默认路由交给网关也就是 DIP源 192.168.10.11:80 - 目的 172.16.10.50:51234第四步Director 收到回包做 SNAT把源地址换成 VIP源 172.16.10.100:80 - 目的 172.16.10.50:51234客户端看到的响应来自172.16.10.100:80端口和地址都对得上连接正常建立。从这四步能看出两件事。第一Director 必须同时维护“哪个客户端连接对应哪台 RS”的映射表这就是 IPVS 连接表存在的意义用ipvsadm -Lnc能看到。第二回程路径完全依赖 RS 的默认网关第三到第四步之所以能发生唯一的原因就是 RS 把包交给了 DIP。RS 上如果有多条路由或者网关配错第三步的包会直接从别的口出去第四步永远不发生表现出来的现象就是客户端一直处于 SYN_SENT 或者连接超时。3.2 地址规划VIP、DIP、RIP 怎么分地址规划看着简单实际上规划不好后面全是麻烦。我的习惯是分两个网段外网侧172.16.10.0/24Director 的 eth0 配置 VIP172.16.10.100客户端在这个网段或者能路由到这个网段内网侧192.168.10.0/24Director 的 eth1 配置 DIP192.168.10.100RS 分别配置192.168.10.11和192.168.10.12这样分的好处是内外隔离清晰VLAN 一划后端机器完全不暴露在外网。如果你的环境只有一个网段NAT 模式也能跑这叫单臂模式但要注意 RS 的网关指向 DIP 之后RS 访问同网段的其他机器也会绕一圈容易出问题不推荐。VIP 和 DIP 千万别配置在同一块网卡上还指望一切正常。虽然 Linux 允许一块网卡挂多个地址但 NAT 模式下进出方向不同单网卡配置会让路由判断变得很微妙排错时你会怀疑人生。有条件就两块网卡实在只能一块也要在测试环境充分验证再上生产。3.3 内核转发开关与 conntrack 容量NAT 模式下 Director 本质上在做 IP 转发所以内核转发必须开sysctl -w net.ipv4.ip_forward1 echo net.ipv4.ip_forward 1 /etc/sysctl.conf sysctl -p这一条是硬性前提不开的话报文到了 Director 直接被丢弃ipvsadm -Ln里规则显示正常、连接数也是 0非常迷惑。第二个要关注的是连接跟踪表。NAT 场景下每个穿过 Director 的连接都会在 conntrack 里留一条记录默认的nf_conntrack_max在很多发行版上是 65536 左右压测几千并发就满了满之后内核会直接丢新连接dmesg里出现nf_conntrack: table full, dropping packet。# 查看当前值 sysctl net.netfilter.nf_conntrack_max cat /proc/sys/net/netfilter/nf_conntrack_count # 调大具体数值按内存来每条记录大约 300 字节 sysctl -w net.netfilter.nf_conntrack_max1048576粗算一下100 万条记录大约占 300MB 内存机器内存充足的话这个值开到百万级没问题。同时建议把nf_conntrack_tcp_timeout_established从默认的 432000 秒5 天调小到 3600 秒左右否则连接关了记录还挂着表迟早被历史连接占满。注意生产环境调 conntrack 参数要评估内存别只顾着调大。我见过为了图省事直接开到 400 万结果小内存机器 OOM 的案例。4. 实操把 NAT 模式的 LVS 跑起来4.1 环境与软件准备三台虚拟机操作系统用 CentOS 7 或者 Rocky 9 都行命令基本一致Ubuntu 系把yum换成apt即可。角色主机名网卡1网卡2网关Directorlb01172.16.10.100/24VIP192.168.10.100/24DIP172.16.10.1RS1rs01192.168.10.11/24无192.168.10.100RS2rs02192.168.10.12/24无192.168.10.100客户端client172.16.10.50/24无172.16.10.1三台机器都要关闭防火墙或者放行对应端口测试环境直接systemctl stop firewalld最省事生产环境老老实实加规则。Director 上装 ipvsadmyum install -y ipvsadm装完之后检查内核模块正常情况下 ipvsadm 执行时会自动加载lsmod | grep ip_vs # 期望看到 ip_vs、ip_vs_rr、ip_vs_wrr、ip_vs_lc 等如果没加载手工执行modprobe ip_vs和modprobe ip_vs_wrr。RS 上装 Nginx 提供测试页面yum install -y nginx systemctl enable --now nginx echo RS1-192.168.10.11 /usr/share/nginx/html/index.html4.2 Director 节点的配置步骤先把网卡地址配好然后是转发开关最后才是 ipvsadm 规则。顺序不能乱我见过先配规则再配地址的中间调试半天。# 1. 开启转发 sysctl -w net.ipv4.ip_forward1 echo net.ipv4.ip_forward 1 /etc/sysctl.conf # 2. 确认地址 ip addr show # eth0 应有 172.16.10.100/24 # eth1 应有 192.168.10.100/24 # 3. 确认能通到 RS ping -c 2 192.168.10.11 ping -c 2 192.168.10.12第三步很关键Director 到 RS 的二层连通性是基础如果 ping 不通后面所有配置都是白搭。接下来下发规则。我先用轮询算法跑通再换成加权便于观察效果。# 清空已有规则避免实验环境残留干扰 ipvsadm -C # 添加虚拟服务VIP:80调度算法用轮询 ipvsadm -A -t 172.16.10.100:80 -s rr # 添加两台真实服务器-m 表示 NAT 模式 ipvsadm -a -t 172.16.10.100:80 -r 192.168.10.11:80 -m ipvsadm -a -t 172.16.10.100:80 -r 192.168.10.12:80 -m # 查看结果 ipvsadm -Ln-Ln的输出应该长这样IP Virtual Server version 1.2.1 (size4096) Prot LocalAddress:Port Scheduler Flags - RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.16.10.100:80 rr - 192.168.10.11:80 Masq 1 0 0 - 192.168.10.12:80 Masq 1 0 0Forward列显示Masq就说明是 NAT 模式Weight都是 1。如果这里显示的是Route或者Tunnel说明参数敲错了分别对应-g和-i。4.3 Real Server 节点必须做的两件事RS 上的配置只有两件事但每一件都不能省。第一件把默认网关指向 DIP。这一步决定了回包能不能回到 Director# 查看当前路由 ip route show # 删除默认路由重新指向 DIP ip route del default ip route add default via 192.168.10.100 # 持久化编辑网卡配置文件里的 GATEWAY第二件确认服务在监听0.0.0.0:80而不是127.0.0.1:80。这个听着像废话但真的很常见——有些默认配置或者容器端口映射会把监听地址限制在环回口上Director 转发过来的包目的是192.168.10.11:80服务没监听这个地址包直接被内核回 RST客户端看到的是“连接被重置”。ss -lntp | grep :80 # 期望看到 0.0.0.0:80 或 *:80NAT 模式和 DR 模式有一个重要区别RS 上不需要做任何 ARP 抑制。因为 VIP 只在 Director 上配置RS 上根本没有这个地址也就不存在 ARP 冲突。网上有不少文档把 DR 模式的arp_ignore、arp_announce参数抄到 NAT 模式的教程里纯属误导照着配了虽然不会出错但会让你误以为这些参数是必需的换个环境就懵了。4.4 规则下发与效果验证从客户端机器上访问 VIPcurl http://172.16.10.100/ # 期望输出 RS1-192.168.10.11 或 RS2-192.168.10.12多刷几次因为用的是轮询应该交替出现两个结果for i in $(seq 1 6); do curl -s http://172.16.10.100/; done然后在 Director 上看连接状态ipvsadm -Lnc这条命令能列出当前所有活跃连接包括客户端地址、VIP、被调度的 RS 和连接状态。这是排错时最有用的工具比抓包快得多。正常情况下列表里每条记录的形式是CIP:端口 - VIP:80 - RIP:80状态是ESTABLISHED。再看统计信息ipvsadm -Ln --stats输出里能看到每个 RS 收到的连接数、入字节、出字节。压测之后对比两台机器的 Conn 数量能直接验证调度是否均衡。如果发现某台机器的连接数是 0要么是权重配错了要么是那台机器的服务有问题。做一轮压测验证吞吐ab -n 20000 -c 500 http://172.16.10.100/这时候在 Director 上开另一个终端跑top观察si软中断和网络吞吐。如果si某个核长期接近 100%说明单核处理能力到顶了可以考虑开启多队列 RSS把中断分散到多个核上。如果网络带宽接近网卡上限那就只能说明 NAT 模式不适合当前的流量规模该上 DR 了。4.5 持久连接与调度算法怎么选规则跑通之后调度算法和持久连接是两个必须调优的参数。先看调度算法常用的几个算法参数适用场景轮询rr后端性能一致、请求耗时均匀加权轮询wrr后端配置不同按权重分配最少连接lc请求耗时差异大加权最少连接wlc默认算法综合效果好源地址哈希sh需要同一客户端固定到同一台 RS最短延迟sed追求响应速度连接数增长慢时更优实际生产里我用wrr最多。原因很实际新老机器混部是常态老机器权重给 1新机器给 3流量自然倾斜等老机器下线时把权重调到 0 就行不用改规则。lc和wlc适合后端有长连接或者请求耗时差异大的场景比如文件下载。持久连接用-p参数开启单位是秒ipvsadm -E -t 172.16.10.100:80 -s wrr -p 300这里要注意开启持久连接之后调度算法在持久时间窗口内基本失效——同一个客户端 IP 的请求会全部落到同一台 RS 上。如果你的场景是有会话状态的比如没做会话共享的老系统这个参数就是救命稻草如果是无状态服务开了反而会让负载不均特别是客户端集中在少数几个出口 IP 后面的时候等于把流量全压在一两台机器上。调整权重不需要删规则重加ipvsadm -e -t 172.16.10.100:80 -r 192.168.10.11:80 -m -w 3 ipvsadm -e -t 172.16.10.100:80 -r 192.168.10.12:80 -m -w 1规则配好之后记得保存重启后能自动恢复ipvsadm-save /etc/sysconfig/ipvsadm systemctl enable ipvsadm注意ipvsadm本身不带健康检查。它只知道你配了哪几台 RS不知道哪台挂了。RS 宕机之后新连接依然会往那台机器上送直到 TCP 超时。想要自动摘除得靠 keepalived 或者 ldirectord 这类外部工具配合这是 LVS 和 Nginx 在能力上的一个关键差异别指望 ipvsadm 自己搞定。5. 排错实录那些让人抓狂的现象5.1 五类高频故障速查表NAT 模式的问题现象高度集中我把遇到过的整理成表按现象倒查原因比从头捋快得多。现象最可能的原因快速验证方法客户端一直超时-Lnc里没有连接Director 没开ip_forwardsysctl net.ipv4.ip_forward连接能建立但立刻断RS 服务没监听对应地址RS 上ss -lntp部分请求超时、部分正常某台 RS 网关配错在 RS 上ip route get 8.8.8.8压测到一定并发就不通conntrack 表满dmesg -T | grep conntrack规则显示正常但连接数为 0VIP 没有配在网卡上ip addr show第二行和第三行是最常见的。尤其第三行两台 RS 配置看起来一模一样但其中一台的网关是在/etc/sysconfig/network-scripts/里改的、另一台是临时ip route改的重启之后失效怎么查都查不出来。我现在的习惯是改完网关立刻ip route get验证一次并且把配置写进网卡配置文件持久化。5.2 抓包定位的三步法现象和原因对不上的时候抓包是唯一可靠的办法。我一般按三步走每一步的目的很明确。第一步在客户端抓tcpdump -i any -nn host 172.16.10.100 and port 80 -c 20如果只能看到 SYN 发出去、看不到 SYN-ACK 回来问题在服务端如果连 SYN 都发不出去那是路由或者 ARP 的问题。第二步在 Director 上抓内网网卡看 DNAT 有没有发生tcpdump -i eth1 -nn host 192.168.10.11 -c 20正常应该看到目的地址已经被改成192.168.10.11:80。如果这里什么都抓不到说明 IPVS 根本没转发回去检查ipvsadm -Ln和ip_forward。第三步在 RS 上抓回包方向tcpdump -i any -nn host 172.16.10.50 -c 20这里应该能看到响应包且源地址是192.168.10.11:80。如果这个包抓到了但客户端没收到说明它在回程路上丢了——十有八九是 RS 的默认网关不对包没走 Director 出去。这三步做完问题定位基本就锁死了剩下的只是改配置。我强烈建议把这三条命令存成快捷脚本下次出问题直接跑比翻文档快。5.3 我实际踩过的几个坑说几个文档里不太提、但确实会绊住人的细节。第一个坑实验环境里 Director 和 RS 在同一台物理机上用虚拟机搭建结果 RS 的回包不走 Director直接通过宿主机网络发出去了。原因是虚拟机的默认网关被 DHCP 改回去了。这种问题在真实环境里对应的是“多网卡机器默认路由不确定”排查时一定要ip route show看默认路由到底指向哪块网卡、哪个下一跳而不是只看配置文件。第二个坑ipvsadm -Lnc里连接状态显示SYN_RECV卡住不动。这种通常不是 LVS 的问题是 RS 的 TCP 半连接队列满了net.core.somaxconn和net.ipv4.tcp_max_syn_backlog太小。调大之后立刻恢复。这也提醒一点LVS 排错时不要把视野局限在 LVS 上后端的内核参数同样会影响。第三个坑用wrr加权之后发现流量倾斜得不明显。原因是 LVS 的加权轮询是按连接数分配的如果你的请求是长连接比如 HTTP/1.1 keep-alive 开了 60 秒新连接产生的速度远远跟不上流量权重自然体现不出来。这种场景要么用wlc要么在七层那一侧做均衡。第四个坑规则保存之后重启没生效。原因是systemctl enable ipvsadm只是开机加载了保存的规则但保存的文件是旧的。每次改完规则都要重新ipvsadm-save一次这个动作很容易忘。我的做法是把它写进变更流程里改规则和保存规则必须一起做。回过头看NAT 模式的配置量其实非常小十几条命令的事真正花时间的是理解报文流向和排错。我个人的体会是遇到连接不通第一反应永远是查 RS 的默认网关第二反应是查 Director 的转发开关这两个点覆盖了我见过的大半问题。至于性能和容量那是规则跑通之后才需要考虑的事别一上来就纠结参数调优。等你把最小可用拓扑压出瓶颈了再回头看 DR 模式那套 ARP 配置理解起来会顺很多。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。