☰
高可用架构实战:Keepalived、LVS与HAproxy选型与配置
2026/10/13 5:37:36 网站建设 项目流程

1. 高可用架构的三种典型落地路径拆解

线上业务跑得越久,越能体会到一个朴素的道理:单点就是定时炸弹。不管是电商大促、内部OA、还是API网关,只要某台机器一挂,业务方电话立刻打过来。高可用这个话题说了很多年,但真正落地的时候,方案选型往往决定了后面运维的幸福感。今天想聊的这套组合——Keepalived热备、Keepalived+LVS、HAproxy——基本覆盖了中小规模到中大规模场景下最常见的高可用需求。它们不是互斥的,很多时候是搭配使用的,但每一种都有自己最擅长的位置。

先把这三个东西的定位说清楚,不然后面容易混。Keepalived本质上是一个VRRP协议的实现,用来做IP漂移和状态检测,它解决的是"谁来接管"的问题;LVS是内核层面的四层负载均衡,性能极高,解决的是"流量怎么分发"的问题;HAproxy是用户态的四层/七层负载均衡,功能丰富,解决的是"流量怎么智能分发"的问题。三者组合起来,就形成了从接入层到应用层的完整高可用链路。

这篇文章适合谁看?如果你正在搭建一套对外服务,或者内部系统要求7x24不能断,又或者你已经在用Nginx做负载但发现健康检查不够灵活,那这篇内容应该能给你一些直接能抄的配置和踩坑经验。我会从架构思路、核心原理、实操配置、故障排查四个维度展开,每个方案都给出可复现的步骤和参数计算过程。不堆概念,只讲能落地的东西。

2. Keepalived热备:最朴素也最可靠的双机方案

2.1 为什么选Keepalived而不是自己写脚本

很多人第一反应是:我写个crontab定时ping一下,不通就改IP不就行了?理论上可行,但实际生产环境里这么干的人,最后基本都换成了Keepalived。原因有几个:第一,自己写的脚本很难处理脑裂场景,两台机器互相觉得对方挂了,同时抢IP,结果IP冲突导致服务彻底不可用;第二,VRRP协议本身有优先级、抢占延迟、认证机制,这些都是经过大量验证的;第三,Keepalived还能顺带做服务健康检查,不只是检查主机存活,还能检查Nginx、MySQL这些进程是否正常。

Keepalived的核心工作模型是这样的:两台机器组成一个VRRP组,一个MASTER一个BACKUP,共享一个虚拟IP(VIP)。MASTER定期发送VRRP通告包,BACKUP收不到就认为MASTER挂了,自己升为MASTER并接管VIP。整个过程通常在1到3秒内完成,对上层业务基本透明。

2.2 双机热备的完整配置实操

假设我们有两台服务器,IP分别是192.168.10.11和192.168.10.12,VIP规划为192.168.10.100。操作系统以常见的Linux发行版为例,安装Keepalived直接包管理器搞定:

# Debian/Ubuntu系 apt install keepalived -y # RHEL/CentOS系 yum install keepalived -y

MASTER节点的配置文件/etc/keepalived/keepalived.conf:

global_defs { router_id node_master script_user root enable_script_security } vrrp_script chk_nginx { script "/usr/bin/killall -0 nginx" interval 2 weight -20 fall 2 rise 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass MySecurePass123 } virtual_ipaddress { 192.168.10.100/24 dev eth0 } track_script { chk_nginx } }

BACKUP节点只需要改三处:router_id改成node_backup,state改成BACKUP,priority改成90。其他保持一致。

这里有几个参数值得展开说。virtual_router_id在同一个网段内必须唯一,如果你们内网有多组Keepalived,这个值冲突了会出现莫名其妙的问题,我见过有人图省事全用51,结果两组集群互相干扰。advert_int是通告间隔,默认1秒,意味着故障切换最快1秒左右,如果业务对切换时间更敏感可以调到0.5,但会增加网络开销。weight -20配合priority 100,意思是当Nginx检查失败时,优先级降到80,低于BACKUP的90,从而触发切换。

2.3 健康检查脚本的坑与技巧

vrrp_script里的检查脚本是整个方案里最容易出问题的地方。上面用的killall -0 nginx只是检查进程是否存在,但进程在不代表服务正常。更靠谱的做法是检查端口或者发一个HTTP请求:

#!/bin/bash # /etc/keepalived/check_nginx.sh count=$(ss -lntp | grep -c ':80 ') if [ "$count" -eq 0 ]; then exit 1 fi exit 0

注意脚本必须有可执行权限,而且script_user要配置正确,否则Keepalived以非root身份跑脚本时可能权限不足。另外fall和rise这两个参数很关键,fall 2表示连续失败2次才认为服务挂了,rise 2表示连续成功2次才恢复。设置太小容易误判,设置太大切换又慢,一般2到3是比较平衡的值。

实操心得:健康检查脚本里千万不要做耗时操作,比如curl一个慢接口。Keepalived的脚本执行是阻塞的,脚本卡住会导致整个检查机制失效。如果确实需要检查HTTP接口,务必加上--max-time 2这类超时参数。

3. Keepalived+LVS:四层负载均衡的高性能组合

3.1 LVS的三种转发模式怎么选

LVS有三种工作模式:NAT、DR、TUN。NAT模式配置简单但性能瓶颈在调度器,因为请求和响应都要经过它;TUN模式支持跨机房但需要隧道支持,配置复杂;DR模式是生产环境用得最多的,调度器只改MAC地址,响应直接由后端服务器返回给客户端,性能几乎线性扩展。

DR模式有个硬性要求:调度器和后端Real Server必须在同一个二层网络里,因为要改MAC。另外Real Server上需要配置VIP到lo接口,并且要抑制ARP响应,否则VIP会冲突。这两点是新手最容易翻车的地方。

3.2 DR模式完整搭建流程

环境规划:调度器两台做Keepalived主备(192.168.10.11/12),VIP为192.168.10.100,后端两台Real Server为192.168.10.21/22。

调度器上安装ipvsadm和keepalived:

yum install ipvsadm keepalived -y

Keepalived配置在双机热备基础上增加virtual_server段:

virtual_server 192.168.10.100 80 { delay_loop 6 lb_algo wrr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.10.21 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.10.22 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }

lb_algo wrr是加权轮询,如果后端机器配置不同可以调整weight。persistence_timeout 50表示50秒内同一客户端请求打到同一台后端,对有session的业务很重要,但如果是无状态服务建议设为0,让负载更均匀。

Real Server上需要执行以下配置:

# 配置VIP到lo接口 ip addr add 192.168.10.100/32 dev lo # 抑制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

这四个ARP参数的含义要理解清楚:arp_ignore=1表示只回答目标IP是本机接口IP的ARP请求,arp_announce=2表示总是使用最佳本地地址发送ARP。不配置这两个,Real Server会响应VIP的ARP请求,导致客户端直接连到Real Server,绕过调度器。

3.3 调度算法与参数调优

LVS支持的调度算法有十几种,常用的就几种:

算法适用场景特点
rr后端性能一致简单轮询
wrr后端性能有差异按权重分配
lc长连接场景连接数少的优先
wlc通用场景加权最小连接,默认推荐
sh需要会话保持源地址哈希

生产环境我一般推荐wlc,它综合考虑了连接数和权重,比单纯轮询更智能。如果业务有状态且不想用persistence_timeout,可以用sh做源地址哈希,但缺点是负载可能不均。

注意事项:DR模式下Real Server的网关不需要指向调度器,它直接用自己的默认网关返回响应。如果Real Server和客户端不在同一网段,要确保路由正确,否则会出现"请求通了但响应回不去"的经典问题。

4. HAproxy:七层负载均衡的灵活之选

4.1 什么时候该用HAproxy而不是LVS

LVS性能确实强,但它是四层的,只能看IP和端口,没法根据URL、Header、Cookie做转发决策。如果你的业务需要按域名分流、按路径转发、做SSL终止、或者需要更精细的健康检查,那HAproxy就是更合适的选择。HAproxy的性能虽然不如LVS内核级转发,但单机跑几万并发连接毫无压力,对绝大多数业务来说完全够用。

HAproxy的另一个优势是配置直观,日志详细,出问题好排查。LVS出问题的时候你只能看ipvsadm的连接数,HAproxy可以直接看日志知道哪个后端挂了、为什么挂。

4.2 HAproxy核心配置详解

安装同样简单:

yum install haproxy -y

一个典型的生产配置:

global log 127.0.0.1 local0 info maxconn 65535 daemon nbproc 4 cpu-map 1 0 cpu-map 2 1 cpu-map 3 2 cpu-map 4 3 defaults log global mode http option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 retries 3 timeout connect 5s timeout client 30s timeout server 30s timeout check 3s frontend web_front bind *:80 bind *:443 ssl crt /etc/haproxy/certs/site.pem acl is_api path_beg /api acl is_static path_beg /static use_backend api_servers if is_api use_backend static_servers if is_static default_backend web_servers backend web_servers balance roundrobin option httpchk GET /health http-check expect status 200 server web1 192.168.10.31:8080 check inter 2s fall 3 rise 2 server web2 192.168.10.32:8080 check inter 2s fall 3 rise 2 backend api_servers balance leastconn option httpchk GET /api/health server api1 192.168.10.41:9090 check inter 2s fall 3 rise 2 server api2 192.168.10.42:9090 check inter 2s fall 3 rise 2 backend static_servers balance source server static1 192.168.10.51:80 check server static2 192.168.10.52:80 check listen stats bind *:8404 stats enable stats uri /haproxy-status stats auth admin:StrongPass456 stats refresh 10s

nbproc 4开启4个进程,配合cpu-map绑定到不同CPU核心,能充分利用多核性能。但要注意,多进程模式下一些统计信息不共享,而且HAproxy 2.0以后更推荐用多线程模式(nbthread)替代多进程。

option httpchk GET /health是七层健康检查,比四层的TCP检查更准确。http-check expect status 200要求返回200才算健康,这样后端应用即使端口在监听但逻辑异常也能被摘除。

4.3 HAproxy与Keepalived的整合

HAproxy本身不提供IP漂移能力,所以生产环境通常是Keepalived+HAproxy的组合。配置方式和双机热备一样,只是健康检查脚本改成检查HAproxy进程:

vrrp_script chk_haproxy { script "/usr/bin/killall -0 haproxy" interval 2 weight -20 fall 2 rise 2 }

这样两台HAproxy做主备,VIP在谁身上谁对外服务。如果想做双活,可以配合DNS轮询或者上层再加一层LVS,但架构复杂度会上升不少,中小规模业务用主备就够了。

5. 三种方案的对比与选型决策

5.1 性能、功能、复杂度三维对比

维度Keepalived热备Keepalived+LVSHAproxy
工作层级无(只做IP漂移)四层四层/七层
吞吐性能取决于后端极高,十万级并发高,万级并发
功能丰富度低中高
配置复杂度低中高中
健康检查脚本自定义TCP/HTTPTCP/HTTP/自定义
SSL终止不支持不支持支持
会话保持不涉及persistencecookie/source
适用规模双机中大型中小型

选型的核心逻辑其实就一句话:先看规模,再看功能需求。如果后端就两台机器,业务简单,Keepalived热备足够了;如果后端几十台,追求极致性能,上LVS;如果需要按URL分流、SSL卸载、精细健康检查,HAproxy更合适。实际生产中,LVS+HAproxy的分层架构也很常见:LVS做四层入口,HAproxy做七层分发,Keepalived保证每一层都不单点。

5.2 分层组合架构实战

一个典型的中大型架构是这样的:最外层两台LVS+Keepalived做四层入口,VIP对外;LVS后面挂多台HAproxy做七层分发;HAproxy后面是真正的应用服务器。这样LVS扛住流量峰值,HAproxy做灵活路由,每一层都无单点。

这种架构的配置要点是:LVS的Real Server变成HAproxy的IP,HAproxy的backend指向应用服务器。健康检查要逐层配置,LVS检查HAproxy端口,HAproxy检查应用健康接口。任何一层出问题都能自动摘除,不会影响整体服务。

实操心得:分层架构虽然强大,但排查问题的时候链路变长了。建议每一层都开启详细日志,并且给请求加上统一的trace id,否则一个请求出问题你要从LVS查到HAproxy再查到应用,没有trace id会非常痛苦。

6. 常见故障与排查技巧实录

6.1 脑裂问题的识别与预防

脑裂是高可用架构里最危险的问题。两台机器都认为自己是MASTER,同时持有VIP,导致IP冲突、连接混乱。识别方法很简单:在两端同时执行ip addr show,如果都看到VIP,那就是脑裂了。

预防脑裂有几个手段:第一,确保VRRP通告链路可靠,不要用业务网卡做心跳;第二,配置nopreempt避免抢占导致频繁切换;第三,可以加一个第三方仲裁,比如用脚本检测到双MASTER时强制降级一台。Keepalived本身没有内置仲裁机制,这点要有清醒认识。

# 检测脑裂的简单脚本 vip="192.168.10.100" if ip addr show | grep -q "$vip"; then # 本机持有VIP,尝试ping另一台的物理IP if ping -c 2 -W 1 192.168.10.12 > /dev/null 2>&1; then # 对端也活着,可能脑裂,记录日志 logger "Possible split-brain detected" fi fi

6.2 常见问题速查表

现象可能原因排查方向
VIP不漂移VRRP通告被防火墙拦截检查iptables是否放行VRRP协议
切换后服务不可用后端服务未随VIP启动检查notify脚本
LVS后端全部不可用Real Server ARP未抑制检查arp_ignore/arp_announce
HAproxy健康检查误判检查间隔太短或超时太短调整inter/fall/rise
连接不均匀调度算法或persistence配置检查lb_algo和timeout
SSL握手失败证书链不完整检查pem文件是否包含中间证书
高并发下丢包连接数超限检查maxconn和内核参数

6.3 内核参数调优清单

高并发场景下,默认内核参数往往不够用。以下参数建议在调度器和HAproxy上都配置:

# /etc/sysctl.conf net.ipv4.ip_forward = 1 net.ipv4.ip_nonlocal_bind = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_max_syn_backlog = 8192 net.core.somaxconn = 65535 net.core.netdev_max_backlog = 65535 net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.tcp_syncookies = 1

ip_nonlocal_bind这个参数特别重要,它允许进程绑定非本机IP,Keepalived和HAproxy在VIP漂移后需要这个才能正常绑定。不配置的话,VIP切过来了但服务起不来,非常隐蔽。

注意事项:tcp_tw_reuse和tcp_tw_recycle经常被一起提,但tcp_tw_recycle在NAT环境下会导致连接异常,新版本内核已经移除,不要再去开它。

7. 生产环境部署的几点个人体会

踩过几次坑之后,我对这套组合有几个比较深的体会。第一,配置一定要版本化管理,Keepalived和HAproxy的配置文件改动频繁,没有版本控制的话,出问题回滚都找不到之前的版本。第二,健康检查脚本要单独测试,不要直接上生产,我见过脚本里写错路径导致检查永远失败,结果VIP一直在漂移。第三,监控要覆盖每一层,不只是看VIP在谁身上,还要看后端Real Server的健康状态、连接数分布、响应时间,任何一个指标异常都可能是故障前兆。

另外关于切换时间,很多人追求越快越好,但实际上1到3秒的切换对大多数业务是可以接受的。如果强行把advert_int调到0.1秒,网络抖动就可能导致误切换,反而更不稳定。稳定性永远优先于极致的切换速度。

最后说一个容易被忽略的点:测试故障切换。不要等真出故障了才发现切换不工作。定期手动触发切换,比如停掉MASTER的Keepalived,观察VIP是否正常漂移、服务是否自动恢复。这个演练每个月做一次,比任何文档都管用。我个人的习惯是每次变更配置后都做一次切换测试,确认无误才算变更完成。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询