土法炼钢兴趣小组的算法知识备份

【网络工程】L4 负载均衡:IPVS、LVS 与连接级调度

文章导航

分类入口
network
标签入口
#load-balancing#ipvs#lvs#keepalived#linux

目录

L4 负载均衡工作在传输层(Transport Layer),以 TCP 连接或 UDP 数据报为调度单位,不解析应用层协议。它的核心优势是性能——不需要解析 HTTP 报文,不需要 TLS 终止,转发路径短,单机可以轻松处理百万级并发连接。

L4 和 L7 负载均衡不是替代关系,而是互补关系。典型架构是 L4 LB 在前(处理连接级调度和高可用),L7 LB 在后(处理请求级路由和内容交换)。本文聚焦 L4 层的工程实现。

一、IPVS 内核实现

1.1 IPVS 的位置

IPVS(IP Virtual Server)是 Linux 内核中的 L4 负载均衡模块,工作在 netfilter 框架的 INPUT 和 FORWARD 链上。与 iptables 的 DNAT 方式相比,IPVS 使用哈希表存储转发规则,查找时间复杂度为 O(1),在大量规则下性能优势显著:

特性 iptables DNAT IPVS
规则查找 O(n),遍历链 O(1),哈希表
调度算法 无内置 10+ 种算法
连接追踪 依赖 conntrack 内置连接表
1000 规则时性能 明显下降 无影响
10000 规则时性能 严重下降 无影响
持久连接支持 需要额外配置 内置

这就是为什么 Kubernetes 从 iptables 模式迁移到 IPVS 模式——当 Service 数量达到数千个时,iptables 的规则遍历成为性能瓶颈。

1.2 IPVS 基本操作

# 加载 IPVS 模块
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh

# 确认模块加载
lsmod | grep ip_vs

# 创建虚拟服务
ipvsadm -A -t 10.0.1.100:80 -s rr
# -A: Add virtual service
# -t: TCP (用 -u 表示 UDP)
# -s: 调度算法 (rr = Round Robin)

# 添加真实服务器(Real Server)
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.10:80 -m
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.11:80 -m
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.12:80 -m
# -r: Real server 地址
# -m: Masquerading (NAT 模式)
# -g: Direct Routing (DR 模式)
# -i: IP Tunneling (TUN 模式)

# 查看当前配置
ipvsadm -Ln
# IP Virtual Server version 1.2.1 (size=4096)
# Prot LocalAddress:Port Scheduler Flags
#   -> RemoteAddress:Port       Forward Weight ActiveConn InActConn
# TCP  10.0.1.100:80 rr
#   -> 10.0.2.10:80             Masq    1      23         45
#   -> 10.0.2.11:80             Masq    1      21         42
#   -> 10.0.2.12:80             Masq    1      25         48

# 查看连接表
ipvsadm -Lnc | head -10

# 查看统计
ipvsadm --stats

# 删除真实服务器
ipvsadm -d -t 10.0.1.100:80 -r 10.0.2.10:80

# 删除虚拟服务
ipvsadm -D -t 10.0.1.100:80

# 清空所有规则
ipvsadm -C

1.3 IPVS 的数据路径

理解 IPVS 的内核数据路径有助于排查问题。入站数据包的处理流程:

网卡接收 → NIC Driver → NAPI/softirq
  → ip_rcv()                    # IP 层接收
  → ip_local_deliver()          # 目标是本机
  → NF_INET_LOCAL_IN            # netfilter LOCAL_IN 钩子
  → ip_vs_in()                  # IPVS 拦截入站包
    → ip_vs_service_find()      # 哈希查找虚拟服务 O(1)
    → ip_vs_schedule()          # 调度算法选择 RS
    → ip_vs_conn_new()          # 创建连接记录
    → packet_xmit()             # 按模式转发(NAT/DR/TUN)

IPVS 在连接表中维护每个连接的状态。后续同一连接的数据包直接查表转发,不再经过调度算法:

# 查看连接表(含定时器信息)
ipvsadm -Lnc --sort
# pro expire   state       source              virtual             destination
# TCP 14:57    ESTABLISHED 192.168.1.10:43210  10.0.1.100:80       10.0.2.10:80
# TCP 01:23    TIME_WAIT   192.168.1.11:55432  10.0.1.100:80       10.0.2.11:80
# TCP 00:45    SYN_RECV    192.168.1.12:60001  10.0.1.100:80       10.0.2.12:80

# 连接表大小配置
sysctl -w net.ipv4.vs.conn_tab_bits=20  # 连接表哈希桶 2^20 = 1M
# 重新编译 IPVS 模块后生效,或在模块加载时指定:
# modprobe ip_vs conn_tab_bits=20

1.4 IPVS 与 conntrack 的关系

IPVS 有自己的连接追踪表,与 netfilter 的 conntrack 是独立的。同时启用两者会带来性能开销和潜在冲突:

# 查看 IPVS 是否启用了 conntrack
sysctl net.ipv4.vs.conntrack
# 0 = 不使用 conntrack(推荐,性能更好)
# 1 = 使用 conntrack(某些场景需要,如 FTP 被动模式)

# 如果关闭 conntrack,以下功能不可用:
# - iptables 的 -m state/conntrack 匹配
# - NAT 模式的 SNAT(某些内核版本)
# - FTP/SIP 等需要连接跟踪帮助的协议

二、三种转发模式

2.1 NAT 模式(Masquerading)

NAT 模式是最容易理解和部署的模式。LVS 修改请求包的目标 IP 为真实服务器 IP,修改响应包的源 IP 为 VIP:

客户端 → [src=C, dst=VIP] → LVS → [src=C, dst=RS] → Real Server
客户端 ← [src=VIP, dst=C] ← LVS ← [src=RS, dst=C] ← Real Server

配置:

# LVS 机器配置
# 1. 启用 IP 转发
sysctl -w net.ipv4.ip_forward=1

# 2. 配置 VIP
ip addr add 10.0.1.100/32 dev eth0

# 3. 创建 IPVS 服务(NAT 模式)
ipvsadm -A -t 10.0.1.100:80 -s wrr
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.10:80 -m -w 3
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.11:80 -m -w 2
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.12:80 -m -w 1
# -w: 权重

# Real Server 配置
# 默认网关必须指向 LVS 的内网 IP
ip route add default via 10.0.2.1  # LVS 的内网 IP

NAT 模式的优缺点:

优势 劣势
部署简单,RS 无需特殊配置 LVS 是流量瓶颈(所有流量经过)
RS 可以在不同子网 性能受限于 LVS 的带宽和处理能力
RS 可以是任意 OS 响应包大于请求包时放大明显
支持端口映射 大规模部署不适合

2.2 DR 模式(Direct Routing)

DR 模式是生产环境最常用的模式。LVS 修改请求包的目标 MAC 地址为真实服务器的 MAC,但不修改 IP 地址。响应包直接从 RS 发回客户端,不经过 LVS:

客户端 → [src=C, dst=VIP] → LVS → [src=C, dst=VIP, MAC=RS] → Real Server
客户端 ← [src=VIP, dst=C] ←————————————————————————————————── Real Server

配置:

# LVS 机器配置
ip addr add 10.0.1.100/32 dev eth0
ipvsadm -A -t 10.0.1.100:80 -s wrr
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.10:80 -g -w 1
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.11:80 -g -w 1

# Real Server 配置(每台 RS 都需要)
# 1. 在 lo 上配置 VIP(不对外广播 ARP)
ip addr add 10.0.1.100/32 dev lo

# 2. 抑制 ARP 响应(关键!否则会导致 IP 冲突)
sysctl -w net.ipv4.conf.lo.arp_ignore=1
sysctl -w net.ipv4.conf.lo.arp_announce=2
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2

arp_ignore 和 arp_announce 的含义:

DR 模式的优缺点:

优势 劣势
响应不经过 LVS,吞吐量高 RS 必须在同一 L2 广播域
LVS 只处理入站流量 RS 需要配置 VIP 和 ARP 抑制
性能接近线速 不支持端口映射
适合大规模部署 配置比 NAT 复杂

2.3 TUN 模式(IP Tunneling)

TUN 模式用 IP-in-IP 隧道封装请求包,允许 RS 在不同的物理网络中:

客户端 → [src=C, dst=VIP] → LVS → [outer: src=LVS, dst=RS][inner: src=C, dst=VIP] → RS
客户端 ← [src=VIP, dst=C] ←────────────────────────────────────────────────────── RS
# LVS 配置
ipvsadm -A -t 10.0.1.100:80 -s rr
ipvsadm -a -t 10.0.1.100:80 -r 10.0.2.10:80 -i
ipvsadm -a -t 10.0.1.100:80 -r 10.0.3.10:80 -i  # 不同子网的 RS

# RS 配置
# 1. 启用 tunl0 接口
ip tunnel add tunl0 mode ipip
ip link set tunl0 up

# 2. 在 tunl0 上配置 VIP
ip addr add 10.0.1.100/32 dev tunl0

# 3. ARP 抑制
sysctl -w net.ipv4.conf.tunl0.arp_ignore=1
sysctl -w net.ipv4.conf.tunl0.arp_announce=2

# 4. 关闭反向路径过滤(否则隧道包会被丢弃)
sysctl -w net.ipv4.conf.tunl0.rp_filter=0

2.4 三种模式对比

特性 NAT DR TUN
响应路径 经过 LVS 直接回客户端 直接回客户端
LVS 瓶颈 入站+出站 仅入站 仅入站
RS 网络要求 任意(默认网关指向 LVS) 同一 L2 广播域 任意(支持隧道)
RS 配置 最简单 需要 VIP + ARP 需要隧道 + VIP
端口映射 支持 不支持 不支持
性能 受 LVS 带宽限制 接近线速 隧道封装有开销
典型场景 小规模、需要端口映射 同机房大规模部署 跨机房/跨地域

生产环境推荐:同机房用 DR 模式,跨机房用 TUN 模式,测试环境用 NAT 模式。

三、调度算法

3.1 算法分类

IPVS 支持的调度算法分为两类:

静态算法(不考虑服务器当前负载):

算法 代码 原理 适用场景
Round Robin rr 轮询 服务器性能一致
Weighted Round Robin wrr 加权轮询 服务器性能不同
Source Hashing sh 源 IP 哈希 需要会话保持
Destination Hashing dh 目标 IP 哈希 缓存代理场景

动态算法(考虑服务器当前负载):

算法 代码 原理 适用场景
Least Connection lc 最少连接 长连接场景
Weighted Least Connection wlc 加权最少连接 性能不同 + 长连接
Shortest Expected Delay sed 最短预期延迟 延迟敏感
Never Queue nq 永不排队 低延迟要求

3.2 算法选择指南

你的场景是什么?
  │
  ├── 所有 RS 性能相同?
  │    ├── 是 → 短连接/无状态 → rr
  │    │         长连接/有状态 → lc
  │    └── 否 → 短连接/无状态 → wrr
  │              长连接/有状态 → wlc (推荐默认选择)
  │
  └── 需要会话保持?
       ├── 是 → sh (源 IP 哈希)
       │         或使用 persistence (持久连接)
       └── 否 → 参考上面的选择

实战建议:默认使用 wlc(加权最少连接)。它在大多数场景下表现最好——既考虑了服务器的权重差异,又考虑了当前负载。只在特殊需求时切换其他算法。

3.3 持久连接(Persistence)

持久连接让来自同一客户端的请求在指定时间内始终被调度到同一 RS:

# 创建持久连接服务(300 秒超时)
ipvsadm -A -t 10.0.1.100:80 -s wlc -p 300

# 查看持久连接状态
ipvsadm -Lnc | grep ASSURED

# 持久连接与 sh 算法的区别:
# sh: 基于源 IP 哈希,RS 变化时全部重新映射
# persistence: 基于连接表,超时后重新调度,更灵活

3.4 Weighted Least Connection 算法详解

wlc 是最常用的算法,理解其调度逻辑有助于预测行为:

选择 RS 的标准:overhead = (ActiveConn * 256 + InactiveConn) / Weight

选择 overhead 最小的 RS。

示例:
RS1: ActiveConn=10, InactiveConn=20, Weight=3
  overhead = (10*256 + 20) / 3 = 859
  
RS2: ActiveConn=8, InactiveConn=50, Weight=2
  overhead = (8*256 + 50) / 2 = 1049

RS3: ActiveConn=15, InactiveConn=10, Weight=5
  overhead = (15*256 + 10) / 5 = 770  ← 最小,选择 RS3
# 实时观察调度效果
watch -n 1 'ipvsadm -Ln --thresholds'

# 修改权重(不中断服务)
ipvsadm -e -t 10.0.1.100:80 -r 10.0.2.10:80 -g -w 5

# 优雅下线(权重设为 0,不再分配新连接)
ipvsadm -e -t 10.0.1.100:80 -r 10.0.2.10:80 -g -w 0
# 已有连接继续处理,新连接不会被调度到这个 RS

# 确认所有连接结束后再移除
while ipvsadm -Lnc | grep "10.0.2.10:80" | grep -q ESTABLISHED; do
    echo "等待连接排空..."
    sleep 5
done
ipvsadm -d -t 10.0.1.100:80 -r 10.0.2.10:80

四、Keepalived 高可用

4.1 Keepalived 架构

LVS 本身是单点。Keepalived 解决两个问题:LVS 的高可用(VRRP)和 RS 的健康检查。

                    VIP: 10.0.1.100
                    ┌──────────────┐
                    │   VRRP VIP   │
                    │   漂移地址    │
                    └──────┬───────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        ┌─────┴─────┐ ┌───┴─────┐     │
        │ LVS Master│ │LVS Backup│     │
        │ Keepalived│ │Keepalived│     │
        │ PRIORITY  │ │PRIORITY  │     │
        │   100     │ │   90     │     │
        └─────┬─────┘ └────┬────┘     │
              │             │          │
        ┌─────┴─────────────┴──────────┴──┐
        │         Real Servers             │
        │  RS1      RS2       RS3         │
        └─────────────────────────────────┘

4.2 Keepalived 配置

! /etc/keepalived/keepalived.conf — Master 节点

global_defs {
    router_id LVS_MASTER
    vrrp_skip_check_adv_addr
    vrrp_garp_interval 0
    vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100          # Master 优先级高
    advert_int 1          # VRRP 通告间隔(秒)

    authentication {
        auth_type PASS
        auth_pass Str0ngP@ss
    }

    virtual_ipaddress {
        10.0.1.100/32 dev eth0
    }

    track_script {
        chk_health
    }
}

vrrp_script chk_health {
    script "/usr/local/bin/check_lvs.sh"
    interval 2
    weight -20            # 检查失败则优先级 -20
    fall 3                # 连续失败 3 次才判定故障
    rise 2                # 连续成功 2 次才判定恢复
}

virtual_server 10.0.1.100 80 {
    delay_loop 5          # 健康检查间隔
    lb_algo wlc           # 调度算法
    lb_kind DR            # 转发模式
    persistence_timeout 300
    protocol TCP

    real_server 10.0.2.10 80 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }

    real_server 10.0.2.11 80 {
        weight 2
        HTTP_GET {
            url {
                path /health
                status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }

    real_server 10.0.2.12 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }
}

Backup 节点配置只需修改两行:

state BACKUP
priority 90

4.3 健康检查脚本

#!/bin/bash
# /usr/local/bin/check_lvs.sh
# 检查 IPVS 服务是否正常

# 检查 ipvsadm 进程
if ! ipvsadm -Ln >/dev/null 2>&1; then
    exit 1
fi

# 检查至少有一个 RS 可用
RS_COUNT=$(ipvsadm -Ln | grep -c "->")
if [ "$RS_COUNT" -eq 0 ]; then
    exit 1
fi

exit 0

4.4 故障切换测试

# Master 节点上
# 1. 查看 VIP 状态
ip addr show | grep 10.0.1.100

# 2. 模拟 Master 故障
systemctl stop keepalived

# 3. 在 Backup 节点上确认 VIP 漂移
ip addr show | grep 10.0.1.100
# 10.0.1.100/32 scope global eth0  ← VIP 已漂移到 Backup

# 4. 恢复 Master
systemctl start keepalived
# VIP 自动漂移回 Master(因为优先级更高)

# 5. 如果不想抢占(避免频繁切换)
# 在 Master 配置中添加:
# nopreempt

五、云环境中的 L4 负载均衡

5.1 云 NLB 的实现原理

云厂商的网络负载均衡器(NLB / CLB)本质上也是 L4 LB,但实现方式不同:

特性 传统 LVS 云 NLB
部署形态 物理/虚拟机 全托管服务
高可用 手动配 Keepalived 内置多 AZ 冗余
扩展性 手动扩容 自动扩展
健康检查 Keepalived/自定义 内置多种检查
连接数 受单机限制 数百万级
固定 IP 需要 VIP 弹性 IP / Anycast

5.2 Kubernetes 中的 MetalLB

在裸金属 Kubernetes 集群中,MetalLB 提供 L4 负载均衡能力:

# MetalLB 配置 — L2 模式
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: production-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.0.1.200-10.0.1.250

---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2-advert
  namespace: metallb-system
spec:
  ipAddressPools:
  - production-pool
# 使用 MetalLB 的 Service
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

MetalLB 的 L2 模式本质上类似 LVS 的 DR 模式——一个节点持有 VIP,用 ARP 通告 VIP 的 MAC 地址。BGP 模式则通过 BGP 协议向路由器通告 VIP,支持真正的 ECMP(等价多路径)负载均衡。

5.3 IPVS 在 Kubernetes 中的角色

Kubernetes kube-proxy 的 IPVS 模式将每个 ClusterIP Service 配置为一个 IPVS 虚拟服务,Pod IP 作为 RS:

# 查看 kube-proxy 的 IPVS 规则
ipvsadm -Ln | head -20
# TCP  10.96.0.1:443 rr
#   -> 192.168.1.10:6443    Masq    1      0          0
#   -> 192.168.1.11:6443    Masq    1      0          0
# TCP  10.96.0.10:53 rr
#   -> 10.244.0.5:53        Masq    1      0          0
#   -> 10.244.0.6:53        Masq    1      0          0

# kube-proxy IPVS 使用 NAT 模式(Masq)
# 因为 Pod IP 在不同节点的不同子网,无法使用 DR 模式

# kube-proxy 的 IPVS 配置参数
# --proxy-mode=ipvs
# --ipvs-scheduler=rr          # 默认 rr,可改为 lc/wrr/wlc/sh 等
# --ipvs-min-sync-period=0
# --ipvs-sync-period=30s

从 iptables 模式切换到 IPVS 模式的性能改善:

Service 数量 iptables 规则条数 IPVS 规则条数 Service 创建延迟
100 ~2,000 100 差异不大
1,000 ~20,000 1,000 iptables 慢 3-5x
5,000 ~100,000 5,000 iptables 慢 10-20x
10,000 ~200,000 10,000 iptables 慢 30x+

5.4 完整部署脚本

以下是一个完整的 LVS DR 模式 + Keepalived 部署脚本:

#!/bin/bash
# deploy_lvs_dr.sh — 部署 LVS DR 模式
# 用法: ./deploy_lvs_dr.sh [master|backup|rs]

VIP="10.0.1.100"
LVS_MASTER_IP="10.0.2.1"
LVS_BACKUP_IP="10.0.2.2"
RS_IPS=("10.0.2.10" "10.0.2.11" "10.0.2.12")
PORT=80

case "$1" in
  master|backup)
    # 安装依赖
    apt-get update && apt-get install -y ipvsadm keepalived

    # 加载内核模块
    for mod in ip_vs ip_vs_rr ip_vs_wrr ip_vs_wlc ip_vs_sh; do
        modprobe $mod
    done

    # 写入模块自动加载
    cat > /etc/modules-load.d/ipvs.conf << 'EOF'
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_wlc
ip_vs_sh
EOF

    # 启用 IP 转发
    sysctl -w net.ipv4.ip_forward=1
    echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-lvs.conf

    # 生成 Keepalived 配置
    if [ "$1" = "master" ]; then
        STATE="MASTER"
        PRIORITY=100
    else
        STATE="BACKUP"
        PRIORITY=90
    fi

    cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
    router_id LVS_${STATE}
}

vrrp_instance VI_1 {
    state ${STATE}
    interface eth0
    virtual_router_id 51
    priority ${PRIORITY}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass LVS_S3cret
    }
    virtual_ipaddress {
        ${VIP}/32 dev eth0
    }
}

virtual_server ${VIP} ${PORT} {
    delay_loop 5
    lb_algo wlc
    lb_kind DR
    persistence_timeout 60
    protocol TCP
EOF

    for rs in "${RS_IPS[@]}"; do
        cat >> /etc/keepalived/keepalived.conf << EOF

    real_server ${rs} ${PORT} {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }
EOF
    done

    echo "}" >> /etc/keepalived/keepalived.conf

    systemctl enable --now keepalived
    echo "LVS ${STATE} 配置完成"
    ;;

  rs)
    # Real Server 配置
    # 在 lo 上配置 VIP
    ip addr add ${VIP}/32 dev lo 2>/dev/null

    # ARP 抑制
    cat > /etc/sysctl.d/99-lvs-rs.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 /etc/sysctl.d/99-lvs-rs.conf

    # 持久化 VIP 配置
    cat > /etc/network/interfaces.d/lo-vip << EOF
auto lo:0
iface lo:0 inet static
    address ${VIP}
    netmask 255.255.255.255
EOF

    echo "Real Server 配置完成"
    ;;

  *)
    echo "用法: $0 [master|backup|rs]"
    exit 1
    ;;
esac

六、IPVS 监控与排查

6.1 关键指标

# 连接统计
ipvsadm --stats
# IP Virtual Server version 1.2.1 (size=4096)
# Prot LocalAddress:Port     Conns   InPkts  OutPkts  InBytes OutBytes
# TCP  10.0.1.100:80         12345   678900  234500   56.7M   123.4M

# 速率统计
ipvsadm --rate
# Prot LocalAddress:Port     CPS      InPPS    OutPPS   InBPS    OutBPS
# TCP  10.0.1.100:80         234      5678     1234     2.3M     5.6M

# 连接表大小
ipvsadm -Lnc | wc -l

# IPVS 内核参数
sysctl -a | grep ipvs

# 关键参数调优
sysctl -w net.ipv4.vs.conn_reuse_mode=1      # 连接复用
sysctl -w net.ipv4.vs.expire_nodest_conn=1    # RS 移除时清理连接
sysctl -w net.ipv4.vs.conntrack=0             # 不使用 conntrack(提升性能)

6.2 常见问题排查

问题 1:DR 模式下 RS 收不到请求

# 检查 RS 上的 VIP 配置
ip addr show lo | grep 10.0.1.100

# 检查 ARP 抑制
sysctl net.ipv4.conf.lo.arp_ignore    # 应该是 1
sysctl net.ipv4.conf.lo.arp_announce  # 应该是 2

# 检查 LVS 和 RS 是否在同一 L2 域
arping -c 1 -I eth0 10.0.2.10

问题 2:连接不均衡

# 查看各 RS 的连接数
ipvsadm -Ln
# 如果某个 RS 连接数远超其他,检查:
# 1. 权重设置是否正确
# 2. 是否启用了 persistence(导致某些客户端固定到某个 RS)
# 3. 算法是否合适(rr 可能因为长连接不均衡,换成 lc/wlc)

问题 3:VIP 切换后连接中断

# DR/TUN 模式下,VIP 切换不影响已建立的连接(因为响应不经过 LVS)
# NAT 模式下,VIP 切换会导致所有连接中断

# 解决方案 1:使用 conntrackd 同步连接表
# Master 和 Backup 之间同步 IPVS 连接状态

# 解决方案 2:使用 IPVS 连接同步功能
# Master 配置
ipvsadm --start-daemon master --mcast-interface eth0
# Backup 配置
ipvsadm --start-daemon backup --mcast-interface eth0
# 通过组播同步连接表,切换后已有连接可以继续服务

问题 4:NAT 模式下 RS 回包不经过 LVS

# 确认 RS 的默认路由指向 LVS
ip route show | grep default
# default via 10.0.2.1 dev eth0  ← 必须是 LVS 的内网 IP

# 如果 RS 有多个网卡,检查策略路由
ip rule show
ip route show table main

6.3 Prometheus 监控指标采集

# 使用 ipvs_exporter 或直接从 /proc 读取
cat /proc/net/ip_vs_stats_percpu

# 关键监控指标
# 1. 每秒新建连接数 (CPS)
# 2. 当前活跃连接数
# 3. 各 RS 的连接分布
# 4. 入站/出站流量

# 简易采集脚本
#!/bin/bash
# ipvs_metrics.sh — 输出 Prometheus 格式指标
echo "# HELP ipvs_connections_total Total IPVS connections"
echo "# TYPE ipvs_connections_total counter"
ipvsadm --stats -n | awk '/->/{
    split($2,a,":");
    printf "ipvs_connections_total{rs=\"%s\",port=\"%s\"} %d\n", a[1], a[2], $3
}'

echo "# HELP ipvs_active_connections Current active connections"
echo "# TYPE ipvs_active_connections gauge"
ipvsadm -Ln | awk '/->/{
    split($2,a,":");
    printf "ipvs_active_connections{rs=\"%s\",port=\"%s\"} %d\n", a[1], a[2], $5
}'

七、总结:L4 负载均衡的工程选择

  1. DR 模式是同机房的首选。响应不经过 LVS,吞吐量几乎等于所有 RS 的带宽之和。唯一的要求是 LVS 和 RS 在同一 L2 广播域。

  2. wlc 是默认算法。加权最少连接在大多数场景下表现最好——既能处理性能不同的服务器,又能根据当前负载动态调度。只在明确有特殊需求时才换算法。

  3. Keepalived 是 LVS 高可用的标准方案。VRRP 实现 VIP 漂移,健康检查实现 RS 自动摘除和恢复。生产环境必须至少两台 LVS 节点。

  4. 云环境优先用托管 NLB。除非有特殊需求(成本控制、自定义调度),否则使用云厂商的 NLB 服务——它解决了高可用、扩展性和运维负担。

  5. L4 和 L7 配合使用。典型架构是 L4 LB 在前做连接级调度和 DDoS 防护,L7 LB 在后做请求级路由和 TLS 终止。两层各司其职,不要试图用一层解决所有问题。


参考文献


上一篇:BPF 网络诊断:bpftrace 与 bcc 工具实战

下一篇:L7 负载均衡:HTTP 感知路由与内容交换

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2025-08-31 · network

【网络工程】HAProxy 工程:高级配置、ACL 与运维

系统讲解 HAProxy 的工程实践:Frontend/Backend/Listen 配置模型、ACL 规则引擎的高级用法、Runtime API 的动态管理能力、多线程模型与性能调优、SSL 终止与健康检查策略,建立 HAProxy 从配置到生产运维的完整体系。

2025-08-20 · network

【网络工程】负载均衡算法深度解析:从轮询到 P2C

系统讲解负载均衡算法的数学原理与工程实现:Round Robin 及加权变体、Least Connection 及其局限、一致性哈希在 LB 中的应用、P2C(Power of Two Choices)的概率优势,以及真实负载下的算法性能对比与选型。


By .