尧图精选

LVS-DR + Keepalived 高可用负载均衡架构详解与实战

🕒 发布时间:2026/10/1 6:10:12 📁 来源:尧图网络
1. 为什么选 LVS-DR Keepalived先把架构账算清楚1.1 负载均衡的本质流量怎么才算“被平均”很多刚接触高可用的人会把注意力全放在负载均衡器本身觉得只要前面挂了台转发设备请求就会自动分散到后端。其实负载均衡的核心问题有两个一是“流量怎么分”二是“分了之后后端能不能正常回包”。这两件事看着简单实际牵扯到协议栈的行为、ARP 的响应机制、甚至内核参数的调整。很多部署翻车都是栽在第二件事上。我在生产环境里做过几轮选型对比最终固定使用 LVS-DR Keepalived 这套组合。LVS 工作在 Linux 内核的 IPVS 模块上转发效率非常高不像 Nginx 那样要经过用户态和内核态之间反复拷贝。DR 模式的全称是 Direct Routing数据包进来之后LVS 只负责改二层 MAC 地址把请求原封不动转发给后端的真实服务器回包由真实服务器直接返回给客户端。这意味着负载均衡器基本不承载回程流量压力小很多瓶颈自然也就低。1.2 Keepalived 的角色它不只是“看门狗”Keepalived 在这套方案里的作用很容易被低估。很多人以为它只是监控 LVS 进程挂了就重启其实核心是它的 VRRP 实现。VRRP 协议让多台 LVS 节点共享一个虚拟 IP主节点周期性发送心跳报文备份节点收不到心跳后就会接管 VIP整个过程对客户端透明。Keepalived 还会主动探测后端真实服务器的健康状态探测失败了就从 LVS 转发表里摘掉该节点恢复了再重新加回来。这个能力非常关键因为 LVS 本身不具备后端健康检查功能如果没有 Keepalived后端某台机器挂了LVS 依然会把请求调度过去那部分用户就直接断连。1.3 和 Nginx、HAProxy 相比优势短板都在哪先说我的结论动态请求转发、需要 HTTP 层路由规则的场景用 Nginx 更顺手需要精细的四层 ACL 或内容交换策略HAProxy 是好选择但如果你要的是超高转发性能和稳定的故障转移LVS-DR 几乎是绕不开的选项。LVS-DR 的短板也很明显它只能做四层转发不能识别 URL、Cookie 这类七层信息无法做基于内容的精细化路由。另外它不修改数据包内容只改 MAC 地址所以后端和负载均衡器必须在同一个二层网络里。部署前如果没看清楚网络拓扑直接拿跨网段的机器硬上流量根本通不了。这个坑我在早期排障时踩过后面会专门讲。2. 部署前的网络规划与硬件准备2.1 角色划分谁当主、谁当备、谁来干活我这次部署用的是一套标准的三层架构两台 LVS 节点组成主备关系两台 Nginx 或 Apache 作为后端真实服务器。先说节点命名后面配置里会直接用到。LVS-Master主负载均衡节点IP 为 192.168.1.10LVS-Backup备负载均衡节点IP 为 192.168.1.11Web-1后端真实服务器 1IP 为 192.168.1.21Web-2后端真实服务器 2IP 为 192.168.1.22VIP虚拟 IP 192.168.1.100由 Keepalived 动态绑定到当前主节点这里最容易被忽略的点是VIP 必须和真实服务器在同一个广播域里。DR 模式要求后端真实服务器能用 VIP 接受请求但同时又不能响应 VIP 的 ARP 请求否则客户端的包会被真实服务器抢走。这个矛盾需要靠后面的 ARP 抑制配置来解决。2.2 内核参数与基础软件准备操作系统我建议用 CentOS 7.9 或兼容的 Linux 发行版内核版本不要太老保证有完整的 IPVS 模块。软件只需要装 KeepalivedLVS 本身不依赖额外的用户态程序内核里已经集成了。安装命令很简单yum install -y keepalived ipvsadmipvsadm 是管理 IPVS 转发表的工具虽然生产配置由 Keepalived 生效但调试时必须用它查看实时状态。内核模块确认一下modprobe ip_vs lsmod | grep ip_vs如果模块没加载先确认内核是否支持再检查是否被安全策略禁用了。这一步看似基础但我在不少机器上遇到过内核模块加载失败的情况原因五花八门有的是内核版本编译时裁剪了 IPVS 功能有的是因为内核安全模块拦截。别急着往下配先把它跑通。2.3 网络拓扑设计的几个细节VIP 所在网段我建议单独划一个子接口比如 ens33:0。不要直接改主网卡的 IP这样切换时恢复麻烦而且容易造成地址冲突。Keepalived 配置里指定 VIP 绑定的网卡名切换时由 VRRP 自动完成地址迁移。后端真实服务器的网卡 IP 保持原有的 192.168.1.21 和 192.168.1.22但必须在 lo 回环接口上额外绑定 VIP同时设置严格的 ARP 过滤规则。这样做的理由是真实服务器在处理请求时发现目标地址是 VIP如果本机没有 VIP 就会直接把包丢掉绑上 VIP 才能收到数据但如果不抑制 ARP 响应同一网段的其他设备会学到 VIP 的 MAC 地址指向真实服务器导致 LVS 转发失效。3. 核心配置实操Keepalived 与 LVS-DR 落地过程3.1 Keepalived 主节点配置拆解主节点的配置文件在 /etc/keepalived/keepalived.conf。我把生产上跑过的配置简化后贴出来逐段说清楚。global_defs { router_id LVS_MASTER vrrp_skip_check_adv_addr vrrp_strict vrrp_iptables } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100/24 dev ens33 label ens33:0 } } virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo wrr lb_kind DR nat_mask 255.255.255.255 persistence_timeout 0 protocol TCP real_server 192.168.1.21 80 { weight 2 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.1.22 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }global_defs 里的 vrrp_strict 启用了严格的 VRRP 模式它会自动配置防火墙规则限制 VRRP 报文只从对应接口进出。如果你机器上本来就有自定义防火墙规则要特别注意这个选项可能造成 Keepalived 的 VRRP 组播包被拦截。后文排障部分我会详细说一个和它直接相关的真实案例。virtual_server 块定义了负载均衡转发表。lb_kind 必须写成 DR这是模式的关键lb_algo 我用了 wrr 加权轮询。为什么不用默认的 rr因为 Web-1 和 Web-2 两台机器的配置并不完全一样Web-1 内存更大权重给 2Web-2 给 1这样流量大致按 2:1 分配。如果你想让所有后端“等开销负载均衡”也就是完全平均分配就用 lb_algo rr权重字段不生效每个节点轮着转发一个请求真实服务器的配置必须一致。这里还有一个关键参数 nat_mask 255.255.255.255。很多人照着网上老教程写 255.255.255.0结果配置一加载就异常。原因是 DR 模式下LVS 会把后端真实服务器当作“子网内的单点主机”来处理掩码设为全 255 表示只匹配这一个 IP而不是整个网段。Keepalived 同步到内核 IPVS 表时如果掩码不对转发逻辑就会错乱。3.2 备节点配置只改三处即可备节点配置文件结构和主节点几乎一样只需改动三处router_id 改成 LVS_BACKUPstate 改为 BACKUPpriority 降为 90其他内容完全一致尤其是 virtual_router_id、认证密码、VIP 和 virtual_server 定义必须保持一致否则两台节点无法组成同一个 VRRP 组会发生双主或者互相抢占的诡异现象。备节点的 priority 为什么不能设成 100因为在 VRRP 协议里优先级数值高者成为 Master。如果两台都是 100主节点挂了还能靠比较 IP 地址大小来选主但主节点恢复后行为就不确定了。设成 100 和 90保证正常情况下 Master 稳定在主节点备节点永远处于竞选等待状态。3.3 真实服务器的 ARP 抑制整个方案最容易翻车的地方真实服务器上要做的配置有两部分绑定 VIP 到回环接口然后设置 ARP 过滤规则。cat /etc/sysconfig/network-scripts/ifcfg-lo:0 EOF DEVICElo:0 IPADDR192.168.1.100 NETMASK255.255.255.255 ONBOOTyes NAMElo:0 EOF ifup lo:0然后写入 ARP 抑制参数cat /etc/sysctl.conf EOF net.ipv4.conf.lo.arp_ignore 1 net.ipv4.conf.lo.arp_announce 2 net.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2 EOF sysctl -p这两个参数要连在一起理解。arp_ignore 设为 1 表示只回答目标 IP 是本接口 IP 的 ARP 请求。注意 lo 接口上绑的 VIP 是虚拟地址而进入真实服务器的 ARP 请求目标 IP 是 VIP源 IP 是客户端或交换机的地址arp_ignore 会判断目标 IP 是否属于接收接口。arp_announce 设为 2 表示发送 ARP 报文时源 IP 选主机上所有接口里最合适的那个避免回包时源地址写成 VIP 导致路由错乱。我见过不少教程只贴 sysctl 参数不解释原理结果有人把网卡主 IP 也写进 lo:0 的配置文件里造成真实服务器无法正常访问外网。正确做法是只有 VIP 绑在 lo:0 上原来的业务 IP 继续留在 eth0 上不动。3.4 启动 Keepalived 并验证转发表主备节点先检查配置语法keepalived -t -f /etc/keepalived/keepalived.conf这个命令我在每次修改配置后都会跑一遍能提前发现括号不匹配、参数拼写错误这类低级问题。确认没问题后启动服务systemctl start keepalived systemctl enable keepalived启动后立刻在主节点上用 ip addr 看 VIP 是否有绑定ip addr show ens33如果看到 192.168.1.100/24 出现在 ens33 或 ens33:0 上说明 VRRP 已经正常起来。再到备节点上确认 VIP 还没被绑定备节点应该只有自己的物理 IP。然后查看 LVS 的转发表ipvsadm -Ln正常会输出类似下面的内容IP Virtual Server version 1.2.1 Prot LocalAddress:Port Scheduler Flags - RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.100:80 wrr - 192.168.1.21:80 Route 2 0 0 - 192.168.1.22:80 Route 1 0 0Forward 列显示 Route说明 DR 模式生效。如果显示 Tunnel 或者 Masq那就是配置里的 lb_kind 没写对。4. 高可用切换实测与故障排查实录4.1 主节点宕机演练VIP 切换要多久配置完成后一定要做实际演练别等到真出事了才发现切换有问题。我最常用的测试方法是直接关机或停掉 Keepalived 服务。停掉 Master 上的 Keepalivedsystemctl stop keepalived正常情况下备节点在 3 秒内advert_int 1 乘以 3 个通告周期收不到 Master 的心跳就会抢占 VIP。在备节点上执行ip addr show ens33一旦看到 VIP 已经绑定就说明切换成功。此时再用另一台机器访问 http://192.168.1.100业务应该不受影响请求继续被分发到后端真实服务器。值得注意的一个细节如果你的客户端缓存的 ARP 表项还指向旧 Master 的 MAC 地址切换后头几个请求可能会失败或者出现延迟。这是因为客户端在发起连接时会优先使用本地 ARP 缓存里的地址等到缓存超时后重新广播 ARP 请求才会拿到新 Master 的 MAC。在真实场景里同网段的交换机通过免费 ARP 广播会相对快地更新转发表但如果你在公网环境或跨了三层设备这个收敛时间会长一些。解决手段是在 Keepalived 配置里把 advert_int 调小或者配合交换机配置快速收敛。不过实际业务中这个窗口通常可以接受真要是秒级不可用都不行那得考虑其他更高规格的容灾方案。4.2 一个高危报错的全过程复盘keepalived exited with permanent error config最近有不少同行反映启动 Keepalived 时报错日志里写着 keepalived exited with permanent error config. 我仔细看过几个现场大多是配置解析阶段直接失败进程根本起不来。典型的错误原因有几种virtual_server 或 real_server 块内缺少必要指令比如 real_server 里没写 TCP_CHECK 或 HTTP_GET 健康检查定义authentication 块缺少 auth_type 或 auth_passvirtual_router_id 两端不一致VRRP 组匹配不上配置里写了 lb_kind DR 但 real_server 的端口定义错误或者健康检查类型写错其中最常见的是 real_server 块里的健康检查配置缺失。Keepalived 从 1.3 版本开始对配置解析更严格以前能容忍的写法现在直接拒绝启动。排查思路是这样先看日志journalctl -u keepalived -n 50日志会直接告诉你哪一行解析失败。如果没有明确行号就把配置里每个块单独注释掉二分定位。我建议新手一开始就用最小配置验证 Keepalived 的 VRRP 功能只保留 global_defs 和一个 vrrp_instance其他全部注释。等 VRRP 能正常切换再把 virtual_server 块解开逐段加回来。这比一次性写完所有配置再回头找错误要好用得多。4.3 真实服务器收不到流量先查 ARP 再查防火墙还有一个高频问题Keepalived 起来了VIP 也绑上了但访问 VIP 时请求没有被转发到后端的真实服务器或者真实服务器收到包但不回包。前半段问题绝大多数是 ARP 抑制配错了。验证方法很简单在客户端机器上执行arping -I eth0 -c 3 192.168.1.100看返回的 MAC 地址是不是当前 Master 节点的 MAC。如果是真实服务器的 MAC说明 ARP 抑制没有生效VIP 被真实服务器抢答了。回去检查 sysctl 参数特别是 net.ipv4.conf.all.arp_ignore 是否真的设为 1。后半段问题通常是防火墙拦了回包。真实服务器上确认一下iptables -L -n如果有默认 DROP 策略记得放行 80 端口。还有 SELinux 也可能干扰生产环境建议先 setenforce 0 测试确认是它的问题后再决定是否长期关闭或用策略放行。4.4 关于 vrrp_strict 和防火墙的一个实例前面提到 vrrp_strict 会让 Keepalived 自动配置防火墙规则。在一个客户的部署环境里主备节点之间能互相 ping 通但 VRRP 报文始终不通主备一直处于竞争状态。通过抓包发现 keepalived 的组播报文根本没有到达对端。后来发现问题是 Keepalived 自动添加的 iptables 规则和系统原有的 firewalld 规则冲突。vrrp_strict 模式的默认行为是只允许 VRRP 报文通过其他协议全拦。而 firewalld 的公共区域策略又把 VRRP 组播地址 224.0.0.18 拦掉了。我当时的处理是保留 vrrp_strict但在系统防火墙里加入显式放行firewall-cmd --permanent --add-rich-rulerule protocol value112 accept firewall-cmd --reload协议 112 就是 VRRP。加完之后主备心跳恢复正常。这里要提醒的是每个环境的防火墙基线不一样同样一条规则在 A 环境好用在 B 环境可能就和现有策略打架。改完必须重新过一遍主备切换测试。5. 监控体系与运维细节优化5.1 健康检查参数该怎么调TCP_CHECK 的三个参数我实际跑下来的经验值是 connect_timeout 3、nb_get_retry 3、delay_before_retry 3。这套组合意味着对每个真实服务器最多探测 3 次每次超时 3 秒失败后等待 3 秒再试。如果后端服务真的挂了Keepalived 会在 9 秒左右把节点摘除。如果你的后端是数据库或缓存这类对延迟更敏感的服务建议把连接超时调成 2 秒重试次数不变摘除时间能缩短到 6 秒。要注意的是调快意味着对后端波动更敏感后端偶尔出现 1 秒慢查询就把节点摘掉这种误判反而影响稳定性。生产环境里我会结合后端监控数据决定阈值不建议机械地抄一套配置。5.2 权重设计与容量预估怎么做很多人以为权重只是随便填个数字实际它决定了流量的分配比例和真实服务器的硬件配置、带宽、应用特性都有关系。我之前给一个客户做容量评估时两台后端机器配置分别是 4 核 8G 和 8 核 16G。一开始权重都设成 1结果 8 核机器长期空闲4 核机器 CPU 打满。后来把权重调成 2:18 核机器承担大约 2/3 流量4 核机器承担 1/3整体吞吐提升明显。如果后端应用是无状态接口比如纯 API 服务可以大胆用 wrr。如果涉及会话保持比如登录状态存在内存里LVS 层可以通过 persistence_timeout 设置会话保持超时时间比如 600 秒。但要注意这个参数会直接影响负载均衡的“等开销”特性同一用户的请求总是被分到同一台后端两台机器之间可能出现流量倾斜。本质上这是会话状态和有状态应用的权衡不是 LVS 能自动帮你解决的。5.3 日志和指标监控的几个推荐动作Keepalived 默认日志走系统日志通过 journalctl 查看。建议加一个独立的监控脚本或接入现有的 Prometheus Alertmanager 体系监控以下指标VIP 是否绑定在当前预期的主节点上IPVS 转发表中的 ActiveConn 是否持续增长后端真实服务器的 TCP 健康检查是否全部通过VRRP 状态是否长期处于 MASTER 或 BACKUP实践中我发现单纯看进程存活不靠谱。Keepalived 进程可能在但 VRRP 已经脑裂了或者 VIP 绑定的接口异常。写监控时不要只看 systemctl status 的结果而是定期执行 ip addr show 和 keepalived 的 vrrp 状态输出把真实网络状态作为监控对象。6. 我踩过的那些坑再多说几句先说说我最容易忽略的一个事备节点上的 LVS 转发表。刚开始搭建时我把 virtual_server 配置完整写在了主备两台机器上但备节点的 ipvsadm -Ln 输出里的 Forward 列一直显示 Masq。折腾了很久才发现是备节点某个历史配置文件残留导致 IPVS 表存在旧条目Keepalived 启动时没有完全清理干净。重启备节点网络服务和 Keepalived 后把残留表项清掉ipvsadm -C再重启服务一切恢复正常。这个经验告诉我调试 LVS 时必须养成分步验证的习惯先看 Keepalived 的 VRRP 状态再看 IPVS 表最后测真实链路。一步到位反而容易把问题搅成一锅粥。另外一个容易被忽略的点是时间同步。VRRP 报文太敏感如果主备节点系统时间偏差过大Keepalived 会认为对端异常导致频繁切换。我在维护规范里要求所有节点统一配置 NTP 或 chrony这也属于高可用的基础保障。如果你的后端真实服务器操作系统版本不统一比如一台 CentOS 7、一台 UbuntuARP 参数的写法略有差异但逻辑是一样的关注 lo 接口上的 VIP 绑定和 sysctl.conf 中的 arp_ignore / arp_announce。Ubuntu 上持久化配置用 netplan 或 /etc/sysctl.d/ 下的独立文件不要把 CentOS 的脚本原样拷过去细节差异会带来意想不到的麻烦。说实话LVS-DR Keepalived 这套方案能经受住这么多年的生产验证靠的是它架构简单、转发路径清晰。但正是因为它简单任何一个环节的细节出错都会导致整套系统表现诡异。配置文件的每个参数、每个 IP 地址的绑定位置、每条防火墙规则都值得你多花十分钟搞清楚背后的原因。我在每一次部署结束后都会把当时的完整配置和踩坑记录归档下次再遇到类似问题能省下大量排查时间。做基础设施维护这行真正的资产不是某个配置模版而是对每一行配置为什么这么写的理解深度。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →