构建基于Keepalived+LVS的高可用四层负载均衡集群

在高并发业务场景中,负载均衡器是流量入口的第一道关卡,其稳定性和性能直接决定了整个系统的可用性。然而,单点的负载均衡器自身即是一个巨大的单点故障(SPOF)。本文将从底层原理到一线工程实践,深入剖析如何利用 LVS(Linux Virtual Server)作为高性能的四层负载均衡核心,并结合 Keepalived 的 VRRP 协议实现主备自动切换,构建一个兼具高性能与高可用的四层负载均衡集群。本文面向有一定网络及系统基础的中高级工程师,旨在穿透表层配置,理解其背后的内核网络栈、协议交互与架构权衡。

现象与问题背景

假设我们正在为一个高频交易系统或者一个大型电商平台的后端服务设计入口架构。初始阶段,我们可能会部署一台 Nginx 或 LVS 作为所有业务服务器(Real Server)的流量入口。这种架构简单直接,但在流量洪峰或硬件故障面前极其脆弱。一旦这台唯一的负载均衡器宕机——无论是由于内核恐慌、网卡故障、电源中断还是网络分区——整个业务系统将对外完全不可访问,造成严重的生产事故和商业损失。问题的核心在于,负载均衡器本身成为了架构中的“阿喀琉斯之踵”。因此,我们必须设计一种机制,能够让负载均衡层自身实现冗余和故障自动转移,这便是双机热备(High Availability)的核心诉fus请。

关键原理拆解

要构建一个可靠的热备系统,我们必须理解其两大基石:LVS 的高性能数据转发平面,以及 Keepalived 的高可用控制平面。它们分别在 Linux 内核和用户空间工作,共同构成了这套经典架构。

LVS/IPVS:内核中的高性能交换机

作为一名架构师,我们首先要明确 LVS 并非一个“软件”,而是 Linux 内核网络协议栈(Netfilter)的一部分,其核心是 IPVS (IP Virtual Server)。你可以将其理解为一个在内核态运行、效率极高的四层交换机。当一个数据包到达网卡并进入内核协议栈时,IPVS 通过在 Netfilter 的 PREROUTING 链或 INPUT 链上注册钩子函数,能够抢在 TCP/IP 协议栈处理之前,根据预设的规则直接修改数据包的目标地址,然后将其转发出去。这个过程完全在内核态完成,避免了用户态与内核态之间上下文切换的巨大开销,这是 LVS 性能远超 Nginx 等七层负载均衡器的根本原因。

LVS 主要有三种工作模式,其中生产环境最常用的是 DR (Direct Routing) 模式,它的工作原理极其精妙:

  • 请求(Ingress)流程:
    1. 客户端向虚拟 IP (VIP) 发起请求,数据包的目标 IP 是 VIP。
    2. 数据包经由物理网络到达 LVS Director 服务器。
    3. LVS Director 接收到数据包后,发现目标 IP 是自己管理的 VIP。IPVS 模块介入,根据负载均衡算法(如轮询、最少连接等)选择一台后端 Real Server。
    4. 关键步骤:LVS Director 不修改数据包的目标 IP 地址(仍然是 VIP),而是直接修改数据包的目标 MAC 地址,将其改为选定的 Real Server 的 MAC 地址。然后将这个修改过二层头部的数据帧直接抛到局域网中。
    5. 交换机根据新的目标 MAC 地址,将数据帧转发给对应的 Real Server。
  • 响应(Egress)流程:
    1. Real Server 收到数据帧,解开后发现目标 IP 是 VIP。由于所有 Real Server 都被配置在 `lo` 环回接口上绑定了这个 VIP,因此内核认为这个包是发给自己的,正常处理。
    2. 业务处理完成后,Real Server 构建响应数据包。此时,源 IP 是 VIP,目标 IP 是客户端 IP。
    3. 由于目标是公网的客户端,Real Server 会通过自己的默认网关将响应包直接发送出去,完全绕过了 LVS Director

DR 模式的性能优势显而易见:响应流量不经过 LVS Director,这极大地减轻了 Director 的网络带宽和 CPU 压力,使其能够支撑极高的吞吐量,成为了事实上的业界标准方案。

Keepalived/VRRP:虚拟路由器的冗余协议

解决了数据平面的性能问题,我们还需要解决控制平面的单点问题。Keepalived 就是为此而生的。它在用户空间运行,但其核心功能是通过 VRRP (Virtual Router Redundancy Protocol, RFC 5798) 协议与内核交互,实现 VIP 的动态漂移。

VRRP 的设计初衷是为了解决静态路由环境下默认网关的单点问题。它将多台物理路由器(在我们的场景中是 LVS Director)组织成一个虚拟路由器组(VRRP Group)。这个组对外暴露一个唯一的虚拟 IP (VIP)。组内所有成员通过发送 VRRP 协议通告(默认使用多播地址 224.0.0.18)来选举一个 Master,其余则成为 Backup。

  • 选举机制:选举基于优先级(Priority)。配置的优先级越高的节点,越有可能成为 Master。如果优先级相同,则比较 IP 地址大小。
  • 状态机与心跳:Master 节点会周期性地(默认为 1 秒)发送 VRRP 通告,证明自己“活着”。Backup 节点则持续监听这些通告。如果在指定时间内(默认为 3 倍通告间隔)没有收到 Master 的心跳,Backup 节点中优先级最高的那个就会认为 Master 已宕机,立即发起抢占,将自己提升为新的 Master。
  • VIP 漂移与网络宣告:当一个节点从 Backup 变为 Master 时,它会立即执行两个关键动作:
    1. 通过 netlink 接口调用内核,将 VIP 配置到自己的物理网卡上。
    2. 向局域网发送一个或多个免费 ARP (Gratuitous ARP) 包。这个 ARP 包的目的是宣告“拥有 VIP 的 MAC 地址已经变更为我的 MAC 地址”,以此来强制刷新上游交换机和路由器的 ARP 缓存表。这是实现秒级切换、避免流量黑洞的核心机制。

Keepalived 不仅实现了 VRRP,还集成了对 IPVS 的管理能力。它能够周期性地检查 Real Server 的健康状况(如 TCP 端口探测、HTTP 请求检查),并根据结果动态地向内核中的 IPVS 模块添加或移除 Real Server 条目,从而构成了一个完整的、自愈的负载均衡系统。

系统架构总览

结合 LVS 与 Keepalived,我们的高可用负载均衡集群架构如下:

  • 两台 LVS Director 服务器:物理配置完全相同,我们称之为 LVS-Master 和 LVS-Backup。它们都运行着 Keepalived 服务。
  • 虚拟 IP (VIP):这是整个集群对外提供服务的统一入口 IP。在任意时刻,VIP 只会绑定在 LVS-Master 服务器的物理网卡上。
  • 心跳网络:两台 Director 之间通过 VRRP 协议进行心跳通信,通常在业务网卡上进行,也可以配置专门的心跳网络。
  • 后端 Real Server 池:一组运行实际业务应用的服务器。它们与 LVS Director 在同一个二层网络中(这是 DR 模式的要求)。

正常工作流程: LVS-Master 节点持有 VIP,处理所有进入的客户端请求,并将它们分发到后端 Real Server 池。LVS-Backup 节点处于待命状态,不持有 VIP,但持续监听 Master 发来的 VRRP 心跳。

故障切换流程: 当 LVS-Master 因任何原因宕机或网络中断,LVS-Backup 在超时后无法收到心跳。它会立即将自己的状态提升为 Master,接管 VIP,并发送 Gratuitous ARP 更新网络设备。客户端的后续请求将无缝地流向新的 Master,整个切换过程对客户端透明,通常在 1-3 秒内完成。

核心模块设计与实现

理论终须落地。以下是关键的配置与代码实现,其中蕴含着许多容易被忽视的工程细节。

LVS Director 节点配置 (`keepalived.conf`)

这是整个系统的“大脑”。Master 和 Backup 节点的配置几乎完全一样,只有 `state` 和 `priority` 两个参数不同。

LVS-Master (e.g., 192.168.1.10) 配置:


global_defs {
   router_id LVS_MASTER_01 # 路由ID,全局唯一
}

# VRRP实例,用于VIP的HA
vrrp_instance VI_1 {
    state MASTER             # 主节点声明为MASTER
    interface eth0           # VIP绑定的物理接口
    virtual_router_id 51     # 虚拟路由ID,主备必须一致
    priority 150             # 优先级,Master要高于Backup
    advert_int 1             # VRRP通告间隔,单位秒
    authentication {
        auth_type PASS
        auth_pass 1111       # 简单的认证密码,主备一致
    }
    virtual_ipaddress {
        192.168.1.100/24     # 这里是VIP
    }
}

# 虚拟服务器定义 (LVS部分)
virtual_server 192.168.1.100 80 {
    delay_loop 6             # 健康检查间隔
    lb_algo wrr              # 负载均衡算法:加权轮询
    lb_kind DR               # 工作模式:DR模式
    persistence_timeout 50   # 会话保持时间
    protocol TCP

    real_server 192.168.1.201 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.1.202 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

LVS-Backup (e.g., 192.168.1.11) 配置:

与 Master 的配置相比,只需修改两处:


...
vrrp_instance VI_1 {
    state BACKUP             # 从节点声明为BACKUP
    ...
    priority 100             # 优先级,低于Master
    ...
}
...

极客解读:

  • `virtual_router_id`: 这是 VRRP 组的唯一标识。同一网络中如果有多套 LVS+Keepalived 集群,此 ID 必须不同,否则会互相干扰。
  • `priority`: 优先级是选举的核心。Master 的优先级必须高于所有 Backup。
  • `lb_kind DR`: 明确指定 LVS 工作在 DR 模式,这是性能的关键。
  • `TCP_CHECK`: Keepalived 自带的健康检查机制。它会尝试与 Real Server 的 80 端口建立 TCP 连接。如果失败,Keepalived 会自动调用 `ipvsadm` 命令将该 Real Server 从可用池中摘除。

Real Server 节点的关键配置

这是 DR 模式中最容易出错的地方,即所谓的“ARP 问题”。由于 VIP 同时配置在 LVS Director 和所有 Real Server 上,如果不做任何处理,当网络中的设备查询 VIP 的 MAC 地址时,可能会收到多个 ARP 响应,导致流量混乱。我们必须确保 Real Server 上的 VIP 对外“隐身”,只在内核层面响应数据包。

所有 Real Server 都需要执行以下配置:


#!/bin/bash

# VIP地址
VIP="192.168.1.100"

# 将VIP绑定到lo环回接口,并设置子接口以避免与lo主地址冲突
ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP
route add -host $VIP dev lo:0

# 关闭ARP响应 (arp_ignore)
# 1: 只在请求的目标IP是本地接口配置的地址时,才响应ARP请求
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "1" > /proc/sys/net/ipv4/conf/eth0/arp_ignore

# 控制ARP通告 (arp_announce)
# 2: 总是使用最适当的本地地址作为ARP请求的源地址,避免使用VIP作为源地址对外通告
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
echo "2" > /proc/sys/net/ipv4/conf/eth0/arp_announce

echo "Real Server LVS-DR config completed."

极客解读:

  • 将 VIP 绑在 `lo` 接口:这是核心技巧。`lo` 环回接口不会对外进行 ARP 通告和响应。当 LVS Director 将目标 MAC 修改后的数据帧发给 Real Server 时,Real Server 的网卡(如 eth0)接收后,内核在 IP 层发现目标 IP (VIP) 是本机 `lo` 接口上的地址,于是合法地接收并处理它。
  • `arp_ignore=1`:内核参数,告诉内核只有当 ARP 请求的目标 IP 地址是接收该请求的接口上配置的地址时,才做出响应。由于 VIP 配置在 `lo` 上,而 ARP 请求从 `eth0` 进来,因此 Real Server 不会响应对 VIP 的 ARP 请求。
  • `arp_announce=2`:内核参数,确保本机向外发起通信时,不会将 `lo` 接口上的 VIP 地址作为源 IP 地址宣告出去。它会选择 `eth0` 接口的真实 IP 作为源 IP 进行 ARP。

这套组合拳彻底解决了 ARP 冲突问题,保证了 LVS-DR 模式的正确运行。

性能优化与高可用设计的对抗性思考

一套健壮的系统不仅要能跑起来,更要能在极端情况下存活。以下是架构师必须思考的几个对抗性问题。

脑裂(Split-Brain)问题及其缓解

脑裂是所有主备/集群架构的噩梦。在我们的场景中,它指两台 LVS Director 因为网络分区(例如,它们之间的心跳网络中断,但它们各自都能访问外部网络)而都认为自己是 Master,从而都占用了 VIP。这会导致灾难性后果:上游交换机的 ARP 表会在两个 MAC 地址之间疯狂切换,导致部分客户端流量被导向旧的 Master,部分被导向新的 Master,造成大量连接中断和服务不可用。

缓解策略:

  • 冗余心跳网络:使用网络绑定(Bonding)技术将两块物理网卡虚拟成一块,或者在 Keepalived 中配置多个心跳通道,降低单点网络故障导致脑裂的概率。
  • 引入仲裁机制:VRRP 协议本身没有强大的仲裁机制。我们可以通过 `track_script` 脚本引入一个外部“见证人”。例如,让 Keepalived 定期去 `ping` 网关地址。如果连网关都 `ping` 不通,说明自身网络存在严重问题,即使收不到 Master 心跳,也主动降低自己的优先级或进入 `FAULT` 状态,避免错误地抢占 VIP。
  • 高级 fencing 机制:在更严格的金融场景中,可能会引入硬件 fencing 设备(如电源控制器)。当检测到脑裂时,通过带外管理接口(如 IPMI)直接将其中一个节点强制重启或断电,确保同一时间只有一个 Master 存活。

抢占(Preemption)策略的权衡

Keepalived 默认是抢占模式。即当原来的 Master 节点恢复后,它会立即发送高优先级的 VRRP 通告,从当前的临时 Master 手中把 VIP 再抢回来。这在理论上保证了最高可用性的节点始终提供服务,但在实践中可能导致问题。

想象一个场景:原 Master 节点网络不稳定,频繁地断开和重连。这会导致 VIP 在两个节点间来回“漂移”,每次漂移都会引起短暂的网络中断和 ARP 表更新,这种“网络抖动”对业务的伤害可能比短暂由 Backup 提供服务更大。因此,在许多生产环境中,我们倾向于配置 `nopreempt`。


vrrp_instance VI_1 {
    ...
    nopreempt
    ...
}

在 `nopreempt` 模式下,一旦 Backup 节点成为 Master,即使原 Master 恢复,它也只会安静地作为 Backup 存在,不会主动抢占。这使得系统状态更加稳定,但需要运维人员在确认原 Master 完全恢复后,手动介入进行服务回切(failback)。这是典型的用运维复杂度换取系统稳定性的 trade-off。

会话保持(Session Persistence)

对于像电商购物车、用户登录状态等需要保持会话的应用,必须开启会话保持。LVS 通过 `persistence_timeout` 参数实现。IPVS 模块内部维护一个连接跟踪表,记录了“客户端IP -> 虚拟服务 -> Real Server”的映射关系。在超时时间内,来自同一客户端 IP 的所有请求都会被固定转发到同一台 Real Server。这个值需要根据业务特性仔细评估:设置太短,会话容易中断;设置太长,会占用大量内核内存,且在某台 Real Server 宕机时,可能导致负载分配不均。

架构演进与落地路径

任何架构都不是一蹴而就的,而是随着业务发展不断演进的。

  1. 阶段一:单点 LVS Director。 在业务初期或开发测试环境,可以先部署单点 LVS,验证 DR 模式配置的正确性,并对后端服务进行负载均衡。此阶段主要目标是验证技术栈和性能。
  2. 阶段二:主备模式(Master/Backup)。 这是本文详述的经典方案。当业务对可用性提出要求时,引入第二台 Director 和 Keepalived,实现故障自动切换。这是绝大多数中大型企业采用的标准部署模式。
  3. 阶段三:双主模式(Active/Active)。 如果预算充足,为了更好地利用硬件资源,可以采用双主模式。配置两组或多组 VRRP 实例,让两台 Director 各自持有一部分 VIP。例如,Director A 是 VIP1 的 Master 和 VIP2 的 Backup,Director B 是 VIP2 的 Master 和 VIP1 的 Backup。这样两台机器都在处理流量,互为备份。这种模式配置更复杂,需要仔细规划 VIP 和路由。
  4. 阶段四:走向云原生与商业解决方案。 当企业全面上云或业务规模达到互联网巨头级别时,自建 LVS/Keepalived 集群的运维成本会凸显。此时可以考虑:
    • 云服务商负载均衡器(SLB/ELB):它们底层可能也是基于 LVS/DPDK 等技术,但提供了更完善的监控、弹性伸缩和安全防护能力,将运维复杂性外包给了云厂商。
    • 硬件负载均衡器(F5/A10):在金融、电信等对性能和稳定性要求极高的场景,硬件 F5 凭借其专用的网络处理器(ASIC)和成熟的软件栈,仍然是黄金标准,当然成本也更高。
    • Kubernetes Service & Service Mesh:在容器化和微服务时代,Kubernetes 的 Service 对象(其 `kube-proxy` 组件在较新版本中也默认使用 IPVS 模式)提供了原生的服务发现和负载均衡。而 Service Mesh (如 Istio) 则在更高维度提供了更精细的流量控制,但这是另一个宏大的话题了。

总而言之,LVS + Keepalived 组合是一套经受了近二十年生产环境严苛考验的经典架构。它以极高的性能、稳定性和开源免费的特性,至今仍是众多企业在自建数据中心或私有云中构建高可用四层负载均衡的首选方案。理解并精通其原理和实践,是每一位后端架构师的必备技能。

延伸阅读与相关资源

  • 想系统性规划股票、期货、外汇或数字币等多资产的交易系统建设,可以参考我们的
    交易系统整体解决方案
  • 如果你正在评估撮合引擎、风控系统、清结算、账户体系等模块的落地方式,可以浏览
    产品与服务
    中关于交易系统搭建与定制开发的介绍。
  • 需要针对现有架构做评估、重构或从零规划,可以通过
    联系我们
    和架构顾问沟通细节,获取定制化的技术方案建议。
滚动至顶部