ARTICLE DETAIL

资讯详情

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

LVS-DR模式实验指南:ARP抑制与内核参数配置详解

LVS-DR模式实验指南:ARP抑制与内核参数配置详解 我第一次搭LVS-DR模式的时候因为图省事把VIP当作普通地址直接绑在真实服务器的eth0上。结果接口一启用整个实验网段的交换机ARP表开始漂移客户端访问VIP时通时断最后查了大半天才发现问题出在ARP响应上。LVS-DR模式本身并不复杂Director进Real Server出数据包在二层被改写MAC后转交后端。但正因为这种“出流量不回Director”的设计实验配置里最关键的往往不是ipvsadm那几行命令而是Linux内核的ARP参数这也是我写这篇博文的主要原因。我会把原理、实验配置、实际踩坑和验证手段串起来讲适合想从零搞懂DR模式、又不想只看网上零散命令的读者。1. 先说结论DR模式凭什么是最常上线的方案很多人刚接触LVS时会困惑LVS明明有NAT、DR、TUN这么多种工作模式为什么生产环境里我看到的大多数都是DR模式这不是偶然。要解释清楚这个问题最好先把几种模式放在一张表里对比然后你就能明白DR模式的定位。1.1 几种调度模式先摆在同一张表LVS的核心是Linux内核里的IPVS框架用户态我们用ipvsadm来管理虚拟服务和真实服务器。虚拟服务绑定在VIP上真实服务器用RIP表示。根据转发方式不同常见的有NAT、DR、TUN、FULLNAT等模式模式转发机制是否改写IP响应是否经过DirectorRS是否需要绑定VIP能否跨三层网络典型瓶颈NAT修改目标IP和源IP是是不需要可以Director进出双向流量压力大DR修改帧的目的MAC否否需要不可以必须在同一广播域基本无瓶颈仅入站经过TUNIPIP隧道封装否否需要可以隧道封装开销内核DSR支持FULLNAT修改目标IP和源IP全NAT是是不需要可以连接跟踪消耗大InTCP状态同步复杂这张表里最关键的一列是“响应是否经过Director”。NAT模式下客户端发出的请求和真实服务器返回的响应都要经过DirectorDirector承担了双向流量一旦并发量上来很容易成为瓶颈。DR模式下Director只负责把入站请求在二层改一下MAC转给RSRS回包时直接发给客户端Director完全不在响应链路上。这个特性让DR模式特别适合“响应流量远大于请求流量”的Web场景。1.2 DR模式的取舍优势明显限制也明显DR模式的优势很直白出站流量不进DirectorDirector只需要处理请求包所以单台Director可以扛很高的新建连接数不需要像TUN模式那样做IP封装性能更干净也不需要像NAT那样修改IP报文RS拿到的是原始请求应用无感知。但它也有硬限制。第一Director和所有RS必须在同一个二层广播域里中间不能跨路由器否则MAC改写这套方案直接失效。第二RS必须把VIP绑在lo接口上并且要做严格的ARP抑制这是实验配置里最容易翻车的地方。第三如果RS上有多个网卡或复杂的路由策略回包路径需要特别注意一旦回包被错误地交给Director链路就通了Router。我个人的选型经验是如果你的业务全部部署在同一个机房、同一个VLAN优先用DR模式如果后端服务器分布在多个机房或需要跨网段调度就考虑TUN模式或直接上商用负载均衡如果RS上不方便配置VIP和ARP参数比如云主机那就只能走FULLNAT或SLB这类方案。后面的实验我们默认是同一虚拟交换机下的三台Linux机器正好满足DR模式的部署条件。2. 数据包在DR模式下到底怎么走一次请求的全链路视角DR模式之所以让很多人觉得“玄学”是因为它只修改以太网帧的目的MAC不修改IP地址。这个动作发生在OSI二层很多习惯了“路由器转发、改TTL、改MAC”的人会绕不过来。我建议你把思路从“IP路由”切换到“交换机MAC转发”上DR模式的原理一下就通了。2.1 一次完整请求的转发路径假设客户端IP是192.168.1.50访问的是VIP 192.168.1.100:80整个请求过程如下客户端先发ARP请求问192.168.1.100的MAC地址是谁。因为Director把VIP配置在物理网卡eth0上所以Director会正常响应这个ARP而RS虽然也在lo上绑了VIP但通过arp_ignore参数抑制了对外响应不会凑热闹。客户端把数据帧发给Director的MAC。以太网帧里的源MAC是客户端的目的MAC是Director的IP头的源IP是192.168.1.50目的IP是192.168.1.100。Director的IPVS模块收到这个包后根据调度算法选中一台RS。然后只做一件事把数据帧的目的MAC改成RS1或RS2的MAC源MAC改成Director自己出口网卡的MAC再把帧扔回交换机。IP层什么都不动端口也不改。交换机看到目的MAC是某台RS就把数据帧精准转发到那台RS的网卡上。RS的网卡收到帧后检查IP层目标地址192.168.1.100发现这个地址就在本机的lo接口上于是正常把报文交给TCP栈最终送到Nginx或Apache。RS处理完请求生成响应报文源IP是VIP目的IP是客户端的IP。RS查路由表发现客户端和自己同网段直接通过eth0把响应帧发给客户端完全不需要经过Director。客户端收到响应看到源IP是VIP和请求一致TCP连接继续正常工作。整个过程中客户端感知不到后端其实换过机器。2.2 RS为什么必须绑VIP又为什么要“假装看不见”第一个问题很好回答RS收到Director转过来的请求后内核发现IP层的目的地址是本机地址才会把包交给上层协议栈。如果RS没有绑定VIP内核一查路由表发现192.168.1.100不是本机地址顺手就把包丢掉了。所以RS必须绑VIP而且绑在lo上最合适。绑在lo而不是eth0是为了避免在eth0上直接暴露这个地址产生ARP通告。第二个问题才是DR模式的核心坑。RS绑了VIP之后从内核的角度看这台机器确实拥有192.168.1.100这个地址。如果客户端发一个ARP请求问“谁是192.168.1.100”RS默认会正常响应“我是”。这样一来同一个VIP就有Director和所有RS在抢答交换机的ARP表会反复横跳。客户端可能把VIP的MAC地址记成某一台RS的MAC请求直接打到RS上IPVS调度彻底失效负载均衡名存实亡。所以RS要“假装看不见”虽然我有这个IP但我不对外说。具体手段就是设置net.ipv4.conf.all.arp_ignore和arp_announce这两个内核参数让RS对到达物理网卡eth0上的、目标为VIP的ARP请求保持沉默。这相当于把VIP藏在lo上只让Director在局域网里“总揽全局”。2.3 arp_ignore和arp_announce的实验取值这两个参数是DR模式实验的灵魂。理解它们不用背源码记住两个动作就够arp_ignore控制“别人问我我是否回答”。设置为1时只有ARP请求到达的接口上配置了目标IP本机才会响应。外部ARP请求从eth0进来目标IP是VIP而VIP配置在lo接口上eth0上并没有192.168.1.100这个地址所以RS忽略这次ARP请求。Director不受影响因为Director的VIP就配在eth0上。arp_announce控制“我主动发出的ARP包里源IP用什么”。设置为2时内核会尽量选择发送ARP包的接口上配置的IP作为源IP避免拿VIP这样的本地地址去外面通告。这个参数主要用来防止RS发出的某些ARP报文里夹带VIP信息。实验配置里我建议在RS上把下面这几个参数都写进去sysctl -w net.ipv4.conf.lo.arp_ignore1 sysctl -w net.ipv4.conf.lo.arp_announce2 sysctl -w net.ipv4.conf.all.arp_ignore1 sysctl -w net.ipv4.conf.all.arp_announce2 sysctl -w net.ipv4.conf.eth0.arp_ignore1 sysctl -w net.ipv4.conf.eth0.arp_announce2有些教程只写all和eth0有些只写lo。经验做法是all、lo、具体物理网卡三层都写上。Linux内核在读取conf/all和conf/接口名时通常会取两者中更严格的值你全部写成一样的既省心又不会因为发行版差异出现遗漏。反正这些命令在配置完后用sysctl -a | grep arp_ignore验证一遍确保每行都是1或2。3. 动手实验三台Linux虚拟机搭建DR集群理论讲完下面进入实验。我用三台Rocky Linux 9虚拟机CentOS 7也完全适用一台做Director两台做RS客户端用宿主机或第四台虚拟机都可以。所有机器放在同一个虚拟交换机下确保二层互通。3.1 实验拓扑和网段规划规划如下VIP统一用192.168.1.100角色主机名物理接口IPVIP配置位置作用Directorlvs-director192.168.1.10/24eth0: 192.168.1.100/32装ipvsadm做调度Real Server 1rs1192.168.1.11/24lo: 192.168.1.100/32Nginx页面标识RS1Real Server 2rs2192.168.1.12/24lo: 192.168.1.100/32Nginx页面标识RS2客户端client192.168.1.50/24无验证访问为什么Director的VIP要写/32而不是/24因为VIP只是一个用于接收请求的地址不需要让内核为它自动生成共享网段路由/32能避免很多路由表干扰也让ARP行为更可控。RS上的VIP同样写/32绑在lo上这是DR模式的标准写法。3.2 Director侧安装ipvsadm并配置虚拟服务先安装ipvsadm并确认内核IPVS模块可用yum install -y ipvsadm modprobe ip_vs lsmod | grep ip_vs然后给Director的eth0绑定VIPip addr add 192.168.1.100/32 dev eth0这里要强调Director的VIP必须直接绑在物理网卡eth0上不能绑在lo上。否则Director自己对ARP请求的响应也会被抑制客户端根本找不到VIP。绑好之后用ip addr show eth0确认一下。接着配置IPVS虚拟服务和后端RSipvsadm -A -t 192.168.1.100:80 -s rr ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.11:80 -g ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.12:80 -g ipvsadm -L -n命令里的-A是增加虚拟服务-s rr表示使用轮询算法-a是向这个虚拟服务里添加真实服务器-r后面跟RS地址-g表示使用gateway模式也就是DR模式。初次实验用rr最直观看到的结果就是两台RS挨个被轮流调度。ipvsadm -L -n输出里如果能看到192.168.1.100:80下面有两个Route模式的RS说明配置已经生效。3.3 Real Server侧绑定VIP并抑制ARPRS的配置比Director多一点。先做ARP参数设置再绑VIP这个顺序很重要。顺序反了虽然大多数时候也能行但保险起见先让RS“闭嘴”再把VIP放上去。在rs1和rs2上分别执行sysctl -w net.ipv4.conf.lo.arp_ignore1 sysctl -w net.ipv4.conf.lo.arp_announce2 sysctl -w net.ipv4.conf.all.arp_ignore1 sysctl -w net.ipv4.conf.all.arp_announce2 sysctl -w net.ipv4.conf.eth0.arp_ignore1 sysctl -w net.ipv4.conf.eth0.arp_announce2 ip addr add 192.168.1.100/32 dev lo接着在RS上安装Nginx并启动yum install -y nginx systemctl enable --now nginx为了区分调度效果把RS1的默认首页内容改成RS1把RS2的改成RS2。然后客户端访问一下http://192.168.1.100如果能看到页面内容在RS1和RS2之间来回切换说明实验已经跑通。不过实验环境重启后这些临时配置会全部丢失。建议把ARP参数写入/etc/sysctl.d/99-lvs-rs.confVIP绑定的命令写入/etc/rc.d/rc.local或者在网卡配置文件里添加辅助地址。学习阶段用命令跑通即可生产环境必须考虑持久化。4. 实验踩坑实录从丢包到回环的排查链路DR模式实验里最不缺的就是问题。我自己踩过的坑以及帮别人排查时高频出现的问题集中在下面几个现象里。每个现象我都会按“可能原因 → 验证命令 → 解决办法”的顺序讲你可以直接照着排查。4.1 现象一客户端ping不通VIP客户端ping 192.168.1.100一直丢包或不通。遇到这个问题第一步不是看IPVS而是看ARP表。在客户端执行ip neigh show 192.168.1.100 arping -c 3 -I eth0 192.168.1.100看返回的MAC地址是谁。正常情况下VIP的MAC必须是Director eth0的MAC。如果看到的是RS1或RS2的MAC说明RS还是抢答了ARParp_ignore没有生效。常见原因有两个RS的VIP配置在了eth0而不是lo上。在eth0上配置VIP即使设置了arp_ignore1也可能在某些内核版本上产生额外通告而且行为不可控。正确做法是只绑lo。sysctl参数没有写全只设了all没设具体接口重启后参数丢失。解决方案很简单把RS上的VIP移到lo重新执行那一组sysctl再从客户端确认ARP表。如果MAC稳定指向Directorping基本就通了。4.2 现象二Director转发统计有包但RS就是不上线有时候ipvsadm -L -n能看到转发的包数一直在涨但客户端访问就是超时。这种问题定位在RS身上的概率最大。先上RS检查服务状态ss -lntp | grep 80 curl -I http://127.0.0.1/如果127.0.0.1的80端口能通但从外部不通重点检查Nginx有没有监听VIP很多Nginx默认配置listen 80代表监听本机所有地址没问题但如果有人改成listen 127.0.0.1:80外部自然无法访问。RS上监听0.0.0.0:80即可。另一个容易被忽略的是路由问题。RS回包不一定非要经过Director但RS必须有一条能到客户端的路由。如果客户端和RS同网段eth0直连路由就够了如果跨网段必须检查RS的默认网关是否配置正确。默认网关千万不要指向Director的DIP否则回包会绕回DirectorDR模式等于破功。4.3 现象三明明用的是rr轮询请求却总打在同一台RS这也是个经典场景。客户端用浏览器连续刷新看到的页面始终是同一台RS。问题不一定出在LVS上而是HTTP keep-alive。IPVS的调度粒度是连接不是单个请求。浏览器一次TCP连接建立后如果保持长连接后续HTTP请求都走同一个连接自然都落在同一台RS上。真正验证轮询需要创建大量短连接。用ab压测时这样观察ab -n 10000 -c 100 http://192.168.1.100/然后到两台RS上看Nginx访问日志计数应该接近1:1。如果还是不均匀检查ipvsadm里有没有设置持久连接ipvsadm -L -n --persistent带-p参数的虚拟服务会让IPVS记住客户端IP在超时时间内把同一来源固定到同一台RS。实验环境里建议不要开-p否则看不出轮询效果。5. 验证调度与压测用数据确认负载均衡生效实验跑通只是第一步真正说服自己的是抓包和数据统计。我建议你把三样工具组合使用ipvsadm统计、tcpdump抓包、ab压测。它们分别回答“转发了多少”“怎么转发的”“调度是否均匀”三个问题。5.1 用ipvsadm和tcpdump还原转发过程先在Director上看IPVS统计ipvsadm -L -n --stats这个输出会显示每台RS收到的总连接数、包数、字节数。轮询跑几轮之后两台RS的连接数应该接近。然后在Director的eth0上抓包tcpdump -i eth0 -e -n tcp port 80 -v加上-e参数是为了显示MAC地址。你会看到两种帧一种的源MAC是客户端MAC目的MAC是Director eth0的MAC这是入站请求另一种的源MAC是Director eth0的MAC目的MAC是RS1或RS2的MAC这就是IPVS改写MAC之后发出的帧。目标MAC变了但IP头里目的IP始终是192.168.1.100。再到任意一台RS上抓包tcpdump -i eth0 -e -n tcp port 80 -v你会看到Director转过来的请求和RS直接回给客户端的响应。响应包的源IP是VIP目的IP是客户端IP说明出流量确实没有经过Director。这个抓包结果一出来整条链路就清清楚楚了。5.2 用并发压测确认负载均匀我习惯把RS1的首页写成RS1RS2的首页写成RS2然后用ab压测ab -n 10000 -c 200 http://192.168.1.100/不加-k参数时ab每个请求都会新建一条TCP连接IPVS的轮询算法会把这些连接尽量平均地分给两台RS。压测结束后看两台RS的access_log行数偏差一般不会超过5%。如果偏差较大检查是不是有一台RS的Nginx已经扛不住了或者系统资源不足导致新连接建失败。如果加上-k参数ab会和服务器保持keep-alive每个压测进程占用一条长连接这时所有请求会根据IPVS的连接哈希固定到同一台RS看起来就像“负载不均衡”。所以判断LVS本身是否正常请用不带-k的压测方式。5.3 顺手把参数持久化和基础健康检查做掉实验环境里用sysctl -w和ip addr add配置重启就没了。我现在的习惯是在RS上写/etc/sysctl.d/99-lvs-rs.conf把arp_ignore和arp_announce全部固定下来然后执行sysctl --system让其生效。在Director上用ipvsadm-save导出规则例如ipvsadm-save /etc/sysconfig/ipvsadm开机后通过ipvsadm-restore恢复。如果Director和RS都使用Netplan或ifcfg文件就把VIP作为辅助地址写进配置文件不要依赖手动命令。还有个容易踩的点ipvsadm本身不负责健康检查。RS的Nginx挂掉后ipvsadm仍然会把新连接转发给它用户会看到一个超时页面。实验阶段可以不管但如果你想自动化一点可以在Director上用脚本定期curl每个RS的存活状态不健康就把对应RS从IPVS规则里删掉恢复后再加回来。6. 从实验到上线前必须处理的三个细节实验做完之后很多人会直接把这套方案搬上生产。从我的经验看还有三个细节最好提前处理否则到了现场会手忙脚乱。6.1 给Director加上Keepalived高可用单台Director本身就是单点。生产环境中通常用Keepalived把VIP绑定在一对Director之间一台Master挂掉后另外一台Backup接管VIP同时接管IPVS规则。RS侧的配置完全不用变因为DR模式下每台RS都会在本地保留VIP只是不响应ARP谁持有VIP的ARP响应权流量就进谁。Keepalived的配置不算复杂虚拟服务部分可以和ipvsadm规则互相配合。你既可以在Keepalived里定义real_server让它自动增删后端也可以用两台Keepalived只做VIP漂移IPVS规则通过脚本同步。实验里先把Keepalived跑起来熟悉VRRP的MASTER/BACKUP状态切换对理解DR模式也有帮助。6.2 网络层要为MAC转发留好后路DR模式严重依赖二层广播域。如果Director和RS不在同一个交换机端口组里比如中间隔了防火墙、三层交换机或VLAN间路由原生态DR模式就跑不通。所以上线前要画清楚网络拓扑Director的DIP、RS的RIP、VIP的网段必须在一个广播域内。交换机端口如果开了端口安全或MAC漂移检测要预留漂移容忍度避免交换机认为VIP的MAC在多个端口间反复横跳。如果业务流量跨机柜关注东西向流量经过的交换机端口是否属于同一VLAN。这些问题在虚拟机实验里不太容易出现但在物理机房里很常见。我见过不止一次因为交换机MAC表震荡导致VIP间歇性不可用的情况最后的根源就是RS没有抑制好ARP。6.3 把“先抑制ARP再绑VIP”养成肌肉记忆最后说一个我的个人体会。我后来每次配置一台新的RS顺序永远是固定的先写sysctl参数再用ip addr add把VIP绑到lo最后启动Nginx。我曾经反过来操作先绑VIP再写sysctl结果几秒之内交换机就学到了RS的MAC客户端访问VIP直接乱套。虽然这个顺序问题在理论上不至于让配置失败但少踩一次坑就少浪费一小时。如果将来你在生产里遇到更诡异的DR模式问题比如单台RS流量特别大时响应变慢、或者回包源地址偶尔变成非VIP记得回头检查两件事一是RS的路由表看默认路由有没有被篡改二是rp_filter的反向路径过滤策略多网卡环境下有时需要调整。DR模式的原理并不难难的是把每台主机的网络行为控制到恰到好处而ARP抑制就是那个最关键的控制点。
返回列表