news 2026/10/10 20:52:37

keepalived+LVS高可用负载均衡实战:从原理配置到故障切换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
keepalived+LVS高可用负载均衡实战:从原理配置到故障切换

刚接手这套系统的时候,我其实对keepalived+LVS是有点抵触的——毕竟公司里不少人在推云负载均衡,谁还愿意自己搭一套四层转发呢。直到有一次半夜接到电话:后端两台Web服务器一张网卡傻掉,前面那台单点Nginx直接把所有流量拒之门外,我才真正下决心把原来那套“一台LB扛所有”的架构换掉。

后来在几十台机器的规模上跑通了keepalived+LVS高可用方案,稳定跑了两年多,中间做过十几次演练,结论是:这个组合在四层流量分发和网关高可用这个场景里,依旧是性价比最高、最可控的选择之一。这篇文章我就把从原理到配置、从验证到排障的完整过程整理出来,分成五个部分,按我自己上线的顺序写,希望能给正在评估或已经准备动手的人一些参考。

1. 为什么我在生产环境最终选了keepalived+LVS这套组合

1.1 单点故障是怎么暴露出来的

先说背景。我负责的是一套面向内部业务系统的统一入口,流量从外部打到一台Nginx上,再由Nginx反代到后面的若干应用节点。早期并发量不高,一台Nginx四核八线程妥妥够用。可等到日活上来之后,问题开始显现:某一台后端节点发布上下线稍微慢一点,Nginx的upstream探活会把流量都堆到剩余节点;赶上Nginx自己所在宿主机网卡故障或者内核异常,整个入口就彻底断了。

网上很多人讲高可用,喜欢从“要买两台机器”开始讲。但真实生产里,单点故障往往是慢慢暴露的——先是监控图上某个指标曲线消失,再是凌晨收到“入口不可达”的告警,最后才是你被迫在半夜爬起来切流量。我那次就是凌晨两点,一条“所有域名超时”的告警直接把值班群炸了。

我当时的第一反应是加一台Nginx做主备。但仔细一想,Nginx本身就是七层组件,它在转发能力、并发上限上也有自己的软肋;更关键的是,Nginx主备切换即使做了,前置的VIP漂移、健康检查、失败重试这些逻辑都需要自己写脚本或者依赖第三方组件。与其在七层上纠结,不如把四层的流量入口先做扎实——四层这一层稳了,上层Nginx也好、应用也好,压力都会小很多。就是因为这个思路,我盯上了LVS。

1.2 keepalived和LVS各管哪一段

很多人把keepalived和LVS当成一回事,其实分工非常清晰。LVS(Linux Virtual Server)负责的是流量转发:它工作在TCP/IP协议栈的四层,把进来的请求按照调度算法分发给后端的RealServer。keepalived则负责两件事,一是提供VIP的高可用漂移能力,二是对后端的RealServer做健康检查。

可以这么理解:LVS是“干活的手”,keepalived是“管活的大脑”。LVS本身不感知机器故障,它只按照规则把包发出去,哪怕后端机器已经宕了它也一样发。所以必须由keepalived定时去探测各个RealServer的状态,一旦发现某个节点不健康,就把这个节点从LVS的转发列表里摘掉;同时keepalived还在Director之间跑VRRP协议,保证主Director挂了之后,备用Director能立刻接管VIP,继续对外提供服务。

这两者合在一起,才形成了完整的“负载均衡+高可用”闭环。单用LVS,没有健康检查和VIP漂移,出问题该切还得人工;单用keepalived,没有LVS的转发能力,它也只能漂移一个没人用的VIP。所以生产环境里这俩组件几乎是绑定出现。

1.3 和Nginx、云SLB放到一起怎么取舍

我见过不少团队在这个选型上犹豫。简单说下我的判断:

方案优点缺点适用场景
LVS+keepalived性能极高、四层转发延迟低、不依赖外部厂商、可控性强配置有门槛,DR模式要处理ARP,七层能力要交给上层组件高并发入口、数据库/缓存前端的流量分发、自建机房
Nginx主备配置直观、七层路由/重写能力强、社区资料多高并发下CPU开销高、切换依赖额外组件中小规模Web入口、需要HTTP层逻辑的网关
云SLB免运维、弹性好、自带防护依赖云厂商、费用随流量增长、个别场景有连接数限制没有专职运维的团队、预算充足的云上架构

实际生产里,我更多把它们当成互补关系:最外层用LVS做四层分发,后面挂一组Nginx做七层路由和SSL终结,再往后才是应用集群。这样LVS只管“把请求发给谁”,Nginx只管“请求到了之后怎么处理”,各干各擅长的事,排查问题时边界也清楚。

2. 动手前必须先想清楚:架构规划与IP编排

2.1 机器角色划分:Director、RealServer、VIP

我见过不少人拿到keepalived+LVS就直接开配,结果IP段没规划好、回环地址互相冲突,折腾几天才搞清楚问题在哪。其实部署前把下面三组角色理清楚,后面会省很多事。

  • Director:也就是负载均衡器,负责转发流量。生产环境至少要两台,一主一备,主备都需要安装LVS和keepalived。
  • RealServer:真正处理业务的服务器,跑着Nginx、Tomcat或者其他服务。LVS做负载均衡时,后端的RealServer只需要回应请求,不需要安装LVS相关组件。
  • VIP(Virtual IP):对外暴露的虚拟IP,也就是客户端真正访问的地址。VIP在正常情况下绑定在主Director上,故障时漂移到备Director上。

我习惯把所有角色的IP和职责先写进一个表格,在部署前和团队对一遍。比如我最近一次上线用的规划是这样:

角色主机名IP地址说明
Director主lb01192.168.1.11初始MASTER,持VIP
Director备lb02192.168.1.12BACKUP,故障时接管VIP
RealServerrs01192.168.1.21业务节点A
RealServerrs02192.168.1.22业务节点B
VIP-192.168.1.100对外公布地址
网关-192.168.1.1统一出口

这个规划里有一个细节容易踩坑:Director的两台机器和RealServer最好在同一个二层网络里,因为DR模式(后文会详细讲)要求所有节点能在二层互通。如果你把Director放在一个网段、RealServer放在另一个网段,DR模式基本就要泡汤,只能考虑NAT模式或者改架构了。

2.2 DR模式为什么是首选,以及它带来的ARP问题

LVS有三种工作模式:NAT、DR、TUN。我直接说结论:自建机房的内网服务,首选DR模式。原因有三个:RealServer返回给客户端的响应包不用经过Director,转发效率最高;Director本身不成为链路瓶颈;配置相对简单。

但DR模式有个必须解决的问题:客户端访问VIP时,ARP广播会问“VIP在哪台机器上”,正常情况下VIP绑在主Director上,主Director会响应。可如果RealServer也把VIP配到了自己的loopback接口上,RealServer也可能响应ARP,这就出大事了——客户端发往VIP的包可能被RealServer抢走,而RealServer再转发又不知道该送给谁,整个链路就乱了。

解决办法是让RealServer抑制对VIP的ARP响应,这就是网上所有DR模式教程里都会出现那几句sysctl配置的原因。后面配置章节我会给出完整脚本,这里先把原理讲明白:你必须让VIP在各个RealServer上“存在但不出声”,就像每个人都把门牌号写在自己屋里的镜子上,但临街的马路上只挂主Director的招牌。

2.3 各网卡和网关的边界条件

除了IP,还建议关注下面几个边界条件:

  • Director上VIP绑定的网卡,建议用单独的接口或者子接口,比如eth0:1,不要和业务IP混在同一张主接口上,方便观察和抓包。
  • VRRP协议使用组播地址224.0.0.18,端口112。有些交换机开了组播过滤,或者开启了DHCP Snooping,可能导致keepalived的心跳报文被丢掉,主备两台机器会互认为对方故障,出现“脑裂”。上线前务必确认交换机的组播配置。
  • RealServer上的默认路由不要指向VIP,也不要指向Director的IP,而是指向正常的物理网关。否则响应包可能绕回Director,造成环路。

我在第一次部署时就是因为RealServer的默认路由写得不对,导致返回包经过Director,Director又把它转发回RealServer,形成了一个奇怪的闭环,压测时延迟高得离谱。后来把RealServer的路由恢复成走物理网关,症状立刻消失。这个细节大家务必注意。

3. 生产环境下的全套配置实操

3.1 keepalived主备配置逐项解读

接下来是重头戏。先说keepalived的配置,我使用的是CentOS 7系列系统,keepalived版本1.3.5,配置文件路径是/etc/keepalived/keepalived.conf。

主Director(lb01)的配置:

global_defs { router_id LVS_MASTER enable_script_security } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 511111 } virtual_ipaddress { 192.168.1.100/24 dev eth0 label eth0:1 } track_script { chk_lvs } } virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo wrr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.1.21 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.1.22 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }

几个关键参数我要单独拿出来说,因为配置时真容易搞混:

  • virtual_router_id:同一个VRRP实例的两台机器必须一致,取值范围0到255。如果有多套keepalived高可用组共处在同一二层网络,这个ID不能重复,否则会互相干扰。
  • priority:主备切换的依据。数值越大优先级越高。备机一般建议比主机低50左右,不要只低1,避免网络抖动时频繁切换。
  • advert_int:VRRP心跳间隔,单位秒。默认1即可,不要为了追求“快速切换”把它改到0.2或者0.1,那样会在高负载下产生大量组播包,反而加大交换机负担。
  • persistence_timeout:会话保持时间。如果业务没有强会话要求,建议设成0或者很小的值。我之前设了50秒,结果压测时发现同一IP的请求总是打在同一台RealServer上,以为调度算法失效,后来才明白是persistence起了作用。

备Director(lb02)的配置和主基本相同,只改下面几个地方:

  • router_id改成LVS_BACKUP
  • state改成BACKUP
  • priority改成50

注意,VRRP协议不是严格依赖state字段来判断谁当老大的,真正起作用的是priority。所以就算你两台都写MASTER,只要priority有高低,它照样能选出主。但生产上还是建议state写清楚,方便别人看配置的时候理解你的意图。

3.2 LVS转发规则什么时候生效:ipvsadm

keepalived配置好之后,LVS的规则其实是由keepalived动态写入内核的。也就是说,你不需要手动去执行ipvsadm的添加命令,keepalived会根据virtual_server段的内容自动生成规则。

但有一个前提:keepalived配置里的virtual_server要和VIP端口对应好。比如VIP是192.168.1.100,端口是80,那么客户端访问192.168.1.100:80时,LVS才会把请求转发到RealServer。如果你业务端口是8080,VirtualServer段也要同步改成8080。

为了确认规则是否生效,我用的是这套验证命令:

ipvsadm -L -n

正常情况下你会看到类似输出:

IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.100:80 wrr persistent 50 -> 192.168.1.21:80 Route 1 0 0 -> 192.168.1.22:80 Route 1 0 0
  • 如果列表里看不到任何规则,多半是keepalived没起来,或者配置格式有报错。看日志用tail -f /var/log/messages,keepalived的报错会写在里面。
  • 如果Forward那一列显示的不是Route而是Masq,说明当前工作模式不是DR,而是NAT。需要回到配置里检查lb_kind DR是否写对。

3.3 RealServer上的VIP绑定与环境收敛脚本

RealServer本身不用装keepalived和LVS,但必须在loopback接口上绑定VIP,并调整ARP参数。这是我上线前一直在用的脚本,建议放到/etc/rc.local或者systemd服务里开机自启:

#!/bin/bash VIP=192.168.1.100 ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP up route add -host $VIP dev lo:0 # 关闭对VIP的ARP响应 echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce sysctl -p

这里我要特别解释一下arp_ignore和arp_announce这两个参数到底在干嘛:

  • arp_ignore=1:只回答目标IP是本机IP的ARP请求。因为VIP虽然在lo上,但lo不对外响应,所以RealServer就不会去抢答VIP的ARP请求。
  • arp_announce=2:在ARP请求中使用最优本机地址,而不是使用可能错误的源地址。这能确保RealServer发送的ARP请求来自真实的内网IP,而不是VIP。

同时注意,RealServer上的业务服务(比如Nginx)监听的是0.0.0.0:80,这样VIP绑到lo上后,请求到达lo上的VIP,Nginx一样能接住。如果你让Nginx只监听内网IP而不监听VIP,那VIP的流量到了机器上也没有进程接收,健康检查就会出问题。

4. 故障切换的真实过程与验证手段

4.1 主Director宕机后发生了什么

配置完成、服务正常后,你一定会想:到底一切换,流量会不会断?我们看看真实发生的过程。

假设主Director(lb01)因为断电直接宕机,整个过程如下:

  1. 备用Director(lb02)在3个advert_int周期内没有收到lb01的VRRP心跳报文,触发超时。
  2. lb02把自己的状态从BACKUP提升为MASTER,并在eth0上绑定VIP 192.168.1.100。
  3. lb02发送免费ARP(Gratuitous ARP),通知同一二层网络内的交换机:“VIP的MAC地址已经变了,请更新转发表”。
  4. 后续客户端发往VIP的请求,到达交换机后,被转发到lb02。
  5. lb02上的LVS规则接管流量,按调度算法继续分发到后端的RealServer。

从客户端视角来看,它在TCP层连接的是VIP,只要TCP连接还在维持,请求几乎不会有感知;如果是新建立的连接,在切换完成的几秒内可能会出现连接超时或者拒绝。这也是为什么keepalived的advert_int、priority这些参数会影响切换速度和质量。

我在机房做过一次真实的断电网演习,从拔掉主Director电源,到lb02收到VIP并开始正常转发,耗时大约4到6秒。期间有一批新请求建立连接时RST,但已建立的连接没断。对大多数内部系统来说,这个时间窗口是可以接受的;如果是金融交易或者秒杀这类超敏业务,就需要在更上层做重试和降级策略了。

4.2 如何优雅地做切换演练

既然上了高可用,就不能只在出了事故时验证。我习惯每一到两个月做一次主动切换演练,方法是手动停掉主Director上的keepalived进程:

systemctl stop keepalived

观察指标包括:

  • 备用Director是否在预期时间内接管VIP(用ip addr show eth0看VIP是否出现)。
  • 业务侧是否有大量5xx或连接失败(要有基本监控,至少用脚本发HTTP请求探测)。
  • 主Director恢复后,VIP是否自动回切(默认是会回切的,因为priority更高)。

回切其实是双刃剑。好处是恢复初始架构,坏处是一旦主Director回来后,可能引发一次新的连接中断。所以很多生产团队会把主备配置成“不抢占”模式,也就是nopreempt。做法是在两组配置的vrrp_instance里都加上nopreempt,这样VIP不会自动飘回原主,除非原主明确丢失了VIP。我个人更倾向保留抢占,前提是你在低峰期做恢复。这个看团队的运维习惯,没有绝对对错。

4.3 健康检查到底该用什么方式

keepalived对后端RealServer的健康检查有三种方式:TCP_CHECK、HTTP_GET、SSL_GET、MISC_CHECK。我只讲两个生产里常用到的。

TCP_CHECK适合纯TCP端口探活。比如后端是Nginx监听80,就用connect_port 80。但这里有个坑:TCP_CHECK只验证端口能连上,不验证业务逻辑是否正常。如果Nginx进程还活着、端口还开着,但upstream已经打满、返回全是502,TCP_CHECK照样认为节点健康,依然会把流量分过去。

所以对于HTTP服务,我更推荐HTTP_GET。它不仅检查端口,还会实际请求一个URL,如果返回码非2xx/3xx,就判定节点异常。配置示例:

real_server 192.168.1.21 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } }

注意,后端必须要有一个/healthz这样的轻量接口,并且这个接口不能被限流或者鉴权。我曾经遇到过某团队把健康检查请求指向了登录页,结果换季时验证码服务故障,把所有RealServer都检查成了异常,流量雪崩。健康检查的接口最好返回纯文本,不连数据库、不查缓存,只做进程级探活,最多检查一下关键依赖是否在线。

5. 我在生产环境踩过的坑和优化记录

5.1 配置里最容易写错的三个地方

第一个是virtual_router_id冲突。有一次我们和另一个部门共用了一台交换机,他们的keepalived也用了ID 51,结果两边VRRP互相抢VIP,表现为VIP一会在一台机器上,一会又消失。排查先用tcpdump -i eth0 vrrp抓包,发现同一个ID来源不止一组MAC,最后定位到是ID冲突。改掉之后就彻底安静了。

第二个是persistence_timeout设置过长导致调度不均。上面提过,这个参数适合有会话保持需求的业务,但没有需求的时候千万别乱开。把它设成0后,调度算法立刻恢复均匀分布。

第三个是RealServer的arp_announce参数配错。注意lo和all两个作用域都要设置,只设lo不够,因为内核在某些场景会读取all下的配置。我踩过一次只设了lo的亏,结果vip还是时不时被RealServer响应,排查半天才发现all下的值还是默认的0。

5.2 长时间运行的性能瓶颈检查

LVS本身性能很强,百Gbps吞吐的都有,但DR模式下有个不可避免的开销:它需要维护每个连接的状态。如果业务长连接非常多,Director的状态表会膨胀,内存占用持续上涨。可以通过ipvsadm -L -n --stats观察连接数,也可以通过cat /proc/net/ip_conntrack | wc -l查看连接跟踪条目的规模。

我遇到过这样一个场景:后端服务是WebSocket长连接,每台机器几万个连接维持在线,LVS状态表一路涨到几十万条,Director内存占用居高不下。优化方向是缩短连接超时、定期清理无效连接。但在LVS层直接清理会影响已建立的会话,所以我最终把长连接业务从LVS后端挪走,单独用一层网关承载,LVS只负责普通HTTP请求。这件事给我的教训是:LVS适合短连接和普通会话,长连接场景要提前想清楚连接跟踪的运维成本。

另外,建议给ipvsadm的调度算法留一点思考空间。我默认用wrr加权轮询,简单且平均。但如果后端节点性能差异明显,建议用lc最小连接数,让连接数少的节点多接一点流量。具体用哪个,没有标准答案,压测数据就是最好的依据。

5.3 监控告警的补充脚本

最后这部分是我的私藏。keepalived本身只负责切换,但它不会替你做完整的业务监控。我建议在Director上部署一个简单的监控脚本,每30秒检查一次VIP归属和LVS规则是否存在:

#!/bin/bash VIP=192.168.1.100 if ! ip addr show eth0 | grep -q "$VIP"; then echo "VIP lost on $(hostname) at $(date)" >> /var/log/lvs-monitor.log fi if ! ipvsadm -L -n | grep -q "$VIP"; then echo "LVS rule missing on $(hostname) at $(date)" >> /var/log/lvs-monitor.log fi

这个脚本只做记录,不做自动处理,但配合告警组件,基本能把“VIP丢了”“规则没了”“keepalived挂了”这类潜在故障第一时间暴露出来。比单纯看进程还活着要靠谱得多。

还有一个我个人的小习惯:每次调整keepalived.conf之后,先跑一遍keepalived -t -f /etc/keepalived/keepalived.conf做语法检查,再重启服务,避免因为一个标点符号让整个高可用链路在夜里悄悄失效。

这套组合我已经维护了相当长的时间,它不见得是最花哨的架构,但每次出问题,它都能按预期切换、按预期转发。如果你也要在生产环境中搭高可用入口,我建议先从这套配置跑起,把切换演练做扎实,再去想那些更复杂的编排方案。四层稳了,上层才能安心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 20:45:50

Agent平台超时故障剖析:从同步编排到异步化改造实践

1. 项目背景:Agent Platform 到底在做什么1.1 这个平台解决的核心问题先说背景。我接手的是一个面向企业客户的 Agent Platform,简单来说,就是把多个大模型 Agent 编排起来,对外提供统一的对话与任务执行接口。业务方通过这个平台…

作者头像 李华
网站建设 2026/10/10 20:42:22

PHP微信支付v3完整实现:签名验签、证书管理与回调解密

简介:本资源是面向PHP后端开发者与微信支付接入初学者的V3版完整实践方案,聚焦最新微信支付接口集成中的证书管理、API签名、统一下单、异步回调及沙箱测试等核心环节,解决生产环境中常见的配置混乱、签名失败、通知验签异常等痛点。压缩包共…

作者头像 李华
网站建设 2026/10/10 20:41:39

Ceph运维实战:从核心指标到故障排查与自动化落地

接手过Ceph的人都有一个共识:这系统不是装完就完事的,真正的活儿全在运维。我在生产环境里折腾Ceph也有几年了,从最初的三节点小集群一路扩到几百个OSD,期间经历过PG卡在activeremapped的焦虑,也见过一块慢盘拖得整个集…

作者头像 李华
网站建设 2026/10/10 20:41:31

AnyPS5:PS5格式解析与协议映射框架技术解析

项目标题:“AnyPS5”这个名称本身带有强烈的指向性与模糊性并存的特点——它既像一个技术代号,又像一句口号;既暗示了与PlayStation 5生态的关联,又刻意回避了官方命名规范;既可能指向兼容、模拟、跨平台运行&#xff…

作者头像 李华
网站建设 2026/10/10 20:38:47

风机叶片缺陷检测数据集:18912张图与YOLO/COCO/VOC格式实战

简介:本资源为风力涡轮机缺陷检测数据集,面向从事新能源设备智能运维、工业视觉检测的算法工程师与高校研究者,可用于训练和评估风机叶片、塔筒等关键部件的缺陷识别模型。数据集包含18912张图片,支持YOLO、PASCAL VOC XML与COCO …

作者头像 李华