文章

LACP 链路聚合技术详解

LACP 链路聚合技术

在 GPU 裸金属服务器和数据中心网络中,单条网卡的带宽和可靠性都不够。LACP(Link Aggregation Control Protocol)将多条物理链路捆绑为一条逻辑链路,实现带宽叠加链路冗余负载分担——这是裸金属服务器网络配置的基石。

概述

链路聚合(Link Aggregation)是将多个物理网络接口合并为一个逻辑接口的技术。LACP(Link Aggregation Control Protocol,链路聚合控制协议)是 IEEE 802.3ad 标准定义的协商协议,用于两端设备自动协商聚合组的形成和成员状态。

在 GPU 集群中,链路聚合用于:

  • 管理网络:双网卡 bonding,保证 BMC/SSH 管理通道高可用
  • 存储网络:多条 100GbE 聚合,支撑分布式文件系统的高吞吐
  • 业务网络:多网卡负载分担,提升整体带宽
flowchart LR
    subgraph 服务器侧
        A[eth0<br/>100GbE] 
        B[eth1<br/>100GbE]
        C[eth2<br/>100GbE]
        D[eth3<br/>100GbE]
    end

    A --> LA[bond0<br/>逻辑接口<br/>LACP]
    B --> LA
    C --> LA
    D --> LA

    LA --> SW[交换机聚合组<br/>Port-Channel]

    subgraph 交换机侧
        SW --> P0[端口1]
        SW --> P1[端口2]
        SW --> P2[端口3]
        SW --> P3[端口4]
    end

    P0 -.->|LACPDU 协商| A
    P1 -.->|LACPDU 协商| B
    P2 -.->|LACPDU 协商| C
    P3 -.->|LACPDU 协商| D

    style LA fill:#4a9eff,color:#fff
    style SW fill:#f59e0b,color:#fff

一、LACP 协议原理

1.1 核心概念

概念含义
LAG(Link Aggregation Group)链路聚合组,多个物理端口的集合
Aggregator聚合器,将 LAG 呈现为单一逻辑端口
LACPDULACP 数据单元,两端协商的报文
Actor / Partner本端 / 对端(LACP 协商中的角色命名)
System Priority系统优先级,决定哪端做主动方
Port Priority端口优先级,决定哪些端口被选入活跃组
Operational Key操作密钥,标识聚合组能力(速率/双工)

1.2 LACP 协商流程

sequenceDiagram
    participant S as 服务器 (Actor)
    participant SW as 交换机 (Partner)

    Note over S,SW: 1. 初始状态:两端均未聚合
    S->>SW: LACPDU (Actor: S, Partner: 空, Active)
    SW->>S: LACPDU (Actor: SW, Partner: S, Active)

    Note over S,SW: 2. 交换参数:系统优先级、端口能力
    S->>SW: LACPDU (Key=速率+双工, State=同步中)
    SW->>S: LACPDU (Key=速率+双工, State=同步中)

    Note over S,SW: 3. 参数匹配:速率/双工/Key 一致
    S->>SW: LACPDU (State=已同步, Collecting+Distributing)
    SW->>S: LACPDU (State=已同步, Collecting+Distributing)

    Note over S,SW: 4. 聚合建立:双方开始转发流量
    Note over S,SW: 5. 周期性 LACPDU 保活(默认 30s / 快速 1s)

1.3 LACP 模式

模式行为特点适用场景
Active(主动)主动发送 LACPDU总是尝试建立聚合推荐,两端至少一端 Active
Passive(被动)仅响应 LACPDU等待对方发起谨慎场景,减少误聚合

关键规则:LACP 聚合至少需要一端为 Active 模式。两端都为 Passive 则永远不会建立聚合。

1.4 LACPDU 状态标志

标志位含义
Activity0=Passive, 1=Active
Timeout0=Long(30s), 1=Short(1s)
Aggregation0=Individual, 1=Aggregatable
Synchronization0=未同步, 1=已同步
Collecting0=不接收, 1=接收流量
Distributing0=不发送, 1=发送流量
Default0=使用对端默认值, 1=使用对端配置值
Expired0=未过期, 1=已过期(超时)

二、Linux Bonding 模式

Linux 内核提供 bonding 驱动,支持 7 种模式,其中 Mode 4 对应 LACP。

2.1 七种 Bonding 模式对比

模式名称协议负载分担冗余交换机配置典型场景
0balance-rr轮询无需特殊配置最大带宽,但乱序风险
1active-backup否(主备)无需特殊配置管理网络高可用
2balance-xorXOR hash无需特殊配置确定性分流
3broadcast广播无需特殊配置特殊容错场景
4802.3adLACP需配置 LACP生产推荐
5balance-tlb发送负载无需特殊配置无 LACP 支持时
6balance-alb收发负载无需特殊配置无 LACP 支持时

2.2 Mode 4 (LACP) 详解

flowchart TB
    subgraph "Linux Bonding Mode 4 (802.3ad / LACP)"
        subgraph "发送方向"
            TX[应用数据] --> HASH[流量分发 Hash]
            HASH -->|flow 1| S0[eth0 发送]
            HASH -->|flow 2| S1[eth1 发送]
            HASH -->|flow 3| S2[eth2 发送]
            HASH -->|flow 4| S3[eth3 发送]
        end

        subgraph "接收方向"
            R0[eth0 接收] --> AGG[聚合到 bond0]
            R1[eth1 接收] --> AGG
            R2[eth2 接收] --> AGG
            R3[eth3 接收] --> AGG
        end

        subgraph "LACP 协商"
            L0[eth0 ←→ SW Port1] 
            L1[eth1 ←→ SW Port2]
            L2[eth2 ←→ SW Port3]
            L3[eth3 ←→ SW Port4]
        end
    end

流量分发机制(Hash 策略):

xmit_hash_policy说明分流粒度适用场景
layer2仅用 MAC 地址交换机友好少量主机间通信
layer2+3MAC + IP较均衡推荐,通用场景
layer3+4IP + Port最均衡推荐,高并发场景
encap2+3VLAN + MAC + IP较均衡VLAN 环境
encap3+4VLAN + IP + Port最均衡VLAN + 高并发

关键理解:LACP 不是”单条流量的带宽叠加”。一条 TCP 连接只会走一条物理链路。LACP 提升的是多条并发连接的总带宽。选择 layer3+4 策略可以让不同 TCP/UDP 流分散到不同链路。

三、Linux Bonding 配置

3.1 配置方式一:sysfs + ifcfg(RHEL/CentOS/Rocky)

# ====== 1. 加载 bonding 模块 ======
modprobe bonding
echo "bonding" >> /etc/modules-load.d/bonding.conf

# ====== 2. 配置 bond0 接口 ======
# /etc/sysconfig/network-scripts/ifcfg-bond0
cat > /etc/sysconfig/network-scripts/ifcfg-bond0 << 'EOF'
DEVICE=bond0
NAME=bond0
TYPE=Bond
BONDING_MASTER=yes
IPADDR=10.0.20.100
PREFIX=24
GATEWAY=10.0.20.1
ONBOOT=yes
BOOTPROTO=none
BONDING_OPTS="mode=4 miimon=100 lacp_rate=1 xmit_hash_policy=layer3+4"
# mode=4: LACP (802.3ad)
# miimon=100: 链路监控频率 100ms
# lacp_rate=1: 快速 LACPDU(1秒),默认 0=慢速(30秒)
# xmit_hash_policy=layer3+4: IP+Port 分流
EOF

# ====== 3. 配置成员接口 ======
# /etc/sysconfig/network-scripts/ifcfg-eth0
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << 'EOF'
DEVICE=eth0
NAME=eth0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
EOF

# /etc/sysconfig/network-scripts/ifcfg-eth1
cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << 'EOF'
DEVICE=eth1
NAME=eth1
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
EOF

# ====== 4. 重启网络 ======
nmcli connection reload
nmcli connection up bond0

3.2 配置方式二:nmcli(NetworkManager)

# 创建 bond0 接口
nmcli connection add type bond con-name bond0 ifname bond0 \
  bond.options "mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4"

# 设置 IP
nmcli connection modify bond0 ipv4.addresses 10.0.20.100/24
nmcli connection modify bond0 ipv4.gateway 10.0.20.1
nmcli connection modify bond0 ipv4.method manual

# 添加成员接口
nmcli connection add type ethernet con-name eth0-bond ifname eth0 \
  master bond0
nmcli connection add type ethernet con-name eth1-bond ifname eth1 \
  master bond0

# 激活
nmcli connection up bond0

3.3 配置方式三:Netplan(Ubuntu)

# /etc/netplan/01-bonding.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
    eth1:
      dhcp4: no
    eth2:
      dhcp4: no
    eth3:
      dhcp4: no
  bonds:
    bond0:
      interfaces: [eth0, eth1, eth2, eth3]
      addresses: [10.0.20.100/24]
      routes:
        - to: default
          via: 10.0.20.1
      parameters:
        mode: 802.3ad
        miimon: 100
        lacp-rate: fast
        transmit-hash-policy: layer3+4
sudo netplan apply

3.4 验证 Bond 状态

# 查看 bond 接口概要
cat /proc/net/bonding/bond0

# 预期输出:
# Ethernet Channel Bonding Driver: v3.7.1
# Bonding Mode: IEEE 802.3ad Dynamic link aggregation
# Transmit Hash Policy: layer3+4 (802.3ad Layer 3+4)
# MII Status: up
# MII Polling Interval (ms): 100
# Up Delay (ms): 0
# Down Delay (ms): 0
# 
# 802.3ad info
# LACP rate: fast
# LACPDU Max Rx: 65535
#
# Slave Interface: eth0
# MII Status: up
# Speed: 100000 Mbps
# Duplex: full
# Link Failure Count: 0
# Permanent HW addr: xx:xx:xx:xx:xx:xx
# Slave queue ID: 0
# Aggregator ID: 1
# Actor Churn State: none
# Partner Churn State: none
# Actor System Priority: 65535
# Partner System Priority: 32768
# Actor System: xx:xx:xx:xx:xx:xx
# Partner System: xx:xx:xx:xx:xx:xx
# Actor Key: 9
# Partner Key: 1
# Actor Port State: 63        ← 63=全活跃(Active+Short+Agg+Sync+Coll+Dist)
# Partner Port State: 63

# 查看 LACPDU 统计
ip -s link show bond0

# 查看各成员链路状态
ip link show master bond0

Actor Port State 解码:

标志值=0值=1
0ActivityPassiveActive
1TimeoutLong(30s)Short(1s)
2AggregationIndividualAggregatable
3Synchronization未同步已同步
4Collecting不接收接收
5Distributing不发送发送

63 = 0b111111 = 所有标志位为 1 = 链路完全活跃。如果值为 0b001100 = 28,表示已同步但不收发,说明聚合协商未完成。

四、交换机侧配置

4.1 Cisco(NX-OS / IOS)

# ====== Cisco NX-OS ======
# 进入配置模式
configure terminal

# 创建 Port-Channel
interface port-channel10
  description GPU-Node-01-Bond0
  switchport mode trunk
  switchport trunk allowed vlan 20,30
  spanning-tree port type edge trunk

# 配置成员端口
interface Ethernet1/1
  description GPU-Node-01-eth0
  channel-group 10 mode active      ! active = LACP Active
  no shutdown

interface Ethernet1/2
  description GPU-Node-01-eth1
  channel-group 10 mode active
  no shutdown

interface Ethernet1/3
  description GPU-Node-01-eth2
  channel-group 10 mode active
  no shutdown

interface Ethernet1/4
  description GPU-Node-01-eth3
  channel-group 10 mode active
  no shutdown

# 设置 LACP 快速模式
lacp rate fast interface Ethernet1/1
lacp rate fast interface Ethernet1/2
lacp rate fast interface Ethernet1/3
lacp rate fast interface Ethernet1/4

# 设置 LACP 系统优先级(小的优先)
lacp system-priority 4096

end

# 验证
show port-channel summary
show lacp port-channel 10
show lacp neighbor

4.2 华为 / 华三(VRP / Comware)

# ====== 华为 VRP ======
system-view

# 创建 Eth-Trunk
interface Eth-Trunk10
  description GPU-Node-01-Bond0
  mode lacp-static                    ! 静态 LACP 模式
  trunkport GigabitEthernet 1/0/1 to 1/0/4

# 配置成员端口
interface GigabitEthernet1/0/1
  eth-trunk 10
  lacp priority 100                   ! 端口优先级(小的优先活跃)

interface GigabitEthernet1/0/2
  eth-trunk 10
  lacp priority 200

interface GigabitEthernet1/0/3
  eth-trunk 10
  lacp priority 300

interface GigabitEthernet1/0/4
  eth-trunk 10
  lacp priority 400

# LACP 系统优先级
lacp priority 100

# LACP 超时模式
interface Eth-Trunk10
  lacp timeout fast                   ! 快速超时(3秒)

# 验证
display eth-trunk 10
display lacp verbose

4.3 Mellanox Onyx(Spectrum 交换机)

# Mellanox 交换机常用于 GPU 集群的 RoCE/IB 网络
# ====== Mellanox Onyx ======
enable
configure terminal

# 创建 Port-Channel
interface port-channel 10
  description GPU-Node-01-Bond0
  no shutdown
  exit

# 配置成员端口
interface ethernet 1/1
  channel-group 10 mode active
  no shutdown
  exit

interface ethernet 1/2
  channel-group 10 mode active
  no shutdown
  exit

# LACP 快速模式
interface ethernet 1/1
  lacp rate fast
interface ethernet 1/2
  lacp rate fast

# 验证
show interfaces port-channel 10
show lacp port-channel 10

五、GPU 集群中的链路聚合场景

5.1 三网分离架构

GPU 集群通常采用管理网、存储网、计算网三网分离,每个网络都使用链路聚合。

flowchart TB
    subgraph "GPU 裸金属服务器"
        subgraph "管理网络"
            MGMT0[eth0<br/>1GbE]
            MGMT1[eth1<br/>1GbE]
            MGMT0 --> MB[bond0<br/>active-backup<br/>Mode 1]
            MGMT1 --> MB
        end

        subgraph "存储网络"
            STO0[eth2<br/>25GbE]
            STO1[eth3<br/>25GbE]
            STO0 --> SB[bond1<br/>LACP Mode 4]
            STO1 --> SB
        end

        subgraph "计算网络 (RDMA/RoCE)"
            COMP0[eth4<br/>100GbE]
            COMP1[eth5<br/>100GbE]
            COMP2[eth6<br/>100GbE]
            COMP3[eth7<br/>100GbE]
            COMP0 -.-> CB[bond2<br/>LACP Mode 4<br/>或独立使用]
            COMP1 -.-> CB
            COMP2 -.-> CB
            COMP3 -.-> CB
        end
    end

    MB --> MGMT_SW[管理交换机]
    SB --> STO_SW[存储交换机]
    CB --> COMP_SW[计算交换机<br/>Spine-Leaf]

5.2 各网络 Bonding 策略

网络带宽需求Bonding 模式xmit_hash_policy交换机理由
管理网低 (1GbE)Mode 1 (active-backup)N/A无需 LACP管理流量小,主备足够,避免交换机配置
存储网高 (25-100GbE)Mode 4 (LACP)layer3+4需配 LACP多并发 IO 流需要带宽叠加
计算网极高 (100-400GbE)不 BondingN/A各自独立RDMA/RoCE 要求无损网络,Bonding 会破坏 RoCE PFC/ECN

重要:计算网络(RDMA/RoCE)通常不使用 Bonding!RDMA 需要精确的 PFC(Priority Flow Control)和 ECN 配置,Bonding 的负载分担会打乱流量到端口的映射,导致 PFC 失效。正确做法是每张网卡独立配置 RoCE,由 NCCL 层面做多路径通信。

5.3 管理网络 active-backup 配置

# 管理网络:Mode 1 (active-backup) —— 最简单的冗余方案
# /etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE=bond0
IPADDR=10.0.10.100
PREFIX=24
GATEWAY=10.0.10.1
ONBOOT=yes
BOOTPROTO=none
BONDING_OPTS="mode=1 miimon=100 primary=eth0"
# mode=1: active-backup(主备)
# miimon=100: 100ms 检测链路状态
# primary=eth0: 优先使用 eth0

# 成员接口
# ifcfg-eth0, ifcfg-eth1: MASTER=bond0, SLAVE=yes

5.4 存储网络 LACP 配置

# 存储网络:Mode 4 (LACP) —— 带宽叠加 + 冗余
# /etc/sysconfig/network-scripts/ifcfg-bond1
DEVICE=bond1
IPADDR=10.0.30.100
PREFIX=24
MTU=9000                           # Jumbo Frame,存储网络必备
ONBOOT=yes
BOOTPROTO=none
BONDING_OPTS="mode=4 miimon=100 lacp_rate=1 xmit_hash_policy=layer3+4"
# MTU=9000: 开启巨型帧,提升存储网络吞吐
# 交换机侧需同步开启 Jumbo Frame

六、监控与排障

6.1 Bond 状态监控

# 实时监控 bond 状态(每秒刷新)
watch -n 1 'cat /proc/net/bonding/bond0'

# 监控各成员链路流量
watch -n 1 'ip -s link show master bond0'

# 查看 LACPDU 收发统计
cat /proc/net/bonding/bond0 | grep -A2 "LACP"

6.2 Prometheus 监控指标

# node_exporter 自动采集 bond 接口指标
# 关键指标:
#   node_network_up{device="bond0"}               — bond 接口状态
#   node_network_receive_bytes_total{device="eth0"} — 各成员接收字节
#   node_network_transmit_bytes_total{device="eth1"} — 各成员发送字节
# PromQL: 检查 bond 成员链路是否均衡
# 各成员发送流量
sum(rate(node_network_transmit_bytes_total{device=~"eth[0-3]", instance="gpu-node-01"}[5m])) by (device)

# bond 总流量
rate(node_network_transmit_bytes_total{device="bond0", instance="gpu-node-01"}[5m])

# 成员链路数量(活跃成员数)
count by (instance) (node_network_up{device=~"eth[0-9]+", instance="gpu-node-01"} == 1)
# Alertmanager 告警规则
groups:
- name: bonding
  rules:
  # bond 接口 down
  - alert: BondInterfaceDown
    expr: node_network_up{device=~"bond[0-9]+"} == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "Bond 接口 {{ $labels.device }} 在 {{ $labels.instance }} 上 down"

  # bond 成员减少
  - alert: BondSlaveCountReduced
    expr: count by (instance, device) (node_network_up{device=~"eth[0-9]+"} == 1) < 2
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: "{{ $labels.instance }} bond 成员链路数量减少"
      description: "活跃成员数 < 2,可能存在物理链路故障"

  # bond 成员流量严重不均
  - alert: BondTrafficImbalance
    expr: |
      stddev by (instance) (
        rate(node_network_transmit_bytes_total{device=~"eth[0-9]+"}[5m])
      ) / 
      avg by (instance) (
        rate(node_network_transmit_bytes_total{device=~"eth[0-9]+"}[5m])
      ) > 0.8
    for: 10m
    labels:
      severity: info
    annotations:
      summary: "{{ $labels.instance }} bond 成员流量严重不均"
      description: "标准差/均值 > 0.8,可能 hash 策略不合适或存在单流瓶颈"

6.3 常见故障排查

故障现象可能原因排查步骤解决方案
bond0 状态 down所有成员链路断ip link show bond0检查物理线缆和交换机端口
成员未加入聚合LACP 协商失败检查两端 LACP 模式至少一端设为 Active
成员 Collecting only对端未 Distributing检查交换机 Port-Channel确保交换机侧成员都 active
流量只走一条链路hash 策略不当检查 xmit_hash_policy改用 layer3+4
偶发丢包LACP 超时太长检查 lacp_rate设为 fast(1s)
MTU 不匹配巨型帧配置不一致ip link show 对比两端bond+成员+交换机统一 MTU
MAC 地址冲突bond MAC 来源异常检查 fail_over_mac设置 fail_over_mac=1

6.4 诊断脚本

"""LACP Bond 诊断工具"""

from dataclasses import dataclass, field
import subprocess
import re


@dataclass
class BondSlave:
    interface: str
    mii_status: str           # up / down
    speed: str                # 100000 Mbps
    duplex: str               # full / half
    link_failure_count: int = 0
    aggregator_id: int = 0
    actor_port_state: int = 0
    partner_port_state: int = 0
    lacp_active: bool = False
    lacp_synced: bool = False
    lacp_collecting: bool = False
    lacp_distributing: bool = False


@dataclass
class BondStatus:
    bond_name: str
    bonding_mode: str
    xmit_hash_policy: str
    mii_status: str
    miimon: int = 0
    lacp_rate: str = ""
    slaves: list[BondSlave] = field(default_factory=list)


class BondDiagnostics:
    """Bond/LACP 诊断工具"""

    def get_status(self, bond_name: str = "bond0") -> BondStatus:
        """获取 bond 状态"""
        result = subprocess.run(
            ["cat", f"/proc/net/bonding/{bond_name}"],
            capture_output=True, text=True, timeout=5,
        )
        return self._parse_bond_info(result.stdout, bond_name)

    def diagnose(self, bond_name: str = "bond0") -> dict:
        """执行诊断,返回问题列表"""
        status = self.get_status(bond_name)
        issues = []

        # 1. 检查 bond 接口状态
        if status.mii_status != "up":
            issues.append({
                "severity": "critical",
                "issue": f"{bond_name} 接口状态: {status.mii_status}",
                "action": "检查物理链路和交换机端口",
            })

        # 2. 检查成员数量
        if len(status.slaves) < 2:
            issues.append({
                "severity": "warning",
                "issue": f"{bond_name} 仅有 {len(status.slaves)} 个成员,"
                         f"无冗余保护",
                "action": "添加更多成员接口",
            })

        # 3. 检查各成员状态
        for slave in status.slaves:
            if slave.mii_status != "up":
                issues.append({
                    "severity": "critical",
                    "issue": f"成员 {slave.interface} 链路 down",
                    "action": f"检查 {slave.interface} 物理连接",
                })
                continue

            # 检查 LACP 协商状态
            if status.bonding_mode and "802.3ad" in status.bonding_mode:
                if not slave.lacp_synced:
                    issues.append({
                        "severity": "warning",
                        "issue": f"成员 {slave.interface} LACP 未同步",
                        "action": "检查交换机侧 LACP 配置",
                    })
                if not slave.lacp_collecting:
                    issues.append({
                        "severity": "warning",
                        "issue": f"成员 {slave.interface} 未在接收流量"
                                 f" (Collecting=No)",
                        "action": "检查对端 Distributing 状态",
                    })
                if not slave.lacp_distributing:
                    issues.append({
                        "severity": "warning",
                        "issue": f"成员 {slave.interface} 未在发送流量"
                                 f" (Distributing=No)",
                        "action": "检查对端 Collecting 状态",
                    })
                if slave.link_failure_count > 0:
                    issues.append({
                        "severity": "info",
                        "issue": f"成员 {slave.interface} 有 "
                                 f"{slave.link_failure_count} 次链路故障记录",
                        "action": "关注是否持续增长",
                    })

        # 4. 检查速率一致性
        speeds = set(s.speed for s in status.slaves if s.mii_status == "up")
        if len(speeds) > 1:
            issues.append({
                "severity": "warning",
                "issue": f"成员速率不一致: {speeds}",
                "action": "确保所有成员速率和双工模式一致",
            })

        return {
            "bond_name": bond_name,
            "mode": status.bonding_mode,
            "status": status.mii_status,
            "slaves_count": len(status.slaves),
            "active_slaves": sum(
                1 for s in status.slaves if s.mii_status == "up"
            ),
            "issues": issues,
        }

    def _parse_bond_info(self, output: str, bond_name: str) -> BondStatus:
        """解析 /proc/net/bonding/bondX"""
        status = BondStatus(
            bond_name=bond_name,
            bonding_mode="",
            xmit_hash_policy="",
            mii_status="",
        )

        lines = output.strip().split("\n")
        current_slave: BondSlave = None

        for line in lines:
            line = line.strip()
            if "Bonding Mode:" in line:
                status.bonding_mode = line.split(":", 1)[1].strip()
            elif "Transmit Hash Policy:" in line:
                status.xmit_hash_policy = line.split(":", 1)[1].strip()
            elif "MII Status:" in line:
                value = line.split(":", 1)[1].strip()
                if current_slave is None:
                    status.mii_status = value
                else:
                    current_slave.mii_status = value
            elif "MII Polling Interval" in line:
                status.miimon = int(
                    line.split(":", 1)[1].strip().replace(" ms", "")
                )
            elif "LACP rate:" in line:
                status.lacp_rate = line.split(":", 1)[1].strip()
            elif "Slave Interface:" in line:
                if current_slave:
                    status.slaves.append(current_slave)
                iface = line.split(":", 1)[1].strip()
                current_slave = BondSlave(interface=iface, mii_status="",
                                          speed="", duplex="")
            elif "Speed:" in line and current_slave:
                current_slave.speed = line.split(":", 1)[1].strip()
            elif "Duplex:" in line and current_slave:
                current_slave.duplex = line.split(":", 1)[1].strip()
            elif "Link Failure Count:" in line and current_slave:
                current_slave.link_failure_count = int(
                    line.split(":", 1)[1].strip()
                )
            elif "Aggregator ID:" in line and current_slave:
                current_slave.aggregator_id = int(
                    line.split(":", 1)[1].strip()
                )
            elif "Actor Port State:" in line and current_slave:
                current_slave.actor_port_state = int(
                    line.split(":", 1)[1].strip()
                )
                current_slave.lacp_active = bool(
                    current_slave.actor_port_state & 1
                )
                current_slave.lacp_synced = bool(
                    current_slave.actor_port_state & 8
                )
                current_slave.lacp_collecting = bool(
                    current_slave.actor_port_state & 16
                )
                current_slave.lacp_distributing = bool(
                    current_slave.actor_port_state & 32
                )

        if current_slave:
            status.slaves.append(current_slave)

        return status


# 使用示例
if __name__ == "__main__":
    diag = BondDiagnostics()
    result = diag.diagnose("bond0")
    print(f"Bond: {result['bond_name']}")
    print(f"Mode: {result['mode']}")
    print(f"Status: {result['status']}")
    print(f"Slaves: {result['active_slaves']}/{result['slaves_count']} active")
    print(f"\nIssues ({len(result['issues'])}):")
    for issue in result["issues"]:
        print(f"  [{issue['severity']}] {issue['issue']}")
        print(f"    → {issue['action']}")

七、高级配置

7.1 LACP 速率与超时

参数Long (慢速)Short (快速)推荐
LACPDU 间隔30 秒1 秒Short
超时时间90 秒3 秒Short
故障检测时间最长 90 秒最长 3 秒Short
CPU 开销略高可忽略
适用场景稳定环境生产环境生产必选 Short
# Linux 侧
BONDING_OPTS="mode=4 miimon=100 lacp_rate=1"
# lacp_rate=0: Slow (30s)
# lacp_rate=1: Fast (1s)

# 交换机侧 (Cisco)
lacp rate fast

7.2 LACP 抢占与优先级

当聚合组的活跃成员数受限(如 4 条链路中只允许 2 条活跃),优先级决定哪些链路被选入。

# Linux 侧
BONDING_OPTS="mode=4 miimon=100 lacp_rate=1 ad_select=1"
# ad_select=0: stable(默认,不抢占)
# ad_select=1: bandwidth(链路变化时重新选择)
# ad_select=2: count(链路变化时重新选择并重置计数器)

7.3 VLAN over Bond

# 在 bond 接口上创建 VLAN 子接口
# ifcfg-bond0.20
VLAN=yes
DEVICE=bond0.20
IPADDR=10.0.20.100
PREFIX=24
ONBOOT=yes
BOOTPROTO=none
PHYSDEV=bond0

# ifcfg-bond0.30
VLAN=yes
DEVICE=bond0.30
IPADDR=10.0.30.100
PREFIX=24
ONBOOT=yes
BOOTPROTO=none
PHYSDEV=bond0

7.4 fail_over_mac 策略

策略说明
0none(默认)bond 使用第一个成员的 MAC,切换时不变
1activebond MAC 跟随当前活跃成员的 MAC(适合 active-backup)
2followbond MAC 跟随,但成员使用各自 MAC 发送

在虚拟化/容器环境中,fail_over_mac=1 可以避免 ARP 表混乱。

八、Bonding vs Team vs NIC 独立

特性BondingTeam多 NIC 独立
内核支持内置(bonding.ko)teamd 用户态守护无需配置
LACP 支持✅ Mode 4
热备切换✅ active-backup✅ runner
运行时配置需重启接口D-Bus 动态配置N/A
性能内核态,高用户态,略低最高
推荐度✅ 生产首选逐步被弃用计算/RDMA 网络

建议:生产环境统一使用 bonding(内核态性能最好),避免使用 teamd(已被 Red Hat 标记为弃用)。

九、最佳实践

场景推荐原因
管理网络Mode 1 (active-backup)无需交换机配置,简单可靠
存储网络Mode 4 (LACP) + layer3+4多并发 IO 带宽叠加
RDMA/RoCE 网络不 BondingBonding 破坏 RoCE PFC/ECN
对外服务网络Mode 4 (LACP) + layer3+4高并发流量均衡
LACP 速率lacp_rate=1 (fast)3秒检测故障 vs 90秒
MTU全链路一致避免 Jumbo Frame 不匹配
监控Prometheus + 告警成员减少、流量不均、链路抖动

关联知识

参考资源

  • IEEE 802.3ad-2000 Standard
  • Linux Bonding Documentation: Documentation/networking/bonding.rst
  • Cisco NX-OS Layer 2 Configuration Guide
  • 华为 VRP Eth-Trunk 配置指南
  • Mellanox Spectrum Switch Configuration Guide

学习时间

约 3-4 小时(含实际配置一次 LACP Bonding)

状态

  • 理解 LACP 协议原理和协商流程
  • 掌握 Linux bonding 七种模式
  • 能配置 Mode 4 (LACP) bonding
  • 掌握交换机侧 LACP 配置(Cisco/华为/Mellanox)
  • 理解 GPU 集群中各网络的 Bonding 策略
  • 能监控和排查 LACP 故障
  • 理解 RDMA 网络不 Bonding 的原因
  • 实际配置一次完整的 LACP Bonding
  • 搭建 Prometheus 监控 bond 状态