0%

LVS

LVS

LVS 工作原理

理解 LVS 工作原理,理解 Netfilter 是前提条件

Netfilter

Netfilter 是 Linux 内核中一个的网络数据包处理框架,是 LVS 实现的底层引擎。

Netfilter 在网络层设下了5个 hook,IPVS、iptables 这些 Linux 内核模块通过向这些 hook 注册回调函数来处理数据包。

Netfilter hook:

  1. PREROUTING
    • 时机:数据包刚进入网络层,在进行路由决策之前,所有接收的数据包到达的第一个 hook
    • 作用:通常在这里进行目标地址转换(DNAT),决定数据包是发给本机,还是需转发
  2. INPUT (LOCAL_IN)
    • 时机:数据包经过路由判断,发现其目标地址是本机
    • 作用:控制外部对本机的访问,是入站防火墙规则的核心位置
  3. FORWARD
    • 时机:数据包经过路由判断,发现其目标地址不是本机,而是需要本机进行转发(例如,本机作为路由器或网关)
    • 作用:控制流经本机的数据包,是转发防火墙规则的核心位置
  4. OUTPUT (LOCAL_OUT)
    • 时机:由本机进程产生的数据包,准备发送出去
    • 作用:控制本机程序对外部网络的访问,是出站防火墙规则的核心位置
  5. POSTROUTING
    • 时机:数据包即将离开本机,通过物理网络设备发送出去之前
    • 作用:通常在这里进行源地址转换(SNAT),比如让内网机器通过网关的公网IP访问互联网

IPVS 工作原理

IPVS(LVS 的内核模块)在 Netfilter 注册了 3 个核心 hook 函数

ip_vs_in() —— 核心入口函数

  • 挂载点:通常在 LOCAL_IN
  • 触发时机:当客户端的请求数据包到达 LVS 服务器,且目标地址是虚拟 IP(VIP)时触发
  • 核心作用
    1. 检查连接(Connection Lookup)
      • 它会先查表(哈希表),看这个请求是否属于一个已经建立的连接
      • 如果是老请求(比如 TCP 握手后的数据包),直接按之前的路径转发,不重新调度
    2. 新建连接与调度(Scheduling)
      • 如果是新请求(如 TCP SYN 包),它会调用调度算法(如轮询 rr、最少连接 lc)从后端真实服务器池中挑选一台服务器
    3. 建立连接记录
      • 在内存中创建一个 ip_vs_conn 结构体,记录“客户端 <-> LVS <-> 真实服务器”的映射关系
    4. 修改数据包(DNAT/MAC)
      • 根据工作模式(NAT、DR、TUN),修改数据包的目标 IP 或 MAC 地址,将其指向选中的真实服务器
    5. 重定向
      • 修改完后,它通常返回 NF_STOLEN,告诉内核“这个包我接管了,别再往下传了”,并将其推向转发流程

ip_vs_out() —— 响应处理函数

  • 挂载点NF_INET_FORWARD
  • 触发时机:当真实服务器处理完请求,返回响应包,且该数据包流经 LVS 时触发
    • 注意:在 DR 模式下,响应包直接回客户端,不经过此函数;此函数主要在 NAT 模式下起作用。
  • 核心作用
    1. 查找连接
      • 根据响应包的五元组(源 IP、源端口、目标 IP、目标端口、协议),在连接表中找到对应的 ip_vs_conn 记录
    2. 源地址转换(SNAT)
      • 这是最关键的一步。它会将响应包的源 IP(真实服务器 IP)修改为虚拟 IP(VIP)
      • 这样,客户端收到的包看起来就是 VIP 发回来的,从而实现了负载均衡的透明性
    3. 状态更新
      • 更新连接的状态(如 TCP 序列号),确保连接跟踪的准确性

ip_vs_post_routing() —— 最后的关卡

  • 挂载点NF_INET_POST_ROUTING
  • 触发时机:数据包即将离开网卡,发送到物理网络之前的最后一刻
  • 核心作用
    1. 防止规则冲突
      • 它的主要任务是确保经过 IPVS 处理过的数据包,不再被 iptables 的 NAT 规则重复处理
      • 如果没有这个函数,iptables 可能会再次修改已经被 IPVS 修改过的地址,导致网络错乱
    2. 快速放行
      • 它会检查数据包是否带有 IPVS 的标记。如果有,直接返回 NF_ACCEPTNF_STOLEN,让数据包迅速通过,不再进行复杂的防火墙规则匹配,提高转发效率

请求包流程(CIP -> VIP -> RS)

1. PREROUTING 链:入场

  • 动作:数据包从网卡进入,到达 PREROUTING
  • Netfilter 行为:此时数据包的目标 IP 是 VIP。内核进行路由查找(Routing Decision)。
  • 判断:因为 VIP 配置在 LVS 的网卡上,内核认为“这个包是发给本机的”
  • 流向:数据包被送往 INPUT 链。

2. INPUT 链:LVS 的核心拦截点 (ip_vs_in)

这是 LVS 最关键的“魔法”发生地。

  • Hook 函数ip_vs_in()
  • 动作
    1. 拦截:IPVS 模块在 INPUT 链上注册了钩子,它比普通的 TCP/IP 协议栈更早拿到数据包。
    2. 匹配:检查数据包的目标 IP:Port(VIP:80)是否在 IPVS 的服务列表中。
    3. 调度:如果是新连接,根据算法(如轮询)选一台真实服务器(RS)。
    4. 修改(关键)
      • NAT 模式:修改目标 IP 为 RS 的 IP(DNAT)。
      • DR 模式:修改目标 MAC 地址为 RS 的 MAC。
    5. 连接跟踪:在 Conntrack 表中建立一条记录,标记这个连接将来需要怎么处理回包。
    6. 重定向:IPVS 修改完包后,会告诉内核“这个包我处理了”,并将其强制转发POSTROUTING 链,而不是交给本机的应用程序(如 Nginx/Apache)。

3. POSTROUTING 链:离场

  • Hook 函数ip_vs_post_routing()
  • 动作
    • 数据包此时已经变成了发往 RS 的样子(目标 IP 或 MAC 已变)。
    • ip_vs_post_routing() 的作用是“放行”。它给数据包打上标记,告诉后续的 iptables 规则:“这个包是 LVS 转发的,不要再做 SNAT/Masquerade 处理了,直接发走吧。”
  • 流向:数据包通过物理网卡发出,到达真实服务器(RS)。

NAT 响应包流程(RS -> LVS -> CIP)

1. PREROUTING 链:入场

  • 动作:响应包从网卡进入 LVS。
  • Netfilter 行为:内核进行路由查找。
  • 判断:目标 IP 是 CIP(外网 IP),不是本机。
  • 流向:数据包被送往 FORWARD 链。

2. FORWARD 链:LVS 的还原点 (ip_vs_out)

  • Hook 函数ip_vs_out()
  • 动作
    1. 识别:IPVS 检查数据包的五元组,发现这个包属于之前建立的那个连接(通过 Conntrack 表匹配)。
    2. 还原(SNAT):IPVS 将数据包的源 IP 从 RS 的 IP(RIP)修改回 VIP
      • 目的:让客户端觉得是 VIP 给它回的包,而不是 RS。
    3. 流向:修改完成后,数据包继续向前,进入 POSTROUTING

3. POSTROUTING 链:离场

  • Hook 函数ip_vs_post_routing()
  • 动作
    • 同样,这里的作用是防止被 iptables 的其他规则干扰。
    • 确认数据包已经完成 SNAT,允许其离开网卡。
  • 流向:数据包发往互联网,最终回到客户端(CIP)。

LVS 工作模式

DR 直接路由

请求经过负载均衡器,响应直接返回给客户端

前提条件:

  • LVS 和 RS 在同一物理网段内(可以通过修改 MAC 下一跳直达的前提)
  • LVS 和 RS 同时配置 VIP(RS 可以接收目的 IP 为 VIP 包的前提)

转发流程:

  • 请求阶段
    1. 源/目的 IP 保持不变,源 IP 为客户端 IP(CIP),目的 IP 为 VIP
    2. 通过修改目的 MAC 地址,将下一跳规定为同一物理网段内的 RS 节点
  • 响应阶段
    1. 不返回 LVS,直接返回到客户端
    2. 源 IP 为 VIP,目的 IP 为 客户端 IP(CIP)

优点:

  • 高性能,LVS 不用处理响应,负载降低一半
  • IP 透明,RS 可以拿到客户端 IP(CIP)

缺点:

  • 不支持端口映射,转发只能相同端口
  • 强制要求 LVS 和 RS 在同一物理网段内
  • 强制要求每台 RS 上配置 VIP 和 ARP 抑制

NAT

Tunnel

FullNAT

LVS 负载均衡算法

LVS 组成