LVS
LVS 工作原理
理解 LVS 工作原理,理解 Netfilter 是前提条件
Netfilter
Netfilter 是 Linux 内核中一个的网络数据包处理框架,是 LVS 实现的底层引擎。
Netfilter 在网络层设下了5个 hook,IPVS、iptables 这些 Linux 内核模块通过向这些 hook 注册回调函数来处理数据包。
Netfilter hook:
- PREROUTING
- 时机:数据包刚进入网络层,在进行路由决策之前,所有接收的数据包到达的第一个 hook
- 作用:通常在这里进行目标地址转换(DNAT),决定数据包是发给本机,还是需转发
- INPUT (LOCAL_IN)
- 时机:数据包经过路由判断,发现其目标地址是本机
- 作用:控制外部对本机的访问,是入站防火墙规则的核心位置
- FORWARD
- 时机:数据包经过路由判断,发现其目标地址不是本机,而是需要本机进行转发(例如,本机作为路由器或网关)
- 作用:控制流经本机的数据包,是转发防火墙规则的核心位置
- OUTPUT (LOCAL_OUT)
- 时机:由本机进程产生的数据包,准备发送出去
- 作用:控制本机程序对外部网络的访问,是出站防火墙规则的核心位置
- POSTROUTING
- 时机:数据包即将离开本机,通过物理网络设备发送出去之前
- 作用:通常在这里进行源地址转换(SNAT),比如让内网机器通过网关的公网IP访问互联网

IPVS 工作原理
IPVS(LVS 的内核模块)在 Netfilter 注册了 3 个核心 hook 函数
ip_vs_in() —— 核心入口函数
- 挂载点:通常在
LOCAL_IN - 触发时机:当客户端的请求数据包到达 LVS 服务器,且目标地址是虚拟 IP(VIP)时触发
- 核心作用:
- 检查连接(Connection Lookup):
- 它会先查表(哈希表),看这个请求是否属于一个已经建立的连接
- 如果是老请求(比如 TCP 握手后的数据包),直接按之前的路径转发,不重新调度
- 新建连接与调度(Scheduling):
- 如果是新请求(如 TCP SYN 包),它会调用调度算法(如轮询
rr、最少连接lc)从后端真实服务器池中挑选一台服务器
- 如果是新请求(如 TCP SYN 包),它会调用调度算法(如轮询
- 建立连接记录:
- 在内存中创建一个
ip_vs_conn结构体,记录“客户端 <-> LVS <-> 真实服务器”的映射关系
- 在内存中创建一个
- 修改数据包(DNAT/MAC):
- 根据工作模式(NAT、DR、TUN),修改数据包的目标 IP 或 MAC 地址,将其指向选中的真实服务器
- 重定向:
- 修改完后,它通常返回
NF_STOLEN,告诉内核“这个包我接管了,别再往下传了”,并将其推向转发流程
- 修改完后,它通常返回
- 检查连接(Connection Lookup):
ip_vs_out() —— 响应处理函数
- 挂载点:
NF_INET_FORWARD - 触发时机:当真实服务器处理完请求,返回响应包,且该数据包流经 LVS 时触发
- 注意:在 DR 模式下,响应包直接回客户端,不经过此函数;此函数主要在 NAT 模式下起作用。
- 核心作用:
- 查找连接:
- 根据响应包的五元组(源 IP、源端口、目标 IP、目标端口、协议),在连接表中找到对应的
ip_vs_conn记录
- 根据响应包的五元组(源 IP、源端口、目标 IP、目标端口、协议),在连接表中找到对应的
- 源地址转换(SNAT):
- 这是最关键的一步。它会将响应包的源 IP(真实服务器 IP)修改为虚拟 IP(VIP)
- 这样,客户端收到的包看起来就是 VIP 发回来的,从而实现了负载均衡的透明性
- 状态更新:
- 更新连接的状态(如 TCP 序列号),确保连接跟踪的准确性
- 查找连接:
ip_vs_post_routing() —— 最后的关卡
- 挂载点:
NF_INET_POST_ROUTING - 触发时机:数据包即将离开网卡,发送到物理网络之前的最后一刻
- 核心作用:
- 防止规则冲突:
- 它的主要任务是确保经过 IPVS 处理过的数据包,不再被 iptables 的 NAT 规则重复处理
- 如果没有这个函数,iptables 可能会再次修改已经被 IPVS 修改过的地址,导致网络错乱
- 快速放行:
- 它会检查数据包是否带有 IPVS 的标记。如果有,直接返回
NF_ACCEPT或NF_STOLEN,让数据包迅速通过,不再进行复杂的防火墙规则匹配,提高转发效率
- 它会检查数据包是否带有 IPVS 的标记。如果有,直接返回
- 防止规则冲突:
请求包流程(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() - 动作:
- 拦截:IPVS 模块在 INPUT 链上注册了钩子,它比普通的 TCP/IP 协议栈更早拿到数据包。
- 匹配:检查数据包的目标 IP:Port(VIP:80)是否在 IPVS 的服务列表中。
- 调度:如果是新连接,根据算法(如轮询)选一台真实服务器(RS)。
- 修改(关键):
- NAT 模式:修改目标 IP 为 RS 的 IP(DNAT)。
- DR 模式:修改目标 MAC 地址为 RS 的 MAC。
- 连接跟踪:在 Conntrack 表中建立一条记录,标记这个连接将来需要怎么处理回包。
- 重定向: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() - 动作:
- 识别:IPVS 检查数据包的五元组,发现这个包属于之前建立的那个连接(通过 Conntrack 表匹配)。
- 还原(SNAT):IPVS 将数据包的源 IP 从 RS 的 IP(RIP)修改回 VIP。
- 目的:让客户端觉得是 VIP 给它回的包,而不是 RS。
- 流向:修改完成后,数据包继续向前,进入
POSTROUTING。
3. POSTROUTING 链:离场
- Hook 函数:
ip_vs_post_routing() - 动作:
- 同样,这里的作用是防止被 iptables 的其他规则干扰。
- 确认数据包已经完成 SNAT,允许其离开网卡。
- 流向:数据包发往互联网,最终回到客户端(CIP)。

LVS 工作模式
DR 直接路由
请求经过负载均衡器,响应直接返回给客户端
前提条件:
- LVS 和 RS 在同一物理网段内(可以通过修改 MAC 下一跳直达的前提)
- LVS 和 RS 同时配置 VIP(RS 可以接收目的 IP 为 VIP 包的前提)
转发流程:
- 请求阶段
- 源/目的 IP 保持不变,源 IP 为客户端 IP(CIP),目的 IP 为 VIP
- 通过修改目的 MAC 地址,将下一跳规定为同一物理网段内的 RS 节点
- 响应阶段
- 不返回 LVS,直接返回到客户端
- 源 IP 为 VIP,目的 IP 为 客户端 IP(CIP)
优点:
- 高性能,LVS 不用处理响应,负载降低一半
- IP 透明,RS 可以拿到客户端 IP(CIP)
缺点:
- 不支持端口映射,转发只能相同端口
- 强制要求 LVS 和 RS 在同一物理网段内
- 强制要求每台 RS 上配置 VIP 和 ARP 抑制
