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

【网络工程】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 框架的 INPUTFORWARD 链上。与 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 .