最近给一套业务系统做接入层改造,用的就是LVS DR加keepalived这对经典组合。理清数据流向和ARP抑制那套逻辑花了不少时间,配置本身倒不算复杂,但很多坑都藏在理论和实际之间。想了想还是把这套东西完整记下来,从原理到实验一步步拆开讲,给同样准备上手群集负载均衡的同学省点时间。这套方案解决的是高并发接入和高可用问题,适合运维工程师、系统管理员,以及想搞懂负载均衡原理和落地配置的开发者参考。
1. 为什么是LVS DR+keepalived:这套方案到底解决什么问题
1.1 LVS的三种工作模式,为什么生产环境最常见的是DR
LVS在内核里主要有三种工作模式:NAT模式、TUN模式和DR模式。很多人第一次学LVS的时候都会有疑问,都是负载均衡,为什么偏偏DR模式出镜率最高。答案是成本和性能的平衡点抓得最好。
NAT模式把请求和响应都走Director,一个请求来回都要过负载均衡器,后端的响应数据量大时,Director就成了瓶颈。TUN模式需要所有后端服务器支持IP隧道协议,配置复杂度高,对内核和网络环境有额外要求。DR模式最巧妙的地方在于,Director只处理入站请求,后端服务器直接把响应回给客户端,响应流量根本不经过Director。这种“请求集中、响应分散”的模型,在视频、下载、业务接口这类响应体比较大的场景里优势非常明显。
我实际测试过一组HTTP服务,后端每笔响应大概200KB,用NAT模式时Director网卡出口带宽先是打满,而同样的流量切到DR模式后,Director轻得很,真正扛流量的是后端的网卡。所以DR模式不光是理论上的“最优解”,在真实业务里也是扛得住大流量的一种设计。
1.2 keepalived在集群里的角色,不只是“高可用”三个字
keepalived最初的核心功能是提供Linux服务器的健康检查和故障切换,后来和LVS配合得非常顺手,就成了LVS集群的标配伴侣。它做的事有两件:一是通过VRRP协议在主备Director之间漂移VIP,Director挂了自动切换;二是对后端Real Server做健康检查,发现某台后端异常就把它从转发列表里摘掉。
很多人把keepalived笼统地理解成“让VIP能飘”,其实健康检查才是日常防故障更关键的部分。后端服务卡死、端口无响应、网络不同,这些情况光靠VIP漂移是解决不了的,必须靠keepalived把故障节点移出调度池。我见过不少集群,主备切换没问题,但后端某台机器挂了照样往里转发请求,用户看到的就是间歇性报错,一查全是keepalived的健康检查没配上。
所以这套组合的逻辑是:LVS负责把流量按策略分发到多台后端,keepalived负责保证分发节点本身不成为单点,并且持续剔除后端故障节点。一个是转发引擎,一个是高可用和健康检查的守护者。
1.3 一个HTTP请求从客户端到后端的完整路径
理解了角色之后,把一次请求的完整路径走一遍比看十遍概念都管用。
客户端发起请求访问VIP,也就是192.168.1.100,这个IP在DR模式下配置在Director的网卡上,同时也配置在后端Real Server的loopback接口上。客户端的数据包到达真实网络后,由当前持有VIP的Master Director接收。Director的LVS模块根据调度算法,比如轮询、加权轮询或最少连接,选择一台Real Server,然后把数据帧的二层目的MAC地址改为该Real Server的MAC地址,原封不动地把这个包从局域网转发出去。
因为后端Real Server自己在loopback接口上绑定了VIP,它看到目的IP是自己,就收下这个包,经过本机协议栈处理后交给监听在VIP上的服务进程。响应数据生成后,Real Server直接把包发回客户端,源IP就是VIP,不回Director。客户端全程只和VIP通信,感知不到后端到底有哪几台机。
这套机制里最关键的地方,不是LVS转发,而是后端Real Server必须保证“自己不抢VIP的ARP应答”。如果后端服务器也用自己的物理网卡对外宣告“我有192.168.1.100”,那整个局域网里谁都可能抢到VIP的流量,集群直接就乱了。这就引出后面要花大篇幅讲的ARP抑制配置。
2. 实验环境规划与准备工作
2.1 规划一套能复现的拓扑和IP地址
做实验之前先把地址规划好,别到配到一半才发现网段冲突、广播地址乱套。这里给一套可以直接照抄的规划,五台机器全部处于同一个二层网络,不需要三层路由。
客户端一台,IP为192.168.1.66,用来发测试流量。两台Director,一台Master一台Backup,IP分别是192.168.1.10和192.168.1.11。两台Real Server,分别叫RS1和RS2,IP是192.168.1.20和192.168.1.21。所有人共享一个VIP,192.168.1.100。Master和Backup之间跑VRRP心跳,利用的就是这个二层网络。生产环境里如果条件允许,可以把心跳单独放一张网卡或独立网段,降低误切换的风险,但实验环境同网段跑没有问题。
操作系统我这边用的是同一系列的Linux发行版,官方源里直接有ipvsadm和keepalived两个软件包,装起来不折腾。这里提一句,不同发行版的包管理命令不同,但这套配置逻辑是通用的,配置文件和命令不依赖具体发行版。
2.2 网卡、软件包和基础服务准备清单
需要准备的工具其实就三样:ipvsadm、keepalived,以及后端的Web服务。ipvsadm是用户态的管理工具,用来配置内核里的LVS规则;keepalived负责VRRP和健康检查;后端服务我直接用Nginx或者Apache都行,验证的时候能返回不同内容就行。
实战里我建议后端两台Real Server返回不同页面或者不同hostname标识,这样才能一眼看出负载均衡是否真的把流量分到了不同机器。我这里给两台服务器分别放了不同的默认页面,RS1返回“Server RS1”,RS2返回“Server RS2”,验证起来特别直观。
安装命令在不同发行版上写法不同,但核心就两件事:装包、起服务。装好后先确认ipvsadm已经写进内核模块:
modprobe ip_vs lsmod | grep ip_vs能查看到ip_vs相关模块就说明内核支持LVS。keepalived安装后也确认一下版本号,老版本和新版本配置语法上略有差异,但核心配置块基本一致。
2.3 初始化配置:关闭防火墙干扰、开启路由转发
实验环境里最容易被忽略的就是防火墙和NetworkManager这类东西。新装系统的机器默认开着firewalld或ufw,VIP的VRRP报文用的是组播地址224.0.0.18,协议号112,很多防火墙默认会对这种组播报文做处理,导致主备节点互相看不到心跳,结果就是两台同时认为自己是Master,都绑定VIP。这就是脑裂。实验环境图省事,我直接停掉了防火墙:
systemctl stop firewalld systemctl disable firewalld如果生产环境必须要开防火墙,就要把VRRP组播和调度端口放行,但是实验阶段先把变量降到最少,故障排查也方便。
Director上还要确认开启IP转发。DR模式下Director做的是二层转发,改的是MAC地址,理论上不依赖IP转发开关,但有些内核版本和配置组合下还是开了更稳妥:
sysctl -w net.ipv4.ip_forward=1把这个写进/etc/sysctl.conf,防止重启后失效。后面配置完成之前,先别急着把RS绑VIP,否则时钟不同步、服务没起来都有可能干扰判断。一步一步来。
3. LVS DR模式的详细配置过程
3.1 Director节点上的调度规则配置
到这里开始动真格的了。先配置Master Director,用ipvsadm添加一条针对VIP:80的虚拟服务规则,再添加两台Real Server,并明确指定使用DR模式,也就是-g参数。我最开始做实验时就漏掉过-g,结果默认走的是NAT模式,流量死活不通。
# 在Master Director上执行 ipvsadm -A -t 192.168.1.100:80 -s rr ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.20 -g -w 1 ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.21 -g -w 1第一行添加VIP服务,-s rr表示用轮询调度算法,第二三行把两台Real Server加进转发池,-g指定DR模式。-w是权重,轮询算法下权重为1就是两台轮流来。查看配置结果可以用:
ipvsadm -L -n输出里能看到TCP 192.168.1.100:80 rr这样的虚拟服务,下面挂着两台路由到Real Server的条目,FWD列显示Route就说明走的是DR模式。如果是Masq,那就是NAT模式,说明-g没写对。
还需要把VIP绑定到Director的物理网卡上。生产环境为了避免ARP响应冲突,往往用单独的网卡或者子接口,我这里简化为直接加在eth0上:
ip addr add 192.168.1.100/32 dev eth0掩码用32,表示这是一个仅本机使用的独立地址,不参与网段的常规ARP广播。这只是手动绑定,重启会丢,后面配置keepalived时会自动管理VIP,这一条就是为了先让实验跑通。
3.2 Real Server上的ARP抑制和VIP绑定
这一节是整个DR模式实验里最核心的内容,也是大多数人第一次配置时最容易懵的地方。前面讲过DR模式要求Real Server必须能接收目的IP为VIP的包,所以要在loopback接口上绑VIP。但如果不做任何额外处理,Real Server一旦绑上这个VIP,它就会对ARP请求响应“192.168.1.100是我的”,和Director抢VIP的流量,整个集群就乱了,交换机ARP表也会震荡。
解决办法是绑定VIP到lo接口,同时修改内核ARP相关参数,让Real Server永远不会对外宣告这个地址。具体参数是这两个:
- arp_ignore设置为1,表示本机只回答目标IP是本接口IP的ARP请求,发到其他接口的ARP请求不响应
- arp_announce设置为2,表示对外发送ARP通告时,使用请求来源最匹配的接口地址,避免把lo上的VIP露出去
在RS1上执行:
# 绑定VIP到回环接口 ip addr add 192.168.1.100/32 dev lo # 调整内核ARP参数 sysctl -w net.ipv4.conf.all.arp_ignore=1 sysctl -w net.ipv4.conf.lo.arp_ignore=1 sysctl -w net.ipv4.conf.all.arp_announce=2 sysctl -w net.ipv4.conf.lo.arp_announce=2两台Real Server要执行一模一样的配置。all和lo两个段都要设,只设lo不设all,某些内核版本下网卡接口的行为还是会不一致。把这些参数持久化到/etc/sysctl.d/里,再加一条启动脚本或者用NetworkManager的钩子绑定VIP,重启才会生效。
这一步做完后,可以用一个简单方法验证:在客户端上ping VIP,能通,但把Master Director的网卡停掉,或者临时把VIP从Director摘掉,ping仍然通,那就说明ARL抑制没做好,某些流量可能已经被Real Server抢走了。正确的结果是,只有Director持有VIP时客户端能ping通VIP。
3.3 后端服务启动与手动转发验证
Real Server上启动Web服务后,一个容易踩的坑是服务默认只监听物理IP,结果访问VIP的时候连接被拒。需要确保服务绑定在VIP上,或者监听所有地址。Nginx默认监听0.0.0.0:80,直接就能用。Apache默认也是监听80端口,绑定所有地址,问题不大。如果后端用的是其他服务,记得检查监听地址包含0.0.0.0或VIP。
都准备好以后,在客户端上用curl访问VIP:
curl http://192.168.1.100/多访问几次,正常情况下会交替返回RS1和RS2的页面内容。看是否真正分发到了两台,用ipvsadm在Director上看连接统计:
ipvsadm -L -n --stats可以看到两个Real Server条目的ActiveConn、InActConn明显在交替增加。如果想更直观地看转发过程,在Director上抓包:
tcpdump -i eth0 host 192.168.1.100 and tcp port 80能看到进来的请求包目的MAC被改写成了RS的MAC,这就是DR模式转发时的标志行为。
4. 部署keepalived实现VIP高可用和健康检查
4.1 VRRP协议和keepalived状态机快速入门
keepalived能实现主备切换,底层靠的是VRRP协议。多台Director组成一个虚拟路由器组,share同一个VIP。组里所有成员通过周期性发送VRRP通告报文保持联系,Master负责响应VIP的ARP请求并转发流量,其他成员是Backup,处于待命状态。Master如果连续几个周期都没发通告,Backup就会认定Master挂了,把自己提升为Master,接管VIP。
这里有个优先级的概念,配置里priority数值大的会成为Master。另外VRRP报文用的是组播地址224.0.0.18,所以要保证二层网络能通组播。这也是前面说该放行防火墙的放行,否则就容易脑裂的原因。
keepalived会读取/etc/keepalived/keepalived.conf,里面除了VRRP配置,还有健康检查的部分。keepalived的healthy check不是独立进程去探活,而是配合LVS规则使用的。简单理解就是,它检查后端Real Server的IP和端口,如果发现某台服务异常,就自动从ipvsadm的转发池中删除该Real Server的规则,恢复后再自动加回来。这就是健康检查和LVS规则联动的机制。
4.2 Master和Backup的keepalived配置文件详解
先看Master的配置。一个完整的keepalived.conf包含global_defs、vrrp_instance和virtual_server三个大块。global_defs里主要是router_id,改成能识别的名字就行。vrrp_instance里定义VIP、接口、优先级、认证方式和VRRP组成员。virtual_server里定义VIP:端口和两个Real Server的探活参数。
Master节点配置这样写:
global_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.1.100/32 dev eth0 } } virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.1.20 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.1.21 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }Backup节点和Master基本一样,只需要把state改成BACKUP,priority改成90。virtual_router_id两边的值必须一致,认证字段也要一致,否则互相不认。auth_pass在生产里只是简单密码,不会加密传输,核心网络环境安全问题别依赖它,真正隔离靠VLAN和网络策略。
persistence_timeout这个参数值得单独说。它表示来自同一个源IP的连接在一段时间内都保持绑定到同一台后端。实验阶段建议先设成0或者直接注释掉,方便看到轮询效果。生产环境看业务类型,如果是有状态的登录会话,需要开长一点的持久化时间,比如180秒,否则用户刷新页面就可能跳到另一台后端导致登录态丢失。这也是为什么后来又出现LVS加共享存储加Session同步的各种方案,但一开始先理解清楚持久化参数的作用更重要。
4.3 启停服务和切换验证
配置好之后,启动两台Director上的keepalived服务:
systemctl start keepalived systemctl enable keepalived等几秒钟,分别查看两台的VIP绑定情况。正常情况下Master上有192.168.1.100,Backup上没有。通过ip addr可以看到VIP只出现在Master的eth0上。
如果两台同时有VIP,说明脑裂了。优先检查防火墙和VRRP组播是否被挡,再确认virtual_router_id和认证信息是否一致。
验证切换的步骤很有成就感:直接停掉Master上的keepalived或直接断网模拟宕机:
systemctl stop keepalived这时候在Backup上再看ip addr,VIP应该在几秒内漂移过来。用客户端持续curl VIP,你会发现服务没有中断,或者中断几秒后自动恢复。这也就是高可用的意义所在,用户只访问VIP,Director本身挂了,VIP切到另一台,业务照常。
再把Master的keepalived启动,观察VIP是否回切。默认情况下,配置了nopreempt的时候Backup不会主动抢回VIP,但标准配置下Master恢复后会重新抢占。生产环境为了防止频繁切换导致抖动,根据业务需要决定要不要开启非抢占模式。非抢占模式需要两台都配成BACKUP,配合优先级实现,配置稍显绕,需要在文案里提醒一句,但默认模式的主动回切已经能满足大部分场景了。
健康检查的验证也有意思。直接把RS1的Web服务停掉:
systemctl stop nginx等delay_loop设置的轮询周期过了,在Master上看ipvsadm -L -n,RS1的转发规则自动消失,所有流量都只发到RS2。把服务启动回来,规则又自动恢复。这个自动摘除和恢复的功能,就是keepalived健康检查和LVS联动的价值。
5. 常见问题与排查技巧实录
5.1 客户端ping不通VIP,但服务是好的
这个问题十次有八次出在Real Server的ARP抑制上。现象是VIP在Director上能看到,后端Web服务也在监听,但客户端怎么也访问不通。
排查先把Real Server上的lo绑定的VIP摘掉,只剩Director持有VIP,再ping一下。如果通了,问题就出在ARP抑制参数上。检查方法是在Real Server上执行:
cat /proc/sys/net/ipv4/conf/all/arp_ignore cat /proc/sys/net/ipv4/conf/lo/arp_ignore cat /proc/sys/net/ipv4/conf/all/arp_announce cat /proc/sys/net/ipv4/conf/lo/arp_announce常见问题是只设置了all,没有设lo,或者反过来只设了lo,忘了all。sysctl配置是分层的,all代表全局默认,具体接口还有一层,必须两个维度都覆盖才能确保行为一致。另一个常见问题是系统重启后参数被重置,因为没写进sysctl.conf,所以我建议直接把配置写到/etc/sysctl.d/99-lvs-sysctl.conf里,一劳永逸。
5.2 看起来轮询了,但流量还是压在同一台上
出现这种情况,先看ipvsadm -L -n里两个Real Server的条目是不是都正常,如果有一台FWD列显示Masq而另一台是Route,那就是添加规则的时候有个- g忘写了。Route代表DR模式,Masq代表NAT模式,混着加会产生很诡异的现象,部分请求走NAT部分走DR,网络表现完全乱掉。统一删掉错误规则重新添加就好。
还有一种情况是后端两台Real Server的权重没配好,rr轮询下权重会显著影响分配比例,如果业务要求严格轮询,权重都设1就行。如果配置了persistence_timeout,源IP的持久化表现也会让你觉得“没有轮询”,同一个客户端会一直连着同一台,这是来自地址持久化的限制。验证轮询效果时要么关闭持久化,要么用不同源IP去访问。
5.3 主备切换后服务恢复,但VIP在交换机上的端口飘移问题
有时主备切换后,客户端访问VIP恢复正常,但网络里有部分机器还是把VIP的MAC对应到老的Master地址,导致访问还是失败的景象。这是因为交换机ARP表有老化时间,切换瞬间VIP的MAC变了,但老ARP项还没过期。keepalived切换时会主动发送免费ARP通告,但有些交换机或终端对免费ARP的处理策略不同,就卡住了。
解决办法是不要把MAC老化时间调得过长,特殊环境可以在终端上flush ARP缓存,但生产环境里还是靠keepalived本身的免费ARP机制,以及调整交换机VRRP相关的配置参数来解决。保持advert_int设置合理也是关键,抓包时能看到Master按秒发送组播广播。
5.4 一些日常排查用的顺手小技巧
最后留几个我在实操中觉得特别值得推荐的习惯。
第一,Director上修改完ipvsadm规则后,用ipvsadm -L -n --rate看看每秒连接和流量,这个视图比列表视图更能反映出实时负载变化。第二,抓包尽量只在Director的eth0上抓,顺带把Real Server的MAC地址过滤出来对比,抓包范围不需要太大,抓百来个包就足够判断问题。第三,keepalived的日志写在系统journal里,起不来或者频繁切换时第一时间查:
journalctl -u keepalived -f日志里最常看到的就是VRRP实例状态反复切换,这时候排查两个方向:一层是不是优先级配置有问题,另一层是不是确实有网络抖动导致心跳丢了。
还有个工作中容易忽略的点,keepalived配置文件里不要随手写多余块,比如有的老配置会把virtual_server的配置反复写两遍,keepalived启动没问题,但会有一些隐性的调度异常。保持配置干净,改动时一次只改一个参数,验证通过后再改下一个。
做这套实验的时候,我自己清理过不少配置,把keepalived的virtual_server段和ipvsadm规则反复对比才理清楚关系。keepalived不会自动读取你当时手动用的ipvsadm规则,你会需要手动先把规则清掉,让keepalived全权接管分发配置,这个细节很关键,多台机器配合的时候尤其明显。建议配置好keepalived后,手动清掉ipvsadm里自己加的规则,靠keepalived的配置文件去管理一切。
实际跑一段时间后,你会发现这套架构真正的优势是可靠,容错边界清楚,LVS转发效率高,keepalived切换时有条理但又不是特别激进。理解DR模式的ARP原理、keepalived的状态机制、健康检查的摘除逻辑,基本就能把这套方案的底层吃透。后续还能往加权调度、多实例VIP规划甚至和云网络结合的方向扩展,原理相通。这次就到这儿,配置上有具体报错的话可以拿出来一起研究研究。