ARTICLE DETAIL

资讯详情

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

LVS DR模式实验全解析:ARP抑制与IPVS配置实战

LVS DR模式实验全解析:ARP抑制与IPVS配置实战 1. 实验环境规划四台机器与一条VIP链路先说结论LVS的DR模式Director Routing直接路由模式是所有负载均衡模式里性能最好、也最容易让人栽跟头的一种。我最早接触这个概念是在生产环境被通知“某个集群的VIP不通”到现场一查发现架构图画得漂漂亮亮实际配置里Real Server压根没处理ARP问题结果把整个机房的门禁都搞到不可用——半个小时后才发现是VIP的MAC地址漂到了交换机上。从那以后我每次做LVS DR实验都先给自己列一张“环境清单”把每一台机器要干什么、哪个IP要出现在哪块网卡上写得清清楚楚再动手。DR模式的本质并不复杂客户端请求到达负载均衡器DirectorDirector根据调度算法选一台Real Server然后直接改数据链路层的目标MAC地址把请求原封不动地转发出去。Real Server和Director必须在同一个二层网络里响应报文不经过Director由Real Server直接回给客户端。这个“请求进、响应出互不干扰”的设计决定了三件必须提前确认的事一是所有节点必须在同一个物理网段二是Real Server的VIP必须配置在loopback接口上而且不能对ARP请求应答三是Director上必须开启IP转发但Real Server上绝对不能开。我做实验用的是一套三台CentOS 7虚拟机加一台客户机的组合具体规划如下角色主机名IP地址关键配置Director负载均衡器lvs-director192.168.122.10配置VIP 192.168.122.100开启ip_forwardReal Server 1rs-1192.168.122.21lo:0配置VIP抑制ARP启动httpdReal Server 2rs-2192.168.122.22lo:0配置VIP抑制ARP启动httpd测试客户端client192.168.122.50无需特殊配置只做curl验证有人会问为什么不在Windows上用VMware做实验其实都一样关键是虚拟交换机必须设置为“VMnet仅主机模式”或者“NAT模式”保证几台机器在同一个广播域里。我自己更喜欢使用KVM/QEMU加libvirt因为可以方便地克隆虚拟机而且nat网络内的MAC地址行为更接近物理交换机。请读者注意这一步是整个实验的起点后面所有排错都跟“网络环境不对”强相关。如果你手头只有两台机器也可以用一台机器既当Director又当客户端Real Server用一台虚拟机代替但至少需要在Real Server上执行curl验证否则你根本分不清是调度成功还是流量根本没到后端。2. ARP问题的根因与隐藏风险DR模式最大的坑不在IPVS规则而在ARP。默认情况下Linux主机会对自己拥有的所有IP地址的ARP请求进行应答包括配置在lo:0上的VIP。当客户端或者交换机广播“谁有192.168.122.100”时Real Server如果响应了客户端就会把请求直接发给Real Server这就绕过了DirectorVIP就失去了负载均衡的意义。更可怕的是如果两个Real Server同时响应交换机的MAC表就会在两个端口之间来回抖动大量报文被丢弃最终表现为整个VIP时通时不通。要理解这个问题的解决方案得先弄清楚Linux内核里的两个ARP相关参数arp_ignore和arp_announce。arp_ignore控制的是“收到ARP请求时要不要应答”0默认值只要有任何一个网卡配置了目标IP就应答不管请求到达哪块网卡1只有当目标IP是本网卡IP时才应答2只有当目标IP是本网卡IP且请求源IP与本网卡IP在同一子网时才应答实验里我们一般不用3-8更严格的条件范围过于琐碎生产环境很少用到。arp_announce控制的是“本机发出ARP请求时使用哪个源IP”0默认值使用任意配置在网卡上的IP这可能导致Real Server发出的ARP请求被别人学到VIP的MAC对应Real Server同样会引发路由混乱1尽量避免使用非本网卡IP作为ARP源地址2始终使用最合适的IP即从路由表中选出来的IP作为ARP源地址。在LVS DR模式下Real Server上的VIP为什么要配在lo回环接口上而不是配在eth0上原因很简单回环接口不会对外发送数据包只有本机进程访问VIP时才有意义对外的ARP由物理网卡eth0负责。如果配置在eth0上Real Server对VIP的ARP请求应答就很难完全抑制容易出现“既能收VIP流量、又应答了VIP的ARP”这种不伦不类的状态。下面是我在生产环境踩过坑之后总结的推荐配置适用于所有Linux内核版本RHEL/CentOS 7/8/9、Ubuntu 16.04均验证过# Real Server上执行 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注意第二行和第四行看着重复其实“all”是全局默认具体接口的配置会覆盖全局。我在实验里做过对比只设置all而不设置loReal Server在某些内核版本上依然会异常应答。为了永久生效请把以下内容写入/etc/sysctl.d/99-lvs-dr.confnet.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“eth0”要换成你实际的物理网卡名。写完之后执行sysctl --system重载并用ip addr show确认VIP已经落在lo:0上。这个操作看起来简单但漏掉任何一行后面都会出现“Director没流量”“VIP ping不通”“curl时好时坏”等让人抓狂的问题。3. Director上IPVS规则的配置细节Director这台机器核心工作有两个一是把VIP的ARP请求应答下来二是把流量按照调度算法转发给Real Server。第一个任务依靠的是“VIP配置在eth0上”这个事实——Director拥有VIP对应的IP地址因此能正常应答ARP第二个任务依靠的是ipvsadm命令。实验里我用的是轮询调度算法rr它是IPVS默认的调度算法之一适合后端处理能力几乎相同的场景。如果你的后端机器配置不一样例如一台4核8G、一台2核4G建议换成加权轮询wrr给高配机器更高的权重。配置步骤可以拆成以下几步我用root权限操作# 1. 配置Director的VIPeth0的局域网IP为192.168.122.10 ip addr add 192.168.122.100/32 dev eth0 # 2. 开启IP转发 sysctl -w net.ipv4.ip_forward1 # 永久生效写入 /etc/sysctl.conf为什么要使用/32掩码这里有个容易忽略的点VIP不应该占用整个子网的广播域它只是Director的一块“逻辑网卡”。使用/32掩码系统会把VIP当作点对点地址不会在网络上发送针对VIP的广播也不会参与子网内的普通广播通信。但要注意如果你把VIP配成/24它就会额外响应“192.168.122.255”之类的广播请求虽然大多数场景下不影响实验但会带来不必要的行为。继续配置IPVS规则# 3. 安装与启动管理工具 yum install -y ipvsadm # 4. 创建虚拟服务 ipvsadm -A -t 192.168.122.100:80 -s rr # 5. 添加两台Real Server-g表示DR模式 ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.21 -g ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.22 -g这一步里有几个标志位值得重点说明-A添加虚拟服务-t表示TCP协议后面跟VIP和端口-a在已有虚拟服务下添加Real Server-r指定Real Server的IP-g使用Gatewaying模式即DR模式这是实验的核心配置-w指定权重仅在使用wrr等算法时有效。配置完成后务必用ipvsadm -L -n检查规则。一个典型的输出如下IP Virtual Server version 1.2.1 (size4096) Prot LocalAddress:Port Scheduler Flags - RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.122.100:80 rr - 192.168.122.21:80 Route 1 0 0 - 192.168.122.22:80 Route 1 0 0看到Forward列是Route就说明DR模式配置成功了。如果是Tunnel或Masq那说明你选错了模式需要删除后重新添加。我在生产环境经常遇到的一个误区是Director自己也加入后端节点。如果你让Director既当负载均衡器又当Real Server配置IPVS规则时把192.168.122.10也加进来那当Director调度流量给自己时流量会进入本机协议栈但IPVS不会再二次转发所以会导致连接超时。实验阶段不要这么干除非你明确知道自己在做什么。IPVS规则还支持持久连接-p它的作用是让同一个客户端的多个请求在一段时间内始终调度到同一台Real Server。这个特性对需要session状态的应用如购物车非常有用。在实验里可以这样加ipvsadm -A -t 192.168.122.100:80 -s rr -p 300表示5分钟内同一客户端绑定同一台后端。但请注意持久连接和轮询调度是两码事加了-p之后连续请求不会均匀分配到两台机器这在压测时容易被误判为调度算法失效。4. Real Server的具体配置从安装HTTP服务到抑制ARPReal Server的配置是整个实验里最需要耐心的一步。很多人第一次做这个实验在Director上把IPVS规则配好然后满怀期待地用curl访问VIP结果返回的是“Connection timed out”——为了少走弯路我把自己在实验时的每一个操作都记录下来包括踩过的坑。4.1 安装并验证HTTP服务在rs-1和rs-2上分别安装Apache并写入不同内容的首页以便区分请求究竟被分发到了哪台机器yum install -y httpd echo Real Server 1 - 192.168.122.21 /var/www/html/index.html systemctl start httpd systemctl enable httpdrs-2上对应写入“Real Server 2 - 192.168.122.22”。为什么主页内容要不同因为实验要验证负载均衡是否生效如果两台机器的内容一样curl VIP只能看到反复相同的页面无法直观判断流量是否发生了调度。用“主机名加IP”区分是最直观的验证手段。4.2 配置VIP到lo接口把VIP配置在回环接口的子接口上有两种方式一种是临时生效用ip命令直接添加另一种是永久生效用ifcfg-lo:0配置文件。临时生效的写法ip addr add 192.168.122.100/32 dev lo注意这里不需要加“:0”标签lo是物理回环接口用ip命令添加VIP时它会在lo上自动创建一个子接口视图。你可以用ip addr show lo确认1: lo: LOOPBACK,UP,LOWER_UP mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet 192.168.122.100/32 scope global lo valid_lft forever preferred_lft forever如果希望重启后依旧保留建议创建一个新的配置文件。CentOS 7的系统里最简单的方式是写一个network-scripts风格的ifcfg文件cat /etc/sysconfig/network-scripts/ifcfg-lo:0 EOF DEVICElo:0 IPADDR192.168.122.100 NETMASK255.255.255.255 ONBOOTyes NAMElo:0 EOF ifup lo:0这里用255.255.255.255掩码也就是/32目的是让内核认为VIP是一个完全独立的主机地址不会把它当成整个子网的广播地址。配置完以后用ip addr show lo查看应该能看到lo:0出现在回环接口逻辑子接口列表中。4.3 配置抑制ARPReal Server的ARP抑制一定要在启动服务之前做否则你的服务可能已经被外界探测到了。稳妥的做法是先在/etc/sysctl.d/99-lvs-dr.conf里写好再执行sysctl --system最后再配置IP。顺序反了也不致命但毕竟养成好习惯能少踩坑。我用一个脚本把Real Server的配置统一管理起来脚本内容如下#!/bin/bash # LVS DR Real Server 配置脚本 # 用法: bash dr_rs_config.sh real_server_ip RS_IP$1 VIP192.168.122.100 # 1. 配置回环接口地址 ip addr add ${VIP}/32 dev lo # 2. 抑制ARP sysctl -w net.ipv4.conf.all.arp_ignore1 /dev/null sysctl -w net.ipv4.conf.all.arp_announce2 /dev/null sysctl -w net.ipv4.conf.lo.arp_ignore1 /dev/null sysctl -w net.ipv4.conf.lo.arp_announce2 /dev/null sysctl -w net.ipv4.conf.eth0.arp_ignore1 /dev/null sysctl -w net.ipv4.conf.eth0.arp_announce2 /dev/null # 3. 创建默认路由部分环境需要确保回包走eth0 ip route add ${VIP}/32 dev lo table local echo Real Server ${RS_IP} 配置完成第三步的ip route add ${VIP}/32 dev lo table local是一个经常被忽略的细节。在某些内核版本和网络拓扑下如果路由表里没有VIP对应的local路由本机进程访问VIP时有可能走默认路由出去结果把到VIP的流量发出去了产生环路。正常情况下Linux内核会自动把“配置在接口上的地址”加入local表但为了保险我在脚本里显式添加。生产环境的运维脚本里我也保留着这一行因为内核版本升级后行为可能会有微小变化。配置完以后用ip addr show和sysctl -a | grep arp验证确保arp_ignore和arp_announce的值都是预期的。5. 调度验证与流量特征观察配置好以后最爽的时刻就是验证结果。我在客户端机器上执行for i in $(seq 1 10); do curl -s http://192.168.122.100/; done如果一切正常输出应该交替出现“Real Server 1 - 192.168.122.21”和“Real Server 2 - 192.168.122.22”。这说明了rr轮询算法确实在工作。但“能轮询”只是第一步。我建议再做两个更细致的验证以确认DR模式的数据路径是符合预期的第一个是查看Director上IPVS的连接记录ipvsadm -L -n --stats一个典型的输出IP Virtual Server version 1.2.1 (size4096) Prot LocalAddress:Port Scheduler Flags - RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.122.100:80 rr - 192.168.122.21:80 Route 1 1 2 - 192.168.122.22:80 Route 1 1 1ActiveConn代表当前活跃连接数InActConn是非活跃连接数。如果看到两台机器的连接数在交替增长说明IPVS在正常工作。第二个验证是在Real Server上抓包。DR模式下Real Server收到的数据包源IP是客户端的IP目标IP是VIP但目标MAC地址是自己的MAC。这与NAT模式完全不同——NAT模式下目标IP会变成Real Server的IP。我常用tcpdump验证tcpdump -i eth0 -nn tcp port 80如果看到类似下面的报文说明数据包的到达符合DR模式的预期19:23:45.123456 IP 192.168.122.50.34567 192.168.122.100.80: Flags [S], seq 123, win 64240 19:23:45.123789 IP 192.168.122.21.80 192.168.122.50.34567: Flags [S.], seq 456, ack 124, win 28960源IP是192.168.122.50客户端目标IP是192.168.122.100VIP而实际响应来自192.168.122.21。这恰好证明了“入站流量经Director转发、出站流量由Real Server直接返回”的DR特征。如果你用的是虚拟化环境建议同时在各台虚拟机之间观察ARP表。我遇到的一个奇怪现象是Director的ARP缓存里Real Server的MAC地址有时会不对。原因是Real Server的VIP在lo上当客户端去访问VIP时交换机转发广播帧Real Server的物理网卡eth0可能因为相关配置没能完全抑制ARP应答导致Director学到了错误的MAC。手动清一下ARP缓存可以暂时恢复ip neigh flush all但治本的办法还是回到第2节仔细检查arp_ignore是否都设成了1尤其是“all”和“eth0”两个维度。6. 连通性排查从客户端到VIP再到后端实验中最常见的报错就是curl访问VIP超时。很多人这时候第一反应是“IPVS规则不对”其实超时的原因往往在ARP、路由或者防火墙。我把自己常用的排查顺序整理成一个“五步法”每一步都有明确的检查对象和判断标准照着做基本十分钟内能找到问题。6.1 第一步确认VIP在Director上可见且能ping通在客户端先ping VIPping -c 3 192.168.122.100如果ping不通先看Director上的VIP是否配置成功以及Director的eth0是否处于UP状态ip addr show eth0如果VIP存在但ping不通多半是防火墙拦了ICMP。检查并临时放行firewall-cmd --add-protocolicmp --permanent firewall-cmd --reload # 或者干脆先停掉firewalldsystemctl stop firewalld6.2 第二步确认Real Server的HTTP服务可直接访问在客户端直接访问Real Server的物理IPcurl http://192.168.122.21/ curl http://192.168.122.22/这一步是为了区分“Real Server本身有问题”还是“LVS链路有问题”。如果这里都不通那检查httpd服务和防火墙而不是去折腾LVS。6.3 第三步检查IPVS规则是否存在在Director上执行ipvsadm -L -n如果输出为空说明虚拟服务没建好重新执行第3节的ipvsadm -A和ipvsadm -a命令。6.4 第四步验证Real Server的ARP抑制是否生效RS上查看cat /proc/sys/net/ipv4/conf/all/arp_ignore cat /proc/sys/net/ipv4/conf/lo/arp_ignore cat /proc/sys/net/ipv4/conf/eth0/arp_ignore三个都应该是1。如果有任何一个返回0VIP的归属就可能变得“模棱两可”导致流量绕过Director。这个问题发生得最隐蔽因为Director的规则全对RS的HTTP服务也正常但整个VIP就是不稳定。6.5 第五步观察Director是否真的转发了数据包Director上抓包tcpdump -i eth0 -nn host 192.168.122.100 and port 80如果Director能收到来自客户端的SYN包并且IPVS规则存在那么Director会改写目标MAC后从eth0发出去。如果tcpdump里能看见SYN包但Real Server上的tcpdump看不见则说明二层转发存在故障例如VirtualBox/VMware的虚拟交换机隔离问题。这套五步法解决了我工作中遇到的绝大多数LVS DR故障。最后再提一个细节记得检查Director的物理网卡是否开启了rp_filter反向路径过滤。如果开启且配置为严格模式Director可能丢弃源IP是客户端IP但入口网卡不是路由期望网卡的响应包。LVS DR模式下Director一般只处理入站SYN对出站响应不负责但某些内核配置仍可能影响转发稳妥的做法是在实验环境直接关掉sysctl -w net.ipv4.conf.all.rp_filter0 sysctl -w net.ipv4.conf.eth0.rp_filter0这一步不是必须的但如果在某些CentOS 8环境遇到“SYN能进、响应超时”的怪问题值得一试。7. 经验总结DR模式实验中最常见的高频失误做LVS DR实验失败十次有九次是以下这几个原因。我先列出来帮大家提前避开Real Server的ARP抑制没有补全只设置了all却忽略了lo和eth0的具体配置。这个问题在CentOS 7上不明显但在Ubuntu 20.04和一些内核版本上会立刻暴露表现为VIP只能在Director所在机器上访问。Real Server的VIP物理接口配置错误如果把VIP配置在eth0上并且没有正确抑制ARP它会直接应答ARP请求导致流量不经过Director。更糟糕的是某些情况下两个RS会互相争抢VIP的ARP响应整个二层网络都会被干扰。Director没有开启IP转发net.ipv4.ip_forward1没设置Director收到请求后不知道该往哪路由结果直接丢弃。这个错误很基础但很多人配完IPVS忘了这一步。防火墙未放行80端口CentOS 7默认启用了firewalld即使你yum安装了httpd外部请求也可能被防火墙挡住。实验时最简单的方法是直接停掉firewalld或者用firwall-cmd放行http服务。客户端和Real Server之间的响应路径被拦截DR模式下响应报文直接由Real Server发出如果Real Server的默认路由指向一个不可达的网关响应就会丢。Real Server必须配置一条能通向客户端网络的默认路由网关通常是虚拟交换机/物理路由器。这在很多实验环境里被忽略了。每一个失误的根因其实都指向同一个核心认知LVS DR模式不是简单的“配置一个IPVS规则”它是一个二层转发加三层路由的联合工程。你要同时管理Director上的路由决策、Real Server上的ARP行为、以及网络设备上的MAC地址表三个层次。只要有一个层次的行为不符合预期整个VIP就会出现各种“玄学”问题。如果你做实验的目的是为了加深对负载均衡原理的理解建议不只在三台虚拟机里跑通而是把“手动配置”的所有步骤都亲手敲一遍不要一股脑用脚本。我在带新人时特别强调这一点手动操作能让你看到每一步系统产生的实际反应脚本只会掩盖细节。等你把细节摸透了再写脚本批量部署效率翻倍。最后再分享一个小技巧验证完基本轮询之后可以故意把其中一台Real Server的httpd停掉再执行一轮curl。你会在客户端观察到大约一半的请求连接被拒绝但IPVS规则里这台后端节点的故障状态不会自动调整。这恰恰说明LVS默认没有健康检查机制生产环境必须配合keepalived或者第三方健康检查工具来摘除故障节点。在实验里主动制造一次“后端挂掉”的场景比看一百篇理论文章都有用它让你真正理解为什么LVS落地时总要搭配一套健壮的高可用方案。
返回列表