负载均衡与高可用:LVS、HAProxy、Keepalived 实战

负载均衡与高可用:LVS、HAProxy、Keepalived 实战

运维学习路线系列 · 阶段三 中间件栈 · 第 5 篇

适用环境:Ubuntu 24.04 LTS,示例:192.168.1.10/11(LVS+Keepalived 双机)、.12/.13(后端 RS)

阅读前提:《S3-03 Nginx》《S2-03 防火墙》

前言:单点 = 最大的故障源

《S3-03》的架构:Nginx 挂在 192.168.1.10。那么问题来了------.10 这台机器重启的时候,全站下线。负载均衡器本身成了单点,这是最讽刺也最常见的架构缺陷。

解法是两台机器 + 一个"会漂移的 VIP":

复制代码
            客户端访问 192.168.1.100(VIP)
                  │
      ┌───────────┴───────────┐
   .10 主 LB  ◄──心跳──►  .11 备 LB     Keepalived:主活着备睡觉,主挂了备抢 VIP
      └───────┬───────┬────────┘
             .12     .13  (后端真实服务器)

这篇讲清三件事:四层与七层负载怎么选 、LVS 三种模式的转发原理 、Keepalived 怎么让 VIP 漂移且不脑裂。MySQL 主从的 MHA、Redis 哨兵,本质都是这套"主备 + 心跳 + 漂移"思想的变体------学会一次,到处复用。


一、四层 vs 七层:先分清职责

四层(LVS/HAProxy tcp) 七层(Nginx/HAProxy http)
工作层 TCP/UDP 报文转发 解析 HTTP,按 URL/Host 分发
性能 极高(内核级/连接转发) 高(足够绝大多数场景)
能做 IP:端口 级分发、改包 按路径分发、改头、限流、缓存、压缩
典型位置 最前层(扛入口流量) 四层后面(应用层分发)

生产常见组合 :LVS(四层) → Nginx(七层) → 应用。小规模直接 Nginx 扛一切 + Keepalived 保 Nginx 高可用,也是完全合格的方案。

二、LVS:内核级四层转发

2.1 三种模式

模式 转发方式 性能 RS 配置复杂度 特点
NAT 改目标 IP(进)+ 源 IP(回) 中 低(只需网关指向 LB) 回程流量也过 LB,LB 易成瓶颈
DR(直连路由) 只改 MAC,RS 直接回客户端 最高 高(RS 需绑 VIP + 抑 ARP) 回程不过 LB,扛量首选
TUN IP 隧道封装 高 中 跨机房场景

2.2 DR 模式核心操作(理解"回程不过 LB")

bash 复制代码
# 在 LVS 调度器 .10 上(ipvsadm 管理规则;Keepalived 也能管,见下节)
sudo apt install ipvsadm -y
sudo ipvsadm -A -t 192.168.1.100:80 -s wlc          # 建虚拟服务 VIP:80,算法 wlc
sudo ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.12:80 -g   # -g = DR 模式挂 RS
sudo ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.13:80 -g
sudo ipvsadm -Ln                                     # 查看规则与连接统计
bash 复制代码
# 每个 RS(.12/.13)上:环回口绑 VIP + 抑制 ARP(DR 模式的"门票")
sudo ip addr add 192.168.1.100/32 dev lo
echo 1 | sudo tee /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 | sudo tee /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 | sudo tee /proc/sys/net/ipv4/conf/all/arp_announce

💡 为什么 RS 要绑 VIP 又抑制 ARP?请求经 LVS 改 MAC 后直达 RS 的物理网卡,目标 IP 还是 VIP,RS 必须在本机认领这个 IP(lo 上绑定)才能收包;但不抑制 ARP,网关会误以为 VIP 在 RS 上------流量绕过 LVS,全乱。面试高频:DR 模式 RS 为什么要配 arp_ignore,答案就是这句。

调度算法速记:rr 轮询 / wrr 加权轮询 / lc 最少连接(长短请求混合推荐) / wlc 加权最少连接 / sh 源地址哈希。

三、Keepalived:VIP 漂移与脑裂防护

3.1 VRRP 原理一句话

Keepalived 实现 VRRP 协议 :主备双方在同一个 VRID 里广播心跳(默认 1s 一告,3s 丢失判定死),VIP 只在主上;主失联,备升主、接管 VIP------客户端只认识 VIP,无感切换。

3.2 主备配置(LVS + Keepalived 合体实战)

bash 复制代码
# .10 与 .11 都安装
sudo apt install keepalived -y
bash 复制代码
# /etc/keepalived/keepalived.conf ------ 主(.10)
global_defs {
   router_id lb1
}
vrrp_instance VI_1 {
    state MASTER              # 角色声明(真正的主由 priority 选出)
    interface eth0
    virtual_router_id 51      # 主备必须一致
    priority 100              # 优先级:谁大选谁
    advert_int 1              # 心跳间隔 1s
    authentication {
        auth_type PASS
        auth_pass MySec2026   # 主备一致(VRRP 明文,仅作简单防扰)
    }
    virtual_ipaddress {
        192.168.1.100/24 dev eth0    # VIP
    }
}
# 主上顺带让 Keepalived 管理 LVS 规则(替代手敲 ipvsadm):
virtual_server 192.168.1.100 80 {
    delay_loop 3
    lb_algo wlc
    lb_kind DR
    protocol TCP
    real_server 192.168.1.12 80 {
        weight 1
        TCP_CHECK { connect_timeout 3 }   # 健康检查:端口不通就摘除 RS
    }
    real_server 192.168.1.13 80 {
        weight 1
        TCP_CHECK { connect_timeout 3 }
    }
}

备机(.11)只改三处:state BACKUP、router_id lb2、priority 90,其余一致。

bash 复制代码
sudo systemctl enable --now keepalived
ip addr show eth0 | grep 192.168.1.100   # 主上能看到 VIP;备上没有

3.3 验证切换与脑裂防护

bash 复制代码
# ① 模拟主挂:.10 上 systemctl stop keepalived
#    3 秒内在 .11 上:ip addr 应出现 VIP;客户端 curl 192.168.1.100 全程几乎无感
# ② 主恢复:默认重新抢占(nopreempt 可改为"备继续当主",避免无谓抖动)

# ③ 脑裂(split-brain):主备互相看不见(如防火墙拦了 VRRP)→ 两边都认为自己是主
#    后果:两个 VIP 同 IP 冲突,流量随机黑洞。防护三件套:
#    a) 防火墙放行 VRRP 协议(protocol 112):
sudo iptables -A INPUT -p 112 -i eth0 -s 192.168.1.11 -j ACCEPT
#    b) 多路心跳:VRRP 之外再配 track_script(如 ping 网关),两条件都不满足才降级
#    c) 监控告警:阶段四给"VIP 不在预期机器"做巡检(两台都查到 VIP = 立即告警)

🚨 VRRP 被防火墙拦掉是脑裂第一元凶 ------Keepalived 排错第一反应:tcpdump -i eth0 vrrp 看心跳到没到对端。

3.4 应用层健康检查(不只看端口通)

端口通 ≠ 服务正常(进程活着但接口全超时的"假活")。生产做法:track_script + HTTP 检查:

复制代码
vrrp_script chk_nginx {
    script "/usr/bin/curl -sf http://127.0.0.1/health -o /dev/null"
    interval 2
    fall 2       # 连续 2 次失败才算死
    rise 2
}
vrrp_instance VI_1 {
    state MASTER
    track_script { chk_nginx }    # Nginx 假活 → 主动让出 VIP(配合 nopreempt 效果更稳)
    ...
}

四、HAProxy 顺带认识(选型参考)

HAProxy 一个组件同时提供四层+七层,配置比"LVS+Nginx"组合更简洁,中小团队入口层常见选择:

复制代码
# /etc/haproxy/haproxy.cfg 核心段(tcp 四层示例)
frontend ft_web
    bind *:80
    default_backend bk_web
backend bk_web
    balance leastconn
    server web1 192.168.1.12:80 check inter 2s fall 3
    server web2 192.168.1.13:80 check inter 2s fall 3

选型速记:小规模(<万级 QPS)= Nginx/HAProxy 直接上;超大规模入口 = LVS/云 SLB 扛四层 + Nginx 分七层;云上优先托管 SLB(免运维,天生多可用区)。

五、综合实战 + 验收

拓扑:.10/.11 双 Keepalived(DR 模式 LVS)+ .12/.13 后端 http.server。

bash 复制代码
# ① 按上文配好主备 keepalived + RS 的 lo/ARP 配置
# ② 压测确认分发:curl http://192.168.1.100 循环,应看到两台 RS 内容交替
# ③ 停 .10 keepalived → 计时 VIP 切换耗时(预期 <5s)
# ④ 停 .12 的 http.server → ipvsadm -Ln 确认 .12 被自动摘除,无 502
# ⑤ tcpdump -i eth0 vrrp 观察心跳;人为 iptables DROP VRRP 观察备机升主(脑裂演练,完事删规则!)

验收标准:① 独立搭出主备 + VIP + 健康检查全套;② 能解释 DR 模式回程路径与 RS 的 ARP 抑制原因;③ 能说出脑裂的成因与至少两种防护。


六、🚨 生产环境避坑清单

# 坑 后果 正确姿势
1 VRRP 被防火墙/安全组拦截 脑裂、双 VIP 放行 protocol 112;tcpdump vrrp 排错
2 DR 模式 RS 忘配 ARP 抑制 流量绕过 LB 乱飞 四个 arp 参数写进开机脚本(rc.local/网络钩子)
3 健康检查只查端口 "假活"服务继续收流量 HTTP GET /health 检查 + fall 阈值
4 主备配置不一致(VRID/密码/VIP) 备机根本不认主 keepalived.conf diff 校对;起不来看 journalctl -u keepalived
5 切换不演练 真故障时才发现切换是坏的 季度演练:拔主、看秒级接管
6 VIP 与真实 IP 同段没确认交换机 ARP 宣告不通,VIP 不生效 VIP 选同网段;云上用"浮动 IP"产品替代
7 挂了 RS 的 LVS 规则手工维护 摘除不及时 → 502 规则全部交给 Keepalived 管,别手敲 ipvsadm

七、一句话总结

高可用的公式 = 主备 + 心跳 + 可漂移的 VIP,防脑裂 = 放行心跳 + 多条件判定 + 监控兜底------这套思想从 Keepalived 到哨兵到 MHA 全通用。

💬 互动

你们生产是"Nginx 裸奔单点"还是有 Keepalived 双活?有没有在真故障时验证过切换速度?评论区聊聊你们的高可用现状。

下一篇预告:《S3-06 MySQL 安装部署与配置参数调优》------中间件的数据库篇开张:从 apt 安装到 my.cnf 关键参数,把你的 MySQL 8.4 调到"生产默认值"。

相关推荐
SQL774 小时前
IT运维发展史,一部宏伟史诗
运维·运维发展史
分布式存储与RustFS5 小时前
Terraform 状态文件老在本地丢、并发还撞锁:把 state 锁进 RustFS
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
csdn_aspnet5 小时前
macOS 10 、Docker 玩轉 MySQL
运维·mysql·macos·docker·容器·mac
Java码农也是农6 小时前
一篇文章讲清 NGINX 反向代理:location、proxy_pass、负载均衡与排错
nginx·负载均衡·后端开发·反向代理·proxy_pass
爱和冰阔落7 小时前
【Linux网络】TCP 半包粘包怎么解决?从长度报头、JSON 拆包到网络计算器完整实战
linux·运维·网络·tcp/ip
无奈笑天下18 小时前
银河麒麟上nproc命令教程详解
linux·运维·服务器
威嵌神州1 天前
嵌入式排故实录:高并发下串口数据“超时丢包”的根因剖析与架构优化
运维·服务器·嵌入式硬件·缓存
Decay__1 天前
SQLServer 索引与 SQL 优化 —— 聚集索引、非聚集索引、覆盖索引、碎片维护与执行计划
运维·数据库·sql·mysql·架构
java_logo1 天前
Docker 部署 DeepSeek Harness(moelin):轻松搭建带登录的本地 AI Agent 平台
运维·docker·容器·ai agent·deepseek·harness·轩辕镜像