1. 先理清一个老误会:LVS、Keepalived、HAProxy并不是同一个层面的东西
1.1 一个架构评审里的经典“翻车现场”
我做过不少技术评审,几乎每次都会问候选人:你们当前入口负载均衡用的什么方案?十个人里至少有六个会脱口而出“LVS、Keepalived、HAProxy全套都上了”。我再追问一句“那它们分别负责什么”,场面就开始安静了。
这不是哪个人的水平问题,而是网上的安装教程太容易让人产生错觉。很多教程的标题就是“LVS+Keepalived+HAProxy集群搭建”,实际操作也是三样一起装,装完看到了一串自动生成的配置,却没人告诉你这三样东西根本不在同一个分工层:
- LVS是一个四层负载均衡器,工作在内核态,基于Netfilter框架,负责把大量连接按算法快速转发给后面的真实服务器;
- Keepalived是一套高可用软件,核心是VRRP协议,解决的是“VIP不丢”的问题,附带着能做健康检查并动态调整LVS的后端RS列表;
- HAProxy是一个用户态的四层/七层代理,能做精细的路由、ACL、会话保持、健康检查、限流和可视化统计。
一句话概括:LVS负责“快”,Keepalived负责“稳”,HAProxy负责“灵活”。把三者当成同一个东西来理解,选型和排障都会走弯路。
1.2 各自的出身决定各自擅长什么
LVS是Linux Virtual Server,它诞生很早,目标就是在Linux内核里直接做负载均衡,尽量不引入用户态开销。它不像Nginx、HAProxy那样跑一个进程去接受连接、转发数据,而是通过ip_vs模块拦截进入的包,在流量路径上做转发决策。所以LVS能做到很高的并发转发能力,尤其是使用DR模式时,响应包直接回给客户端,LVS本身不吃出口带宽。
Keepalived最初的使命是配合LVS工作,让LVS从单点变成高可用集群,顺便通过vrrp机制检测后端RS的健康状态,自动把挂掉的机器从LVS调度表里摘掉。后来大家发现它的VRRP能力可以独立使用,于是也让它给Nginx、HAProxy、业务进程提供VIP漂移。
HAProxy诞生的时候,互联网业务已经不再只是简单的“转发”,而是需要按域名、URI、Header、Cookie做不同的流向控制。HAProxy把这些能力集中在一个可配置、可观测的用户态进程里。它对HTTP协议的理解、健康检查的精细度、统计信息的丰富程度,都远胜LVS。代价是每一个连接都要经过用户态处理,性能和内核态的LVS相比还是要差一点。
这个“出身”差异决定了日常使用的基本盘:
- 追求极致吞吐、要处理海量连接,前排放LVS;
- 需要按业务路由、做精细治理,中间放HAProxy或Nginx;
- 不管前面放谁,都要一套VIP漂移和健康检查,那就用Keepalived。
1.3 一张表看明白三者的能力边界
| 比较项 | LVS | Keepalived | HAProxy |
|---|---|---|---|
| 工作层级 | 内核态四层 | 控制面协议 | 用户态四层/七层 |
| 核心职责 | 数据转发 | VIP管理、主备切换 | 代理转发、路由、健康检查 |
| 能否独立对外服务 | 不能独立做高可用 | 不能做数据转发 | 可以,但要另配高可用方案 |
| 健康检查能力 | 极弱,依赖外部 | 自带LVS联动检查 | 丰富,支持HTTP/TCP等多种检查 |
| 会话保持 | 靠调度算法/持久连接 | 不涉及 | Cookie、Stick Table、源地址等 |
| 性能上限 | 极高,DR模式回包不完经过自身 | 不影响数据面 | 高,但受进程和内存模型限制 |
| 适合场景 | 入口流量很大的四层转发 | 任何需要VIP漂移的场景 | 业务路由、多域名、精细校验 |
所以当有人跟你说“我用LVS做负载均衡”,严格讲应该是“我用LVS做内核态转发,用Keepalived保证它不单点故障,用HAProxy做更上层的业务路由”。这个底层逻辑通了,后面的配置才不会变成抄作业。
2. 把原理掰开揉碎:LVS工作模式与Keepalived的VRRP机制,理解之后配置才不会瞎抄
2.1 LVS DR模式为什么是生产首选
LVS有三种常见工作模式:NAT、DR、TUN。其中DR(Direct Routing,直接路由)是生产环境里用得最多、性能上限也最高的模式。
DR模式的处理过程可以这样理解:客户端把请求包发给VIP,LVS收到后不修改IP头,只根据调度算法选定一台后端RS,然后把二层MAC帧的目标地址改成那台RS的MAC地址,再把包从和RS同网段的物理网卡发出去。RS在自己的环回接口lo上绑定了VIP,收到包后发现目的IP就是本机VIP,于是接受并处理业务,回包时直接从RS自己的网卡发回给客户端,完全不经过LVS。
这个“回包不走LVS”的设计非常关键。
举例来说,一个视频点播或者大文件下载场景,请求可能只有几十个字节,响应却有几十兆甚至上百兆。如果走NAT模式,LVS既要承担入口流量又要承担出口流量,出口带宽会先被打满。而DR模式下LVS只需要处理一次小请求包,回包走RS的独立出口,整体吞吐量会高出一个数量级。
这也是为什么生产环境只要网络条件允许,大家都会优先选DR模式。它要求LVS和所有RS在同一个二层网络里,但如果你的服务都在同一个机房、同一个VPC内网,这根本不是问题。
DR模式配置时有几个点很容易错:
- 每台RS都要在lo接口上绑定VIP,而且不能对外宣告。
- 必须配置ARP抑制参数
arp_ignore=1、arp_announce=2,否则RS会响应VIP的ARP请求,跟LVS抢IP地址,流量直接乱掉。 - RS的默认网关不能指向LVS,应该走正常出口路由,不然回包路径会变得很别扭。
2.2 NAT模式和TUN模式:什么时候才需要放弃DR
NAT模式的LVS会在内核里做目的地址转换,客户端流量进来后,LVS把目的IP改成选定RS的真实IP,RS回包时再回到LVS,由LVS做一次反向源地址转换再发回客户端。这相当于流量进出都过一遍LVS,部署上最简单,RS不需要配置VIP,不需要抑制ARP,网络拓扑也可以跨网段。
它的代价我也要说清楚:LVS本身会成为整条链路的吞吐瓶颈,尤其是响应流量大时,出口带宽会变成一个很现实的上限。所以NAT模式更适用于中小流量、对部署简易度要求高于性能峰值的场景。如果你预估入口和出口加起来可能超过单机网卡处理能力,就不要用NAT。
TUN模式是通过IP-IP隧道把包封装后转发给RS,RS解包处理完业务后直接回包给客户端。它解决了DR模式要求二层互通的问题,RS可以分布在不同网段甚至不同机房,但隧道封装和解包有额外CPU开销,整体配置也更复杂。一般不是强跨机房需求,我不会主动推荐TUN。
另外,LVS的调度算法也要结合业务选:
rr:纯轮询,适合所有RS规格一样、请求处理时间差不多的场景;wrr:加权轮询,适合RS规格不一致,比如8C16G和16C32G混跑;wlc:加权最少连接,适合长连接业务,比如网关、IM;sh/source hash:源地址哈希,可以简单实现同一来源IP固定的会话保持;sed/nq这类特殊算法使用场景少,了解一下即可。
还要纠正一个很多人都会有的误解:LVS的调度算法只作用于新建连接。一旦某个TCP连接被转发给了某台RS,那这个连接后续所有包都会走同一条路径,LVS不会把一个已建立连接中途切到别的机器上。
2.3 Keepalived的VIP漂移到底做了什么
Keepalived的核心是VRRP协议。逻辑上多台节点组成一个虚拟路由器,其中只有一台是Master,其余是Backup。Master会周期性地发送VRRP通告报文,Backup接收后确认Master还活着。当Backup连续几个周期没有收到通告,就会认定Master挂了,随即把VIP配置到自己的网卡上,并发送免费ARP通知交换机更新MAC表。
默认配置下,如果advert_int是1秒,Backup大概要在3秒多的超时后才会接管VIP。这个切换时间不是秒级不可控,但也不会是毫秒级,业务上要有预期。
这里有几条细节如果没掌握,后面排查脑裂会非常痛苦:
- 同一个VRRP组里的
virtual_router_id必须保持一致,否则两个节点根本无法正常协商,VIP就会乱; - 最终谁能做Master取决于priority,不取决于state字段。就算你把节点A配成MASTER但priority是50,节点B配成BACKUP但priority是100,B依然会抢占;
- authentication的密码只用于VRRP报文的简单校验,不是安全机制;
- VRRP报文走的是组播地址224.0.0.18,底层IP协议号是112,容易被防火墙或交换机的组播过滤策略拦截。很多脑裂都是这个问题引起的。
Keepalived真正跟LVS联动的地方在virtual_server配置段。Keepalived在启动和运行时会调用ipvsadm命令,把健康检查通过的RS加入LVS调度表,把失败或超时的RS摘除。如果你只是让Keepalived做VIP漂移,不打算用LVS,就千万不要在配置文件里加virtual_server段,否则Keepalived会去操作ipvsadm,而系统里可能根本没加载ip_vs模块,服务自然起不来。
还有一个生产环境很容易被忽略的问题:Keepalived负责VIP漂移,但LVS连接表不会自动从旧Master同步到新Master。主备切换后,原来Master上建立的TCP长连接状态全部丢失,客户端必须重连。如果业务是短连接,影响不大;如果是WebSocket、数据库连接池这类长连接业务,就要在应用设计时允许自动重连,或者去研究ipvs connection sync相关的同步机制。
3. 生产架构选型:先别急着全套上,规模不一样用的方案差很多
3.1 中小规模最务实的组合:HAProxy + Keepalived
很多团队一上来就要复刻大厂的“LVS+Keepalived+HAProxy”三层架构,其实没必要。业务每天百万级访问量、峰值QPS一万左右时,两台HAProxy加一台VIP完全够用。
HAProxy的优势在这个量级非常明显:
- 用户态转发性能虽然不如LVS,但对万级QPS来说是绰绰有余;
- 配置灵活,按域名分流、按URL做ACL、Rewrite Host、会话保持都方便;
- 健康检查可以做HTTP层验证,而不是只探TCP端口;
- 自带统计页面和admin socket,排障时有直观数据。
具体部署很简单:两台服务器分别安装HAProxy和Keepalived,Keepalived提供一个VIP,HAProxy监听*:80或*:443,后端指向业务集群。Keepalived检测HAProxy进程和本地服务状态,主节点挂了自动漂移VIP到备份节点。整体链路短,出了故障用抓包或看日志都能快速定位。
这里也经常有人纠结“为什么不用Nginx做负载均衡”。如果你对静态缓存、请求改写、Web服务能力有需求,Nginx确实更适合。但如果核心诉求就是接流量、做转发、看统计、保持会话,HAProxy的负载均衡能力比Nginx更专。没有谁能取代谁,主要看团队更熟悉什么。
3.2 标准互联网业务:LVS + Keepalived + HAProxy 双层负载
当业务进入需要面对较大并发、长时间保持大量连接、或者响应包很大的阶段时,单层HAProxy会开始在连接数和CPU上显现压力。这时候经典的三件套架构就派上用场了。
整体链路是这样:
- 最前面是一对LVS节点,由Keepalived提供VIP漂移和健康检查,LVS用DR模式把流量转发给下一层;
- 中间是HAProxy集群,接收LVS转发过来的流量,按业务域名、URI、Header做七层分发;
- 最后面是真正的业务应用集群。
为什么要加中间这层?因为LVS只能做到四层转发,它看不懂域名,也看不懂URL路径。一台Linux服务器上可能同时挂着商城、用户中心、内容管理三个业务,如果只靠LVS,所有流量都会被扔到同一批后端,业务隔离和路由就无从谈起。HAProxy在这里的作用就是做“业务路由枢纽”,把VIP接收的流量分给不同的后端组。
这个架构看起来多了一层网络跳数,但实际带来的收益远大于损耗:
- 入口的高可用和四层转发由LVS+Keepalived承担,HAProxy不需要绑定VIP,也不担心ARP问题;
- HAProxy可以独立配置多组backend,故障隔离清晰;
- 后续扩容后端时,只需在HAProxy侧加server,不需要动LVS;
- 压测时哪个环节是瓶颈也一眼就能看出来。
3.3 决策对照:到底选哪种结构
| 业务规模 | 推荐架构 | 理由 |
|---|---|---|
| 日活几千、QPS几百 | HAProxy单节点+域名解析 | 简单够用,一个进程搞定 |
| 日活几万、QPS几千到一万 | 两台HAProxy + Keepalived | 保持高可用,配置灵活 |
| 日活几十万、QPS几万以上 | LVS+Keepalived+HAProxy | 内核态转发承担入口压力 |
| 跨机房、同一业务多地域部署 | DNS解析多活+各机房自治 | LVS跨地域意义不大,网络复杂度高 |
| 云上部署 | 云四层负载均衡+HAProxy/Nginx | 自建LVS在云内受ARP和组播限制较多 |
想强调一点:LVS不是技术KPI,没必要为了“架构好看”强行上。如果当前峰值连接数连几万都不到,加一层LVS只会增加两层故障点。等流量真正涨上来了,再平滑增加LVS层也不迟,这个演进方向是完全可控的。
4. 从零到一部署一套:LVS+Keepalived+HAProxy配置手记
4.1 环境规划和初始化准备
为了便于复现,我用一套简化的实验环境做演示:
- LVS主节点:lvs01,IP 10.0.0.10;
- LVS备节点:lvs02,IP 10.0.0.11;
- VIP地址:10.0.0.100;
- HAProxy节点1:10.0.0.20;
- HAProxy节点2:10.0.0.21;
- Web后端:web01 10.0.0.30、web02 10.0.0.31。
4台机器都部署在同一内网网段,满足LVS DR模式二层互通的硬性要求。如果是Debian/Ubuntu,用apt install keepalived ipvsadm haproxy -y安装;如果是CentOS/RHEL,用yum install keepalived ipvsadm haproxy -y。这些组件在主流发行版里都是成熟包,直接用包管理器安装是最稳妥的,没必要为了“版本新”去源码编译。
安装之后确认LVS内核模块可以正常加载:
modprobe ip_vs modprobe ip_vs_wrr modprobe ip_vs_sh lsmod | grep ip_vs如果重启后想自动加载,可以把模块名写入/etc/modules-load.d/lvs.conf。很多线上问题就是重启后ip_vs模块没有加载,Keepalived配置了virtual_server却无法操作ipvsadm,服务反复异常退出。
4.2 LVS节点配置:先用ipvsadm验证转发链路
LVS本身没有独立守护进程,配置全部通过ipvsadm命令实时维护。Keepalived会接管这个过程,但在正式接入前,我习惯先手动敲一遍命令验证网络层能通:
ipvsadm -A -t 10.0.0.100:80 -s wrr ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.20:80 -g -w 1 ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.21:80 -g -w 1 ipvsadm -ln-g表示DR模式,-w表示权重。手动加完以后,用ipvsadm -ln看一下,如果能看到两条real server记录,说明LVS的内核转发路径已经通了。顺手再确认下LVS节点开启了转发,有些内核参数还是要提前设置:
net.ipv4.ip_forward = 1虽然DR模式回包不经过LVS,这个参数影响不大,但统一配置无害。
4.3 Keepalived配置:主备节点差异只有三处
LVS节点上的Keepalived配置是所有组件里最复杂的,核心是把VIP漂移和LVS后端RS的增删绑定到一起。主节点配置示例:
global_defs { router_id lvs_master } vrrp_instance VI_LVS { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 10.0.0.100/24 dev eth0 label eth0:0 } } virtual_server 10.0.0.100 80 { delay_loop 5 lb_algo wrr lb_kind DR protocol TCP real_server 10.0.0.20 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 2 } } real_server 10.0.0.21 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 2 } } }备节点配置只要改三处:router_id lvs_backup、state BACKUP、priority 90。接口、VIP、virtual_router_id、real_server列表必须和主节点完全一致。如果两边的virtual_server段不一致,主备切换后LVS的调度对象会变得不同,流量分配立刻走样。
这个示例里还有一个容易被忽略的点:LVS后端RS指向的是两台HAProxy的真实IP,而不是HAProxy的VIP。HAProxy不需要再绑定单独的业务VIP,它只要监听*:80就能收到LVS转发过来的流量。这样设计的好处是LVS负责VIP高可用,HAProxy层不用重复维护一套VIP,减少了ARP和地址冲突问题。
4.4 HAProxy配置:绑定真实IP还是通配地址
HAProxy的配置相对容易理解。一个最小可用的HTTP负载均衡配置如下:
global maxconn 100000 nbthread 4 log /dev/log local0 info stats socket /run/haproxy/admin.sock mode 660 level admin defaults log global mode http timeout connect 5s timeout client 30s timeout server 30s timeout http-keep-alive 5s frontend http_in bind *:80 default_backend web_cluster backend web_cluster balance roundrobin option httpchk GET /healthz HTTP/1.1\r\nHost:\ healthz.example.com server web01 10.0.0.30:80 check inter 2s rise 2 fall 3 maxconn 3000 server web02 10.0.0.31:80 check inter 2s rise 2 fall 3 maxconn 3000有两个细节值得展开说:
bind *:80直接用通配地址。如果只绑定VIP地址,LVS转发过来的目的IP是HAProxy的真实IP,流量反而进不来。option httpchk指定的健康检查URI要做得很轻量,最好是固定的/healthz页。不要拿一个返回超大JSON的业务页面当健康检查,否则每次检查都会额外消耗后端资源,高峰期还可能因为健康检查超时造成RS频繁上下线。
配置写完后,先用haproxy -c -f /etc/haproxy/haproxy.cfg验证语法,再systemctl enable --now haproxy启动。过程中如果出现权限或资源类报错,大概率是systemd的LimitNOFILE没调,这个在下一章避坑清单里展开。
4.5 验证链路和主备切换演练
部署完成后的验证,我建议至少做四步:
- 在LVS主节点执行
ipvsadm -ln,确认两台real_server状态正常; - 从客户端请求VIP,
curl -I http://10.0.0.100/,能看到正常HTTP响应;重复请求几次,再通过后端日志看请求是否在web01和web02之间轮询; - 人为停掉一台HAProxy,观察Keepalived在5到10秒内把对应real_server摘除,
ipvsadm -ln里应该少一条记录; - 停掉LVS主节点的Keepalived服务,VIP发生漂移,客户端继续请求VIP,只会出现短暂超时或者业务重试,不能长期挂掉。
这种演练一定要在业务低峰期做。不少企业配置好了Keepalived之后两年没切过一次,真到故障时才发现notify脚本路径写错了、交换机没刷新ARP、防火墙拦截了VRRP包,各种问题集中爆发。主备切换演练应该纳入常规运维计划,每次架构变更后至少重跑一次。
5. 生产避坑清单:这些问题我几乎都在线上遇到过
5.1 ARP抑制:DR模式里最隐蔽的流量黑洞
LVS DR模式最经典的坑就是RS没有做ARP抑制。表现出来是VIP能通,但响应忽快忽慢,或者在客户端抓包能看到同一个VIP在短时间内收到了不同MAC地址的ARP应答。
原因是RS的lo接口上绑定了VIP,但没有告诉内核“这个VIP不参与ARP应答”。当客户端或交换机发起ARP请求问“谁是10.0.0.100”时,LVS和RS都可能应答,交换机的MAC表就会在多个MAC之间反复横跳,流量也跟着乱走。
解决办法是在每台RS上强制配置ARP忽略和通告策略:
net.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写入/etc/sysctl.d/lvs_rs.conf后执行sysctl -p。如果上线前没配,启动Keepalived后VIP一出,整个交换机的ARP表就乱了,排障会非常痛苦。
5.2 LVS连接表溢出:高并发下最冤枉的丢包
LVS的连接表是一个哈希结构,由ip_vs_conn_tab_bits参数控制大小,这个值决定了哈希桶的数量。很多发行版默认值偏小,高并发长连接场景下哈希冲突会迅速增加,表现为LVS转发随机丢包、QPS上不去,但CPU和内存看起来都正常。
监控时如果发现ipvsadm -ln --stats里的并发连接数接近预估上限,优先确认一下ip_vs_conn_tab_bits的当前值:
cat /sys/module/ip_vs/parameters/conn_tab_bits如果这里显示的是12或16这种偏小的数,建议把LVS节点在维护窗口内重新初始化,并提前配置更大的值,比如echo 20 > /sys/module/ip_vs/parameters/conn_tab_bits。要注意的是,这个操作在模块已加载的节点上并不能随时写入,最稳妥的方式是在节点上线前或重启节点时通过modprobe配置提前固定。所以在初始化LVS节点时,这是一项必须做的前置动作,而不是等出了故障再去改。
5.3 Keepalived脑裂的隐蔽诱因
脑裂指的是主备节点同时认为自己是Master,同时持有VIP。一旦发生,客户端访问VIP时交换机可能把流量分给两台机器,业务出现随机超时,且极难排查。
常见诱因有这几类:
- 主备之间的网络通信断了,VRRP组播报文收不到,Backup超时后主动接管VIP;
- 防火墙把IP协议号112的VRRP包拦截了;
- 交换机开启IGMP snooping后对组播地址的管理策略有问题,VRRP组播没被正常转发;
- 节点假死,比如机器负载极高、keepalived进程还在,但已经无法处理报文。
防御脑裂比较有效的方式:
- 主备之间加一条独立心跳链路,比如单独的物理网卡直连,或者至少让VRRP通信不依赖业务主链路;
- 在vrrp_instance里写
track_script,用脚本检测关键服务(比如HAProxy进程、本地80端口),脚本失败时主动降低优先级或退出Master状态; - 配置notify脚本,状态切换立刻告警到监控系统;
- 如果实在不放心,可以在notify_master脚本里检查对端是否还活着,发现双主就手动释放本机VIP。
脑裂无法靠Keepalived单点解决,它需要的是网络层、应用层和运维规范三方面配合。
5.4 HAProxy配置里的三处性能坑
第一处是maxconn和文件描述符不匹配。HAProxy每个连接至少需要两个fd,一个用于客户端侧,一个用于后端服务器侧。如果你把maxconn设置为100000,那么ulimit -n至少要200000以上,否则高并发下会频繁报Too many open files。在systemd环境里,还需要额外设置:
[Service] LimitNOFILE=655350 LimitNPROC=65535修改后执行systemctl daemon-reload并重启HAProxy。很多人只改了系统ulimit,忘了systemd还有自己的限制,结果问题依旧。
第二处是健康检查频率太高或检查路径太重。把inter设成300毫秒看起来能更快发现故障,但实际上后端服务一个抖动,健康检查就开始连续失败,RS被摘掉后又恢复,恢复后又频繁加入,直接带来流量雪崩。生产环境我建议至少inter 2s,并配合rise 2、fall 3这样的阈值,给后端留出足够的恢复窗口。
第三处是超时参数设置不符合业务特征。timeout client是客户端侧空闲超时,timeout server是后端侧空闲超时,如果你在做WebSocket、长轮询、数据库中间件代理,这些值就不能沿用默认的十几秒。需要结合业务最长处理时长去压测,然后把超时调到足够宽。很多莫名其妙的连接断开,最后查到都是这里。
5.5 上线、扩容、切换的时间窗管理
运维层面最容易出问题的不是配置本身,而是操作顺序。以下几个顺序性问题我踩过不止一次:
- 上线LVS前先要把所有RS的sysctl参数和lo:0 VIP配置好,再启动Keepalived。顺序反了,RS一开始就会对外ARP应答,LVS还没就绪,VIP就已经被“污染”了。
- 扩容后端时,先在Keepalived的
real_server里把weight改成0,等存量连接自然消尽,再真正停止服务维护。直接kill进程会让所有活跃连接瞬间断开,长连接业务基本全军覆没。 - 修改VIP或强制刷新交换机MAC表时,在持有VIP的节点上执行一次免费ARP广播:
arping -I eth0 -c 3 -U 10.0.0.100- 每次变更前校验配置文件:
keepalived -t -f /etc/keepalived/keepalived.conf haproxy -c -f /etc/haproxy/haproxy.cfg配置文件要纳入版本管理,主备节点上线前对比一下md5,能杜绝一大批“只在一边改了规则,另外一边不知道”的低级故障。
6. 容量评估与监控:峰值到来之前,这些数字必须心里有数
6.1 该盯的核心指标是什么
LVS、Keepalived、HAProxy各自的监控重点完全不同。
LVS侧最重要是连接数、转发速率和软中断占用。查询命令:
ipvsadm -ln --stats ipvsadm -ln --rate--stats看累计连接数、活跃连接数、转发字节数;--rate看实时速率。同时用top盯一下CPU的si占用,如果si很高,说明网卡包量已经让内核软中断处理开始吃力了。
Keepalived侧重点看VRRP状态和切换次数。最简单的方法是查看ip addr里是否存在VIP,正常只有一个节点持有。再配合notify脚本记录每次Master切换,监控上能看到切换频率。如果一周内多次切换,背后大概率是网络抖动或配置问题。
HAProxy侧主要看当前连接数、会话速率、队列、健康检查失败次数。通过admin socket可以直接查看:
echo "show stat" | socat stdio /run/haproxy/admin.sock有Prometheus环境的话,可以用haproxy_exporter直接拉取指标。一个可落地的监控组合是:node_exporter带ipvs collector采集LVS指标,keepalived_exporter采集VRRP状态,haproxy_exporter采集HAProxy指标,统一进Grafana。
6.2 压测时如何评估结果和瓶颈
压测工作最容易被忽视的是压测机本身先成为瓶颈。默认情况下客户端的可用源端口可能只有几万个,连接一多就会出现Cannot assign requested address。压测前先把net.ipv4.ip_local_port_range调大,或者压测机配置多个IP,否则压测数据毫无参考价值。
压测时可以分三轮做:
- 第一轮HTTP短连接,聚焦QPS和CPU表现。正常情况下LVS的CPU占用应该远低于HAProxy,因为内核态转发效率高;
- 第二轮定长连接,聚焦并发数和内存。HAProxy每个连接要维护两条socket和对应的内存缓冲区,连接数上了几十万后,内存增长非常明显;
- 第三轮混合压测,按真实业务比例混合短连接和长连接,观察后端RS的错误率和延迟分布。
记录下来的关键数字建议是:LVS在什么QPS下软中断开始飙高、HAProxy在什么连接数下内存吃紧、后端RS在什么延迟开始抬头。然后以这些数据为基准,保留30%到50%的水位冗余,设定监控阈值。
6.3 关于“高可用”的最后一层认知
高可用从来不是某个软件单点保证的,它是转发、漂移、健康检查、监控、规范、演练共同组合出来的结果。LVS把转发做快,Keepalived把VIP稳住,HAProxy把流量做细,监控把故障提前暴露,演练把操作动作练熟。缺任何一环,架构都可能在某次大流量或者故障中出问题。
我在实际维护中体会最深的一件事是:简单比炫技重要。流量没起来之前,HAProxy加Keepalived就是最高效的方案;流量起来了,再平滑增加LVS层完全来得及。真没有必要为了显得架构高级,一开始就堆三件套,那样只会增加出故障时的排查半径。
最后分享一个小技巧:每次变更前把ipvsadm -ln的输出和每台RS的健康检查结果截图留档,变更后马上做一次比对。如果流量分配或者RS状态和变更前不一致,能第一时间判断是配置原因还是故障原因。这个习惯看起来不起眼,但线上出问题的时候,它真的能帮你节省几十分钟的排查时间。