網路卡Bonding雙網卡綁定實戰:讓伺服器網路永不中斷


前言

干运维这行十年了,见过太多因为单网卡故障导致的生产事故。记得2019年那会,某电商客户双十一当天,核心交易服务器的网卡突然挂了,整整断网40分钟,直接损失几百万。事后复盘,其实就是一块几十块钱的网卡坏了,但因为没做任何冗余,结果损失惨重。

从那以后,我就把网卡Bonding当成服务器上架的标配操作。这玩意配置起来不复杂,但能在关键时刻救命。今天就把这些年踩过的坑、总结的经验都写出来,希望能帮到同行们少走弯路。

一、Bonding技术概述

1.1 什么是网卡Bonding

简单说,Bonding就是把多块物理网卡绑定成一个逻辑网卡。对上层应用来说,它只看到一个网络接口,但底层实际上有多块网卡在工作。这样做有两个核心好处:

第一是高可用。任何一块物理网卡坏了,流量自动切换到其他网卡,业务无感知。

第二是带宽聚合。多块网卡的带宽可以叠加使用,比如两块千兆网卡绑定后理论上能跑到2Gbps。

Linux内核从2.0版本就开始支持Bonding了,到现在已经非常成熟稳定。2025年的主流发行版,不管是RHEL 9、Ubuntu 24.04还是Debian 12,都对Bonding有完善的支持。

1.2 Bonding的工作原理

Bonding驱动在内核层面工作,它会创建一个虚拟的bond接口,然后把多个物理网卡(称为slave)挂载到这个虚拟接口下面。所有发往bond接口的流量,都会根据配置的模式分发到各个slave网卡上。

从协议栈的角度看,流量是这样走的:

应用程序
    |
TCP/IP协议栈
    |
Bond虚拟接口(bond0)
    |
+---+---+
|       |
eth0   eth1
|       |
物理交换机

Bond接口有自己的MAC地址,默认会使用第一个slave网卡的MAC。当然这个可以手动指定,后面会讲到。

1.3 为什么要用Bonding而不是其他方案

有人可能会问,现在不是有很多高可用方案吗,比如Keepalived、HAProxy这些,为啥还要用Bonding?

这里要搞清楚一点:Bonding解决的是单机网卡层面的冗余,而Keepalived这些解决的是服务层面的冗余。两者不是替代关系,而是互补关系。

举个例子,你用Keepalived做了MySQL主从切换,但如果主库的网卡坏了,Keepalived检测到故障需要时间,切换也需要时间,这期间业务就是中断的。但如果主库本身做了Bonding,网卡坏了流量瞬间切换,Keepalived根本感知不到,业务完全无损。

所以我的建议是:关键业务服务器,Bonding是必须的,在此基础上再叠加服务层面的高可用方案。

二、Bonding模式详解

Linux Bonding支持7种工作模式,编号从0到6。每种模式的特点和适用场景都不一样,选错模式可能达不到预期效果。下面逐个分析。

2.1 Mode 0:balance-rr(轮询模式)

这是最简单的模式,数据包轮流从各个slave网卡发出去。比如第一个包从eth0发,第二个包从eth1发,第三个包又从eth0发,以此类推。

优点:

  • 配置简单,不需要交换机配合
  • 理论上可以实现带宽叠加

缺点:

  • 可能导致数据包乱序,对TCP连接有影响
  • 某些交换机可能因为MAC地址在多个端口出现而产生困惑

适用场景: 说实话,生产环境我几乎不用这个模式。因为数据包乱序的问题在高负载下会很明显,可能导致TCP重传增加,反而降低性能。如果你的场景主要是UDP流量,可以考虑。

2.2 Mode 1:active-backup(主备模式)

这是我用得最多的模式。顾名思义,同一时间只有一块网卡在工作,其他网卡作为备份。主网卡故障时,自动切换到备份网卡。

优点:

  • 配置简单,不需要交换机任何特殊配置
  • 切换速度快,通常在毫秒级
  • 稳定可靠,几乎不会出问题

缺点:

  • 不能实现带宽叠加,同时只用一块网卡的带宽
  • 备份网卡平时闲置,有点浪费

适用场景: 大多数需要高可用但对带宽要求不那么极端的场景。比如数据库服务器、应用服务器、管理网络等。这个模式我推荐作为默认选择,除非有特殊需求。

2.3 Mode 2:balance-xor(异或模式)

这个模式根据源MAC地址和目标MAC地址做异或运算,结果决定用哪块网卡发送。相同的源目地址对,总是走同一块网卡。

优点:

  • 可以实现一定程度的负载均衡
  • 同一个连接的数据包不会乱序

缺点:

  • 需要交换机支持,要配置端口聚合
  • 负载均衡效果取决于连接数,连接少的话可能分布不均

适用场景: 需要负载均衡且交换机支持静态聚合的场景。

2.4 Mode 3:broadcast(广播模式)

所有数据包都从所有slave网卡发送出去。

说实话这个模式我从来没在生产环境用过。它的主要用途是一些特殊的容错场景,比如两块网卡连到两个完全独立的网络,确保数据一定能送达。但这种场景太少见了。

2.5 Mode 4:802.3ad(LACP动态链路聚合)

这是IEEE标准协议,也叫LACP(Link Aggregation Control Protocol)。它需要交换机也支持LACP,双方协商后建立聚合链路。

优点:

  • 标准协议,兼容性好
  • 真正的带宽聚合
  • 自动故障检测和恢复

缺点:

  • 必须交换机支持LACP并正确配置
  • 配置相对复杂
  • 负载均衡效果取决于hash算法和流量模式

适用场景: 对带宽有较高要求,且交换机支持LACP的场景。比如存储服务器、大数据节点、虚拟化宿主机等。这是目前业界用得最多的聚合模式。

2.6 Mode 5:balance-tlb(自适应传输负载均衡)

这个模式比较聪明,它根据每个slave网卡的负载情况动态分配出站流量。负载低的网卡会分配更多流量。

优点:

  • 不需要交换机特殊配置
  • 出站流量可以负载均衡

缺点:

  • 入站流量不能负载均衡,都走主网卡
  • 实现相对复杂,可能有兼容性问题

适用场景: 交换机不支持聚合,但又想实现出站负载均衡的场景。

2.7 Mode 6:balance-alb(自适应负载均衡)

这是Mode 5的增强版,不仅出站流量负载均衡,入站流量也能均衡。它通过ARP协商来实现,会主动修改ARP响应中的MAC地址。

优点:

  • 不需要交换机特殊配置
  • 出入站流量都能负载均衡

缺点:

  • ARP操作可能在某些网络环境下有问题
  • 虚拟化环境下可能不work

适用场景: 物理服务器环境,交换机不支持聚合但需要双向负载均衡。

2.8 模式选择建议

基于这些年的经验,我总结了一个选择流程:

  1. 如果只需要高可用,不需要带宽叠加 -> Mode 1(active-backup)
  2. 如果需要带宽聚合,交换机支持LACP -> Mode 4(802.3ad)
  3. 如果需要带宽聚合,交换机只支持静态聚合 -> Mode 2(balance-xor)
  4. 如果交换机啥都不支持,又想负载均衡 -> Mode 6(balance-alb)

90%的场景,用Mode 1或Mode 4就够了。

三、Bonding配置实战

3.1 环境准备

在开始配置之前,先检查几个前提条件。

确认内核支持Bonding:

# 检查bonding模块
lsmod | grep bonding

# 如果没有加载,手动加载
modprobe bonding

# 查看模块信息
modinfo bonding

在现代Linux发行版上,bonding模块默认都是编译进内核的,一般不需要额外安装。

确认有多块网卡:

# 查看所有网络接口
ip link show

# 或者用老命令
ifconfig -a

# 查看网卡详细信息
ethtool eth0
ethtool eth1

确认网卡连接状态:

# 查看链路状态
ethtool eth0 | grep "Link detected"
ethtool eth1 | grep "Link detected"

# 或者
cat /sys/class/net/eth0/carrier
cat /sys/class/net/eth1/carrier

3.2 RHEL/Rocky/AlmaLinux 9 配置方法

RHEL系从版本8开始推荐使用nmcli(NetworkManager命令行工具)来管理网络。RHEL 9上,传统的network-scripts已经彻底移除了。

3.2.1 使用nmcli配置Mode 1(主备模式)

# 创建bond接口
nmcli connection add type bond \
    con-name bond0 \
    ifname bond0 \
    bond.options "mode=active-backup,miimon=100,primary=ens33"

# 添加第一个slave
nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-slave1 \
    ifname ens33 \
    master bond0

# 添加第二个slave
nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-slave2 \
    ifname ens34 \
    master bond0

# 配置IP地址
nmcli connection modify bond0 \
    ipv4.addresses 192.168.1.100/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.dns "8.8.8.8,8.8.4.4" \
    ipv4.method manual

# 启动bond
nmcli connection up bond0

参数说明:

  • mode=active-backup:主备模式
  • miimon=100:每100毫秒检测一次链路状态
  • primary=ens33:指定ens33为主网卡

3.2.2 使用nmcli配置Mode 4(LACP模式)

# 创建bond接口
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"

# 添加slave
nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-slave1 \
    ifname ens33 \
    master bond0

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-slave2 \
    ifname ens34 \
    master bond0

# 配置IP
nmcli connection modify bond0 \
    ipv4.addresses 192.168.1.100/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.method manual

# 启动
nmcli connection up bond0

参数说明:

  • mode=802.3ad:LACP模式
  • lacp_rate=fast:快速LACP协商(每秒一次),默认是slow(每30秒一次)
  • xmit_hash_policy=layer3+4:使用IP地址和端口号做hash,负载均衡效果更好

3.2.3 查看和管理bond状态

# 查看bond状态
cat /proc/net/bonding/bond0

# 查看连接状态
nmcli connection show

# 查看设备状态
nmcli device status

# 查看详细配置
nmcli connection show bond0

# 临时禁用某个slave(测试用)
nmcli device disconnect ens33

# 重新启用
nmcli device connect ens33

3.3 Ubuntu 24.04 配置方法

Ubuntu从17.10开始使用Netplan作为网络配置工具,底层可以选择NetworkManager或systemd-networkd作为渲染器。服务器版默认用systemd-networkd。

3.3.1 Netplan配置Mode 1

编辑配置文件 /etc/netplan/01-bond-config.yaml

network:
  version: 2
  renderer: networkd

  ethernets:
    ens33:
      dhcp4: false
      dhcp6: false
    ens34:
      dhcp4: false
      dhcp6: false

  bonds:
    bond0:
      interfaces:
        - ens33
        - ens34
      addresses:
        - 192.168.1.100/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
          - 8.8.4.4
      parameters:
        mode: active-backup
        primary: ens33
        mii-monitor-interval: 100
        fail-over-mac-policy: active

应用配置:

# 检查配置语法
netplan try

# 应用配置
netplan apply

# 查看状态
networkctl status bond0

3.3.2 Netplan配置Mode 4

network:
  version: 2
  renderer: networkd

  ethernets:
    ens33:
      dhcp4: false
    ens34:
      dhcp4: false

  bonds:
    bond0:
      interfaces:
        - ens33
        - ens34
      addresses:
        - 192.168.1.100/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
      parameters:
        mode: 802.3ad
        lacp-rate: fast
        mii-monitor-interval: 100
        transmit-hash-policy: layer3+4

3.3.3 使用systemd-networkd直接配置

如果不想用Netplan,也可以直接写systemd-networkd配置文件。

创建 /etc/systemd/network/10-bond0.netdev

[NetDev]
Name=bond0
Kind=bond

[Bond]
Mode=802.3ad
TransmitHashPolicy=layer3+4
MIIMonitorSec=100ms
LACPTransmitRate=fast

创建 /etc/systemd/network/20-bond0-slave.network

[Match]
Name=ens33 ens34

[Network]
Bond=bond0

创建 /etc/systemd/network/30-bond0.network

[Match]
Name=bond0

[Network]
Address=192.168.1.100/24
Gateway=192.168.1.1
DNS=8.8.8.8

重启网络服务:

systemctl restart systemd-networkd

3.4 Debian 12 配置方法

Debian 12可以使用传统的ifupdown配置,也可以使用systemd-networkd。这里演示ifupdown方式。

首先安装ifenslave:

apt install ifenslave

编辑 /etc/network/interfaces

# 回环接口
auto lo
iface lo inet loopback

# 物理网卡设为手动模式
auto ens33
iface ens33 inet manual
    bond-master bond0

auto ens34
iface ens34 inet manual
    bond-master bond0

# Bond接口配置
auto bond0
iface bond0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    gateway 192.168.1.1
    dns-nameservers 8.8.8.8
    bond-slaves ens33 ens34
    bond-mode active-backup
    bond-miimon 100
    bond-primary ens33

重启网络:

systemctl restart networking

3.5 配置永久加载bonding模块

确保bonding模块开机自动加载:

# RHEL系
echo "bonding" > /etc/modules-load.d/bonding.conf

# Debian/Ubuntu
echo "bonding" >> /etc/modules

# 配置模块参数(可选)
cat > /etc/modprobe.d/bonding.conf << EOF
options bonding max_bonds=0
EOF

max_bonds=0表示不自动创建bond接口,让网络管理工具来创建。

四、交换机配置

Bonding的某些模式需要交换机配合配置,特别是Mode 4(LACP)。这里给出几个主流交换机的配置示例。

4.1 华为交换机配置LACP

# 进入系统视图
system-view

# 创建链路聚合组
interface Eth-Trunk 1
 mode lacp-static

# 将端口加入聚合组
interface GigabitEthernet 0/0/1
 eth-trunk 1

interface GigabitEthernet 0/0/2
 eth-trunk 1

# 配置负载均衡模式
interface Eth-Trunk 1
 load-balance src-dst-ip

# 查看聚合状态
display eth-trunk 1

4.2 思科交换机配置LACP

# 进入全局配置模式
configure terminal

# 创建Port-Channel
interface Port-channel1
 switchport mode access
 switchport access vlan 100

# 将端口加入Port-Channel
interface range GigabitEthernet0/1-2
 channel-group 1 mode active

# 配置负载均衡
port-channel load-balance src-dst-ip

# 查看状态
show etherchannel summary
show lacp neighbor

4.3 H3C交换机配置LACP

# 进入系统视图
system-view

# 创建聚合接口
interface Bridge-Aggregation 1
 link-aggregation mode dynamic

# 将端口加入聚合组
interface GigabitEthernet 1/0/1
 port link-aggregation group 1

interface GigabitEthernet 1/0/2
 port link-aggregation group 1

# 配置负载均衡
link-aggregation load-sharing mode destination-ip source-ip

# 查看状态
display link-aggregation verbose

4.4 交换机配置注意事项

  1. 端口属性要一致:聚合组内的所有端口,速率、双工模式、VLAN配置必须完全一致,否则聚合会失败。
  2. LACP模式选择:交换机端可以配置为active或passive。建议服务器和交换机至少有一端是active,否则协商不会启动。
  3. 负载均衡算法:交换机和服务器的负载均衡算法最好配置成一样的,比如都用layer3+4,这样流量分布更均匀。
  4. 生成树协议:聚合端口通常不需要启用STP,因为聚合本身就是冗余的。但如果网络拓扑复杂,还是建议保留。
  5. 跨设备聚合:如果要把服务器的两块网卡分别连到两台交换机,需要交换机支持跨设备聚合(如华为的Eth-Trunk跨框、思科的vPC/VSS)。这种配置更复杂,但可用性更高。

五、高级配置与调优

5.1 ARP监控配置

除了MII监控,Bonding还支持ARP监控。ARP监控通过定期发送ARP请求来检测链路状态,比MII监控更可靠,因为它能检测到网络不通但链路层正常的情况。

# nmcli配置ARP监控
nmcli connection modify bond0 \
    bond.options "mode=active-backup,arp_interval=1000,arp_ip_target=192.168.1.1"

参数说明:

  • arp_interval=1000:每1000毫秒发送一次ARP请求
  • arp_ip_target=192.168.1.1:ARP请求的目标地址,通常设为网关

注意:ARP监控和MII监控不能同时使用。

5.2 多个ARP目标

可以配置多个ARP目标地址,提高检测可靠性:

nmcli connection modify bond0 \
    bond.options "mode=active-backup,arp_interval=1000,arp_ip_target=192.168.1.1+192.168.1.2+192.168.1.3,arp_all_targets=any"

arp_all_targets参数:

  • any:任意一个目标可达就认为链路正常
  • all:所有目标都可达才认为链路正常

5.3 配置Bond接口的MAC地址

默认情况下,bond接口使用第一个slave的MAC地址。可以手动指定:

# 设置固定MAC
nmcli connection modify bond0 \
    ethernet.cloned-mac-address "00:11:22:33:44:55"

或者配置fail_over_mac参数控制故障切换时的MAC行为:

nmcli connection modify bond0 \
    bond.options "mode=active-backup,miimon=100,fail_over_mac=active"

fail_over_mac选项:

  • none:默认值,bond接口MAC不变
  • active:bond接口使用当前active slave的MAC
  • follow:active slave的MAC跟随bond接口

5.4 LACP参数调优

使用Mode 4时,有几个重要参数可以调优:

nmcli connection modify bond0 \
    bond.options "mode=802.3ad,miimon=100,lacp_rate=fast,ad_select=bandwidth,xmit_hash_policy=layer3+4"

参数说明:

lacp_rate

  • slow:默认值,每30秒发送一次LACPDU
  • fast:每秒发送一次LACPDU,故障检测更快

ad_select:聚合组选择策略

  • stable:默认值,选择后不再改变
  • bandwidth:选择带宽最大的聚合组
  • count:选择端口数最多的聚合组

xmit_hash_policy:发送hash策略

  • layer2:基于MAC地址hash
  • layer3+4:基于IP地址和端口号hash(推荐)
  • layer2+3:基于MAC和IP地址hash
  • encap2+3:针对隧道封装流量
  • encap3+4:针对隧道封装流量,使用内层IP

5.5 配置多个Bond接口

一台服务器可以配置多个bond接口,用于不同网络:

# 业务网bond
nmcli connection add type bond \
    con-name bond0 \
    ifname bond0 \
    bond.options "mode=802.3ad,miimon=100,xmit_hash_policy=layer3+4"

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-slave1 \
    ifname ens33 \
    master bond0

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-slave2 \
    ifname ens34 \
    master bond0

nmcli connection modify bond0 \
    ipv4.addresses 192.168.1.100/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.method manual

# 管理网bond
nmcli connection add type bond \
    con-name bond1 \
    ifname bond1 \
    bond.options "mode=active-backup,miimon=100"

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond1-slave1 \
    ifname ens35 \
    master bond1

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond1-slave2 \
    ifname ens36 \
    master bond1

nmcli connection modify bond1 \
    ipv4.addresses 10.0.0.100/24 \
    ipv4.method manual

# 启动
nmcli connection up bond0
nmcli connection up bond1

5.6 Bond接口配置VLAN

bond接口上可以叠加VLAN配置:

# 先创建bond
nmcli connection add type bond \
    con-name bond0 \
    ifname bond0 \
    bond.options "mode=802.3ad,miimon=100"

# ... 添加slave省略 ...

# 在bond上创建VLAN接口
nmcli connection add type vlan \
    con-name bond0.100 \
    dev bond0 \
    id 100 \
    ipv4.addresses 192.168.100.10/24 \
    ipv4.method manual

nmcli connection add type vlan \
    con-name bond0.200 \
    dev bond0 \
    id 200 \
    ipv4.addresses 192.168.200.10/24 \
    ipv4.method manual

这种配置常用于服务器需要接入多个VLAN的场景,比如虚拟化宿主机。

六、监控与运维

6.1 Bond状态检查脚本

写一个实用的检查脚本:

#!/bin/bash
# bond_check.sh - 检查bonding状态

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

check_bond() {
    local bond=$1
    local bond_file="/proc/net/bonding/${bond}"

    if [[ ! -f "$bond_file" ]]; then
        echo -e "${RED}[ERROR]${NC} Bond interface ${bond} does not exist"
        return 1
    fi

    echo "=========================================="
    echo "Checking: ${bond}"
    echo "=========================================="

    # 获取bond模式
    local mode=$(grep "Bonding Mode:" "$bond_file" | cut -d: -f2 | xargs)
    echo "Mode: ${mode}"

    # 获取MII状态
    local mii_status=$(grep "MII Status:" "$bond_file" | head -1 | cut -d: -f2 | xargs)
    if [[ "$mii_status" == "up" ]]; then
        echo -e "Bond MII Status: ${GREEN}${mii_status}${NC}"
    else
        echo -e "Bond MII Status: ${RED}${mii_status}${NC}"
    fi

    # 检查各slave状态
    echo ""
    echo "Slave Interfaces:"
    local slave_count=0
    local active_count=0

    while IFS= read -r line; do
        if [[ "$line" =~ ^Slave\ Interface:\ (.+) ]]; then
            current_slave="${BASH_REMATCH[1]}"
            ((slave_count++))
        fi
        if [[ "$line" =~ ^MII\ Status:\ (.+) ]]; then
            if [[ -n "$current_slave" ]]; then
                status="${BASH_REMATCH[1]}"
                if [[ "$status" == "up" ]]; then
                    echo -e "  - ${current_slave}: ${GREEN}${status}${NC}"
                    ((active_count++))
                else
                    echo -e "  - ${current_slave}: ${RED}${status}${NC}"
                fi
                current_slave=""
            fi
        fi
    done < <(tail -n +10 "$bond_file")

    echo ""
    echo "Summary: ${active_count}/${slave_count} slaves active"

    if [[ $active_count -eq 0 ]]; then
        echo -e "${RED}[CRITICAL]${NC} No active slaves!"
        return 2
    elif [[ $active_count -lt $slave_count ]]; then
        echo -e "${YELLOW}[WARNING]${NC} Some slaves are down"
        return 1
    else
        echo -e "${GREEN}[OK]${NC} All slaves are active"
        return 0
    fi
}

# 主程序
if [[ $# -eq 0 ]]; then
    # 检查所有bond接口
    for bond in /proc/net/bonding/bond*; do
        if [[ -f "$bond" ]]; then
            bond_name=$(basename "$bond")
            check_bond "$bond_name"
            echo ""
        fi
    done
else
    # 检查指定的bond接口
    for bond in "$@"; do
        check_bond "$bond"
        echo ""
    done
fi

使用方法:

chmod +x bond_check.sh

# 检查所有bond
./bond_check.sh

# 检查指定bond
./bond_check.sh bond0

6.2 Prometheus监控配置

使用node_exporter可以采集bonding指标。确保node_exporter启用了bonding collector:

# 启动node_exporter时启用bonding collector
./node_exporter --collector.bonding

然后配置Prometheus告警规则:

groups:
  - name: bonding
    rules:
      # Bond接口有slave down
      - alert: BondingSlaveDegraded
        expr: node_bonding_slaves - node_bonding_active != 0
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "Bonding interface degraded on {{ $labels.instance }}"
          description: "Bond {{ $labels.master }} has {{ $value }} inactive slaves"

      # Bond接口完全down
      - alert: BondingInterfaceDown
        expr: node_bonding_active == 0
        for: 30s
        labels:
          severity: critical
        annotations:
          summary: "Bonding interface down on {{ $labels.instance }}"
          description: "Bond {{ $labels.master }} has no active slaves"

Grafana面板示例:

{
  "panels": [
    {
      "title": "Bond Active Slaves",
      "type": "stat",
      "targets": [
        {
          "expr": "node_bonding_active{instance=\"$instance\"}",
          "legendFormat": "{{ master }}"
        }
      ]
    },
    {
      "title": "Bond Status",
      "type": "table",
      "targets": [
        {
          "expr": "node_bonding_slaves{instance=\"$instance\"} - node_bonding_active{instance=\"$instance\"}",
          "legendFormat": "{{ master }}"
        }
      ]
    }
  ]
}

6.3 日志监控

bonding相关的日志在系统日志中,可以这样监控:

# 实时查看bonding日志
journalctl -f | grep -i bonding

# 或者
tail -f /var/log/messages | grep -i bonding

配置rsyslog转发bonding日志:

# /etc/rsyslog.d/bonding.conf
:msg, contains, "bonding" /var/log/bonding.log
& stop

6.4 定期健康检查Cron任务

# /etc/cron.d/bond-check
*/5 * * * * root /usr/local/bin/bond_check.sh > /dev/null 2>&1 || echo "Bond degraded on $(hostname)" | mail -s "Bond Alert" ops@example.com

七、故障排查指南

7.1 常见问题:Bond接口无法启动

现象:配置完成后,bond接口无法UP。

排查步骤:

# 1. 检查bonding模块是否加载
lsmod | grep bonding

# 2. 检查配置文件语法
# RHEL/Rocky
nmcli connection show bond0

# Ubuntu
netplan try

# 3. 检查slave网卡状态
ip link show ens33
ip link show ens34

# 4. 查看系统日志
journalctl -xe | grep -i bond
dmesg | grep -i bond

# 5. 检查是否有IP冲突
arping -I bond0 192.168.1.100

常见原因:

  • slave网卡已经配置了IP地址,需要先清除
  • slave网卡被其他进程占用
  • bonding模块参数错误

解决方法:

# 清除slave网卡的IP配置
ip addr flush dev ens33
ip addr flush dev ens34

# 重新加载配置
nmcli connection reload
nmcli connection up bond0

7.2 常见问题:LACP协商失败

现象:配置了Mode 4,但bond状态显示不正常,没有建立聚合。

排查步骤:

# 1. 检查LACP状态
cat /proc/net/bonding/bond0
# 注意看Partner Mac Address是否为00:00:00:00:00:00

# 2. 抓包看LACPDU
tcpdump -i ens33 ether proto 0x8809 -vv

# 3. 检查交换机配置
# 登录交换机查看聚合状态

常见原因:

  • 交换机没有配置LACP或配置错误
  • 交换机端口模式不匹配(access vs trunk)
  • 交换机端口VLAN配置不一致
  • 网线连接错误

解决方法:

  • 确认交换机配置正确
  • 确保端口属性一致
  • 尝试将交换机LACP模式改为active

7.3 常见问题:Slave频繁切换

现象:bond运行中,slave频繁在up和down之间切换。

排查步骤:

# 1. 查看切换日志
journalctl -u NetworkManager | grep -i bond

# 2. 检查网卡和链路状态
ethtool ens33
ethtool ens34

# 3. 检查miimon设置是否合理
cat /proc/net/bonding/bond0 | grep "MII Polling"

# 4. 检查网卡驱动和固件版本
ethtool -i ens33

常见原因:

  • 网线接触不良
  • 网卡或交换机端口硬件问题
  • 网卡驱动bug
  • miimon设置太短

解决方法:

  • 更换网线
  • 更换网卡或交换机端口
  • 更新网卡驱动
  • 适当增加miimon值(如200ms)

7.4 常见问题:Mode 4流量不均衡

现象:使用LACP模式,但流量明显偏向某一块网卡。

排查步骤:

# 1. 查看各slave的流量统计
cat /proc/net/bonding/bond0

# 或者用ip命令
ip -s link show ens33
ip -s link show ens34

# 2. 检查hash策略
cat /proc/net/bonding/bond0 | grep "Transmit Hash"

# 3. 分析流量模式
iftop -i bond0

原因分析: LACP的负载均衡是基于hash的,如果流量都来自少量的源或目的地址,hash结果可能都落到同一块网卡上。

解决方法:

  • 改用layer3+4的hash策略(如果还没用的话)
  • 这是正常现象,hash负载均衡不是绝对均匀的
  • 如果需要更均匀的分布,考虑Mode 6(balance-alb)

7.5 常见问题:虚拟机中Bonding不工作

现象:在虚拟机中配置bonding,功能不正常。

这个问题比较常见,原因是虚拟化平台的虚拟交换机可能对bonding的某些模式支持不好。

VMware环境:

  • Mode 1(active-backup)通常没问题
  • Mode 4(LACP)需要vDS(分布式交换机)且配置LAG
  • Mode 6(balance-alb)可能不工作,因为ARP代理受限

KVM/libvirt环境:

  • 建议在宿主机而不是虚拟机中配置bonding
  • 如果必须在VM中配置,使用bridge网络且确保宿主机桥接配置正确

解决方法:

  • 虚拟机中优先使用Mode 1
  • 如果需要带宽聚合,在虚拟化平台层面做聚合

7.6 调试命令汇总

# 查看bond详细状态
cat /proc/net/bonding/bond0

# 查看所有网络接口
ip addr show
ip link show

# 查看网卡详细信息
ethtool eth0
ethtool -i eth0  # 驱动信息
ethtool -S eth0  # 统计信息

# 查看ARP表
ip neigh show

# 抓包分析
tcpdump -i bond0 -nn
tcpdump -i ens33 ether proto 0x8809 -vv  # LACP

# 查看系统日志
journalctl -xe | grep -i bond
dmesg | grep -i bond

# NetworkManager调试
nmcli general logging level DEBUG domain ALL
journalctl -u NetworkManager -f

# 重新加载配置
nmcli connection reload
systemctl restart NetworkManager

八、实战案例

8.1 案例一:电商核心交易库高可用改造

背景: 某电商平台的MySQL主库单网卡部署,之前发生过网卡故障导致服务中断的情况。需要改造为双网卡bonding,要求不能影响现有业务。

环境:

  • 操作系统:Rocky Linux 9.3
  • 服务器:Dell PowerEdge R750
  • 网卡:板载双千兆 + 双万兆网卡
  • 交换机:华为CE6800系列,支持LACP

方案设计:

  1. 使用两块万兆网卡做bond,配置Mode 4(LACP)
  2. 利用维护窗口期执行变更
  3. 提前在测试环境验证

实施步骤:

# 1. 检查当前网络配置
ip addr show
nmcli connection show

# 当前配置:
# ens33: 192.168.1.100/24 (业务IP)
# ens34: 未配置
# ens35: 未配置
# ens36: 10.0.0.100/24 (管理IP)

# 2. 交换机配置(由网络工程师执行)
# 华为交换机配置LACP
# interface Eth-Trunk 10
#  mode lacp-static
# interface 10GE1/0/1
#  eth-trunk 10
# interface 10GE1/0/2
#  eth-trunk 10

# 3. 服务器端配置
# 备份当前配置
nmcli connection show --active > /root/network_backup.txt

# 创建bond接口(先不配IP)
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"

# 添加slave
nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-port1 \
    ifname ens34 \
    master bond0

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-port2 \
    ifname ens35 \
    master bond0

# 4. 关键步骤:IP迁移
# 这一步需要快速执行,建议写成脚本

cat > /root/migrate_ip.sh << 'EOF'
#!/bin/bash
set -e

# 删除原网卡IP
nmcli connection down ens33-connection

# 配置bond IP
nmcli connection modify bond0 \
    ipv4.addresses 192.168.1.100/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.dns "8.8.8.8" \
    ipv4.method manual

# 启动bond
nmcli connection up bond0

echo "Migration completed"
EOF

chmod +x /root/migrate_ip.sh

# 5. 执行迁移(维护窗口内)
# 先通过管理IP连接服务器
ssh admin@10.0.0.100

# 执行迁移脚本
/root/migrate_ip.sh

# 6. 验证
cat /proc/net/bonding/bond0
ping -c 3 192.168.1.1
nmcli connection show --active

验证结果:

Bonding Mode: IEEE 802.3ad Dynamic link aggregation
Transmit Hash Policy: layer3+4 (1)
MII Status: up
MII Polling Interval (ms): 100
LACP rate: fast

Slave Interface: ens34
MII Status: up
Speed: 10000 Mbps
Permanent HW addr: 00:11:22:33:44:55

Slave Interface: ens35
MII Status: up
Speed: 10000 Mbps
Permanent HW addr: 00:11:22:33:44:56

故障测试:

# 模拟网卡故障
nmcli device disconnect ens34

# 查看bond状态
cat /proc/net/bonding/bond0
# 应显示ens34为down,但bond接口仍然正常

# 业务验证
mysql -h192.168.1.100 -uroot -p -e "SELECT 1"
# 应该正常返回

# 恢复
nmcli device connect ens34

8.2 案例二:Kubernetes Worker节点网络优化

背景: 某公司的Kubernetes集群Worker节点跑容器业务,单网卡带宽经常跑满。需要增加网络带宽,同时保证高可用。

环境:

  • 操作系统:Ubuntu 24.04 LTS
  • Kubernetes:1.31
  • 服务器:自组装服务器,4块Intel i350千兆网卡
  • 交换机:普通千兆交换机,不支持LACP

方案设计: 由于交换机不支持LACP,选择Mode 6(balance-alb)来实现负载均衡,不需要交换机配合。

Netplan配置文件 /etc/netplan/01-bond-config.yaml

network:
  version: 2
  renderer: networkd

  ethernets:
    enp1s0:
      dhcp4: false
    enp2s0:
      dhcp4: false
    enp3s0:
      dhcp4: false
    enp4s0:
      dhcp4: false

  bonds:
    bond0:
      interfaces:
        - enp1s0
        - enp2s0
        - enp3s0
        - enp4s0
      addresses:
        - 192.168.1.101/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
      parameters:
        mode: balance-alb
        mii-monitor-interval: 100
      mtu: 9000

注意这里还配置了巨型帧(MTU 9000),可以进一步提升大数据量传输的性能。

应用配置:

# 验证配置
netplan try

# 应用
netplan apply

# 查看状态
networkctl status bond0
cat /proc/net/bonding/bond0

Kubernetes CNI配置调整:

使用Calico时,需要确保Calico使用bond接口:

# 检查Calico自动发现的IP
kubectl get node k8s-worker-1 -o jsonpath='{.status.addresses}'

# 如果需要指定,修改Calico配置
kubectl -n kube-system edit daemonset calico-node
# 添加环境变量:IP_AUTODETECTION_METHOD=interface=bond0

性能测试:

# 安装iperf3
apt install iperf3

# 服务端
iperf3 -s

# 客户端(4个并发连接测试)
iperf3 -c 192.168.1.101 -P 4

# 预期结果:总带宽接近4Gbps(4块千兆网卡)

8.3 案例三:VMware ESXi环境下的Bond配置

背景: VMware ESXi 8.0环境,需要在虚拟机(RHEL 9)中配置bonding,虚拟机有两块虚拟网卡连接到不同的物理上行链路。

这个场景稍微特殊,因为需要在虚拟化层面和虚拟机内部同时做配置。

ESXi端配置:

  1. 确保虚拟机有两块网卡,分别连接到不同的vSwitch上行链路
  2. 虚拟交换机需要开启”允许MAC地址变更”和”允许伪传输”(因为bonding会修改MAC)

vSphere Web Client中:

  • 选择vSwitch -> 编辑设置
  • 安全策略:
    • 允许MAC地址变更:是
    • 允许伪传输:是
    • 混杂模式:否(不需要)

虚拟机内部配置:

由于ESXi不支持真正的LACP(除非用vDS),虚拟机内只能用Mode 1(active-backup):

# 创建bond
nmcli connection add type bond \
    con-name bond0 \
    ifname bond0 \
    bond.options "mode=active-backup,miimon=100,fail_over_mac=active"

# fail_over_mac=active 很重要,让MAC跟随active接口
# 否则VMware可能会丢包

# 添加slave
nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-eth0 \
    ifname ens192 \
    master bond0

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-eth1 \
    ifname ens224 \
    master bond0

# 配置IP
nmcli connection modify bond0 \
    ipv4.addresses 192.168.1.50/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.method manual

# 启动
nmcli connection up bond0

测试failover:

# 在vSphere中断开其中一块网卡的上行链路
# 或者在VM中:
nmcli device disconnect ens192

# 检查bond状态
cat /proc/net/bonding/bond0

# 应该自动切换到ens224,网络不中断
ping -c 10 192.168.1.1

8.4 案例四:跨机房双活网络架构

背景: 某金融客户要实现跨机房双活,服务器需要同时连接两个机房的网络。每个机房各有一根专线,要求任一专线故障业务不受影响。

这是个相对复杂的场景,需要结合Bonding和策略路由。

网络架构:

                    +-------------------+
                    |    应用服务器      |
                    |  bond0: 双网卡    |
                    +--------+----------+
                             |
              +--------------+--------------+
              |                             |
        +-----+-----+                 +-----+-----+
        |   eth0    |                 |   eth1    |
        +-----+-----+                 +-----+-----+
              |                             |
        +-----+-----+                 +-----+-----+
        | 机房A交换机 |                 | 机房B交换机 |
        +-----------+                 +-----------+
              |                             |
        专线接入机房A                   专线接入机房B

配置步骤:

# 1. 创建主备模式bond,eth0为主
nmcli connection add type bond \
    con-name bond0 \
    ifname bond0 \
    bond.options "mode=active-backup,miimon=100,primary=eth0,arp_interval=1000,arp_ip_target=10.1.1.1+10.2.1.1,arp_all_targets=any"

# 这里使用ARP监控而不是MII,因为要检测的是到网关的连通性
# arp_ip_target配置两个机房的网关

# 2. 添加slave
nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-eth0 \
    ifname eth0 \
    master bond0

nmcli connection add type ethernet \
    slave-type bond \
    con-name bond0-eth1 \
    ifname eth1 \
    master bond0

# 3. 配置IP
nmcli connection modify bond0 \
    ipv4.addresses 10.1.1.100/24 \
    ipv4.gateway 10.1.1.1 \
    ipv4.routes "10.2.0.0/16 10.1.1.1 100" \
    ipv4.method manual

# 启动
nmcli connection up bond0

配置策略路由,确保回程流量走正确的路径:

# 添加路由表
echo "100 dc_a" >> /etc/iproute2/rt_tables
echo "200 dc_b" >> /etc/iproute2/rt_tables

# 配置策略路由规则
cat > /etc/networkd-dispatcher/routable.d/policy-route.sh << 'EOF'
#!/bin/bash
# 机房A的流量走机房A网关
ip route add default via 10.1.1.1 table dc_a
ip rule add from 10.1.1.100 table dc_a priority 100

# 机房B的流量走机房B网关(当failover到机房B时)
ip route add default via 10.2.1.1 table dc_b
ip rule add from 10.2.1.100 table dc_b priority 100
EOF

chmod +x /etc/networkd-dispatcher/routable.d/policy-route.sh

这个配置确保了:

  1. 正常情况下,流量走机房A
  2. 机房A专线故障时,ARP检测失败,自动切换到机房B
  3. 切换后,流量自动走机房B的路径

九、最佳实践总结

9.1 配置最佳实践

  1. 模式选择
    • 单纯高可用选Mode 1,简单可靠
    • 需要带宽聚合且交换机支持LACP选Mode 4
    • 交换机不支持聚合但需要负载均衡选Mode 6
  2. 监控间隔设置
    • miimon建议设置100ms,既能快速检测故障,又不会造成太大开销
    • 如果网络不太稳定,可以适当增加到200ms,避免误切换
  3. ARP监控
    • 关键业务建议启用ARP监控,能检测到三层网络问题
    • arp_ip_target设置为网关或上游可靠设备的IP
  4. LACP参数
    • lacp_rate建议设置为fast,加快故障检测
    • xmit_hash_policy建议用layer3+4,负载均衡效果更好
  5. 命名规范
    • Bond接口用bond0、bond1命名
    • 连接名用有意义的名字,如bond0-mgmt、bond0-storage

9.2 运维最佳实践

  1. 变更窗口
    • 网络配置变更务必在维护窗口执行
    • 保留备用访问通道(如管理网、IPMI/iDRAC)
  2. 回滚预案
    • 变更前备份配置
    • 准备回滚脚本
    • 设置定时任务自动回滚(万一连不上)
# 自动回滚示例
# 在变更前执行
echo "nmcli connection down bond0; nmcli connection up eth0" | at now + 10 minutes

# 变更成功后取消
atrm $(atq | awk '{print $1}')
  1. 监控告警
    • Bond状态必须纳入监控
    • Slave数量少于配置数量时告警
    • 定期检查Bond健康状态
  2. 文档记录
    • 记录每台服务器的Bond配置
    • 记录交换机端口对应关系
    • 配置变更要更新文档

9.3 故障处理最佳实践

  1. 故障定级
    • 所有Slave down = P0(紧急)
    • 部分Slave down = P1(重要,需尽快处理)
  2. 应急处理
    • 业务影响时优先恢复服务
    • 可以临时配置单网卡运行
    • 事后再排查根因
  3. 复盘改进
    • 每次故障后要复盘
    • 改进监控和告警
    • 完善应急预案

十、总结

写到这里,差不多把这些年关于网卡Bonding的经验都掏出来了。总结几个核心观点:

  1. Bonding是服务器的基本保障。任何稍微重要一点的服务器,都应该配置网卡冗余。一块几十块的网卡故障导致几十万甚至几百万的损失,这种事情完全可以避免。
  2. 配置不复杂,重在理解。Bonding的配置命令就那么几条,但要用好它,需要理解各种模式的原理、交换机的配合、监控参数的含义。理解了这些,配置就是水到渠成的事。
  3. 选对模式很重要。大部分场景Mode 1或Mode 4就够了。别为了追求花哨选一些不合适的模式,简单可靠才是王道。
  4. 监控和告警不能少。配置完不是终点,要纳入监控。Slave down了没人知道,等Bond完全挂了才发现就晚了。
  5. 定期演练。找个维护窗口,手动拔一根网线,验证一下failover是不是真的work。光配置不测试,心里没底。

最后,技术在不断发展,Linux内核的Bonding模块也在持续优化。保持学习,关注最新的变化,才能不被淘汰。

希望这篇文章对大家有帮助。有问题欢迎交流。


参考资料:

IEEE 802.3ad Link Aggregation Standard

Linux Kernel Documentation – Bonding

Red Hat Enterprise Linux 9 Networking Guide

Ubuntu Server Guide – Network Configuration