手撸Linux高性能负载均衡

基于 IPVS 的公网服务多端口转发实践

1. 背景:为什么要“压榨”公网 IP?

在云原生时代,一个公网 IP 地址是极其宝贵的资源。如果我们仅仅为一个 Web 服务占用一个公网 IP,无疑是巨大的浪费。

事实上,除了 80 和 443 端口,一个 IP 理论上可以提供 60000 多个 TCP/UDP 服务。为了提高资源利用率,我们可以利用 Linux 内核强大的转发能力,构建一个全能型的“入口网关”。今天,我们将基于 Ubuntu 20.04,利用内核原生的 IPVS(IP Virtual Server)模块,手撸一个高性能的四层负载均衡器。


2. 实验环境准备

  • 操作系统:Ubuntu 20.04

  • 公网地址1.1.1.1 (绑定在接口 eth0)

  • 内网网段10.0.0.0/24

  • 开放服务范围:TCP/UDP 10000-19999

  • 后端服务 (Real Server)

    • RS1: 10.0.0.1:8080 (权重 2)

    • RS2: 10.0.0.2:8080 (权重 1)


3. 配置过程

Step 1: 开放防火墙端口

假设服务器默认防火墙策略为 DROP,我们首先需要允许外部流量进入我们指定的负载均衡端口区间。

Bash

# 开放 TCP 端口范围
iptables -A INPUT -p tcp -m tcp --dport 10000:19999 -j ACCEPT
# 开放 UDP 端口范围
iptables -A INPUT -p udp -m udp --dport 10000:19999 -j ACCEPT

Step 2: 安装与配置 IPVS

IPVS 是 Linux 内核 LVS (Linux Virtual Server) 的实现,工作在内核态,性能远超处于用户态的普通转发工具。

1. 安装管理工具 ipvsadm

Bash

apt update && apt install ipvsadm -y

2. 配置负载均衡策略: 我们采用 NAT 模式 转发,并使用 加权轮询 (WRR) 算法。

Bash

# 添加虚拟服务 (Virtual Service),监听公网 IP 的 10000 端口,算法为 wrr
ipvsadm -A -t 1.1.1.1:10000 -s wrr

# 添加真实的后端服务器 (Real Server)
# -m 表示 NAT 模式,-w 表示权重
ipvsadm -a -t 1.1.1.1:10000 -r 10.0.0.1:8080 -m -w 2
ipvsadm -a -t 1.1.1.1:10000 -r 10.0.0.2:8080 -m -w 1

Step 3: 配置 SNAT 解决回程路由

在 NAT 模式下,为了确保后端服务器的回程报文能够原路返回给负载均衡器(从而由负载均衡器改写源 IP 并发回客户端),最简单的方法是在负载均衡器上配置 SNAT (Source NAT)

使用 MASQUERADE 自动映射源地址:

Bash

iptables -t nat -A POSTROUTING -d 10.0.0.1/32 -p tcp -m tcp --dport 8080 -j MASQUERADE
iptables -t nat -A POSTROUTING -d 10.0.0.2/32 -p tcp -m tcp --dport 8080 -j MASQUERADE

注意:别忘了开启内核转发功能:sysctl -w net.ipv4.ip_forward=1


4. 流量解析与测试

测试验证

在外部 PC 上通过浏览器或 curl 持续访问:http://1.1.1.1:10000

抓包分析

在负载均衡服务器上运行 tcpdump 或查看 ipvsadm -L -n --stats,你会发现:

  1. 负载分布:流量严格按照 2:1 的比例分配到 10.0.0.110.0.0.2

  2. 地址转换

    • 入向:目的 IP 从 1.1.1.1 被修改为 10.0.x.x (DNAT)。

    • 出向:源 IP 被修改为负载均衡器的内网 IP (SNAT),确保后端 RS 认为请求来自 LB,从而将响应发回 LB。


5. 总结

通过 IPVS + iptables 的组合,我们只用几行命令就实现了一个高性能、工业级的四层负载均衡器。

  • IPVS 负责高效的负载算法分发。

  • iptables 负责辅助的防火墙放行与 SNAT 转换。

这种方案不仅节省了昂贵的公网 IP 资源,还为内部服务提供了一层隔离保护。如果你有大量 TCP/UDP 服务需要映射,这套方案绝对是不二之选。

6. 进阶思考:从“手撸”到自动化负载均衡服务平台

在完成上述手动配置后,我们虽然实现了一个高性能的负载均衡器,但在实际的生产环境中,频繁手动操作 ipvsadmiptables 既低效又容易出错。从产品化角度出发,我们可以将这一过程演化为一个自动化配置平台

6.1 架构设计思路

我们可以开发一个后端应用(推荐使用 Go 或 Python),将其作为控制平面(Control Plane)部署在该服务器上:

  • API 封装:使用 Gin (Go) 或 Flask (Python) 将底层复杂的 Linux 系统调用封装成标准 RESTful API。

    • 例如:POST /v1/loadbalancers 接口,接收 VIP、端口、后端 RS 列表、权重等 JSON 数据。
  • 自动化执行:后端程序通过执行系统命令(如 exec 包)或调用内核接口,自动完成防火墙开放、IPVS 策略下发、SNAT 规则生成的全过程。

  • 配置持久化:将配置信息存储在轻量级数据库(如 SQLite)中,确保服务器重启后,程序能自动重载并恢复所有的负载均衡规则。

6.2 用户体验升级:直观的配置 UI

通过前端(如 Vue 或 React)为用户提供一个极简的控制面板:

  • 表单式填写:用户无需记忆复杂的命令,只需在页面上填写“公网端口”、“内网后端地址”和“分配权重”。

  • 实时监控:前端调用 API 展示 IPVS 的统计数据(ActiveConn, InPackets 等),让负载情况一目了然。

  • 一键伸缩:当需要新增 Real Server 时,用户只需在 UI 上点击“添加”,后台自动毫秒级完成 ipvsadm -a 操作,实现无损扩容。

6.3 这种转变的价值

将繁琐的底层技术细节“黑盒化”,不仅降低了运维门槛,更让这台公网服务器变成了一个具备多租户自服务能力的小型云负载均衡网关。这正是从“运维工程师”向“系统架构师”思维跨越的关键一步。


结语

通过 IPVS + iptables 的组合,辅以现代化的自动化封装,我们不仅能高效利用宝贵的公网 IP 资源,更能构建出一个稳定、可视、易用的工业级四层转发系统。

参考引用

https://linux.die.net/man/8/ipvsadm

更多推荐