1. 为什么双网卡绑定不是插两根网线那么简单服务器或工控机只有一块网卡网络一断业务就停摆这种事做运维的朋友应该都经历过业务带宽到了千兆上限换万兆网卡又贵又折腾。于是双网卡绑定链路聚合就成了最常用的解决思路——把两块物理网卡绑成一个逻辑网卡对外同一个IP、同一个MAC对内由内核驱动和交换机协商流量怎么走。最近我刚好在调一台研华ECU-579工控机跑的是Debian 12客户需求就是双网卡绑定而且最好是动态链路聚合——这活儿看着简单但如果你不理解底层原理配置完大概率会踩坑。下面我把Linux侧的bonding和team、以及华为和华三交换机侧的对接配置串起来讲一遍适合运维、系统集成商以及做工业现场项目的朋友参考。1.1 聚合与冗余两者不能同时默认成立先把概念拆开。双网卡绑定的收益有两种一种是冗余高可用主网卡断了备用网卡顶上业务不中断另一种是带宽叠加聚合两块网卡同时转发总吞吐量接近两倍。听起来很简单但很多人默认绑完就能两条线一起跑这是最大的误解。为什么不能简单地插两根网线一起用因为交换机会学习MAC地址和端口的对应关系。如果同一块网卡的MAC地址一会儿从端口1冒出来一会儿从端口2冒出来交换机会不停刷新MAC表项造成MAC地址漂移严重时还会引发环路。所以必须借助链路聚合机制让两端商量好这两个物理口属于同一个逻辑接口。这里有一个必须想清楚的点冗余模式和聚合模式是两回事。比如mode 1主备模式下同一时刻只有一条物理链路转发带宽不叠加想叠加带宽就得用balance-rr、balance-xor或802.3ad这类多链路同时转发的模式。所以我每次做项目都会先问一句你到底是要断网不中断还是要跑满更大带宽目的不同后面的方案完全不同。1.2 bonding的七种模式选错等于白绑Linux内核的bonding驱动提供了7种模式理解它们是从会配置到会排错的分水岭。这里用一张表总结模式名称是否需要交换机配合典型场景mode 0balance-rr需要静态聚合逐包轮询能打满总带宽但可能乱序mode 1active-backup不需要纯冗余主备切换带宽不叠加mode 2balance-xor需要静态聚合基于MAC或流的hash常见聚合模式mode 3broadcast需要聚合或全转发把所有报文发到所有口极少用mode 4802.3ad需要LACP动态聚合动态链路聚合服务器推荐mode 5balance-tlb不需要发送负载均衡接收仍走主口mode 6balance-alb不需要发送和接收都负载均衡无需交换机支持实际项目里用得最多的是mode 1和mode 4。mode 1简单可靠什么交换机都能用缺点是带宽不叠加、主备切换需要几百毫秒mode 4走LACP协议两端自动协商交换机上配置好Eth-Trunk或Bridge-Aggregation后链路状态和成员口状态一目了然带宽能真正叠加机房服务器和工业现场我基本都优先推它。mode 0和mode 2也能叠加带宽但要求交换机手工聚合其中mode 0是逐包轮询容易产生乱序对TCP性能有影响除非特殊需求否则不建议在生产环境使用。还有一个参数要记住miimon。它控制bonding驱动轮询物理链路状态的时间间隔单位毫秒生产环境一般设100。比如mode 1主备主网卡被拔了网线miimon100意味着最多100ms就能感知到链路断开并切换配合网关检测等其他手段实际业务中断时间可以控制在1秒以内这在工业项目中是可以接受的。至于LACP快速/慢速报文、xmit_hash_policyhash算法策略后面讲到交换机对接时再展开。2. CentOS 7.9的bonding配置从模块加载到网卡配置CentOS 7.9虽然已进入维护期但存量服务器还有很多很多机房仍然用它跑核心业务。双网卡绑定在7.9上有两种主流做法用NetworkManager的nmcli命令或者直接改ifcfg配置文件。我建议能用nmcli就用nmcli它会自动处理connection状态和持久化比手写配置文件少踩很多坑。2.1 先认清网卡和网络服务再动手动手前先花两分钟确认三件事网卡名、网络服务状态、bonding模块是否可用。ip link # 查看所有网卡记下要绑定的名称 nmcli device status # 查看网卡当前连接状态 systemctl status NetworkManager # CentOS 7.9默认用NetworkManager如果网卡名是eth0、eth1说明系统用了biosdevname或旧命名规则如果是ens33、ens34说明使用一致网络设备命名。不管是哪种绑定前一定记准物理网口对应的系统名称。尤其是远程服务器绑错网卡名等于把自己锁在门外。我见过不止一次有人把管理口和业务口搞混配置一下发SSH直接断最后只能让机房同事帮忙接console口去改。确认bonding模块能被加载modprobe bonding lsmod | grep bonding如果没有输出说明bonding模块没加载成功。CentOS 7.9标准内核都带bonding驱动一般不会出问题但如果之前改装过内核或者用了精简版就要先更新内核或安装kernel-devel再处理。2.2 nmcli与ifcfg两套写法先说nmcli这是CentOS 7.9上最不容易出错的路径。假设要绑定的网卡是eth0和eth1逻辑口叫bond0IP是192.168.10.10/24网关192.168.10.1采用mode 4802.3ad动态链路聚合# 创建bond接口 nmcli connection add type bond ifname bond0 mode 802.3ad ipv4.method manual ipv4.addresses 192.168.10.10/24 ipv4.gateway 192.168.10.1 ipv4.dns 223.5.5.5 # 把两块物理网卡加入bond0并显式指定从口连接名 nmcli connection add con-name bond-eth0 type ethernet ifname eth0 master bond0 nmcli connection add con-name bond-eth1 type ethernet ifname eth1 master bond0 # 启用顺序先启bond0再启两个从口 nmcli connection up bond0 nmcli connection up bond-eth0 nmcli connection up bond-eth1 # 查看bond状态 cat /proc/net/bonding/bond0这里需要说明一下nmcli connection add type ethernet ifname eth0 master bond0默认生成的连接名类似于bond-slave-eth0所以我用con-name显式指定成bond-eth0后续启用和排错时更容易辨认。如果你希望调整bond参数比如设置miimon和hash策略可以这样改nmcli connection modify bond0 bond.options mode802.3ad,miimon100,xmit_hash_policylayer34如果你不在NetworkManager环境或者团队习惯传统ifcfg方式那就直接改配置文件。一共要建三个文件。/etc/sysconfig/network-scripts/ifcfg-bond0DEVICEbond0 NAMEbond0 TYPEBond BONDING_MASTERyes BOOTPROTOnone ONBOOTyes IPADDR192.168.10.10 NETMASK255.255.255.0 GATEWAY192.168.10.1 NM_CONTROLLEDno BONDING_OPTSmode802.3ad miimon100 xmit_hash_policylayer34/etc/sysconfig/network-scripts/ifcfg-eth0DEVICEeth0 NAMEeth0 TYPEEthernet BOOTPROTOnone ONBOOTyes MASTERbond0 SLAVEyes NM_CONTROLLEDno/etc/sysconfig/network-scripts/ifcfg-eth1和eth0只差一个DEVICE和NAME其他都相同。另外还要建一个modprobe.d配置确保开机自动加载bonding模块echo alias bond0 bonding /etc/modprobe.d/bonding.conf echo options bond0 mode802.3ad miimon100 /etc/modprobe.d/bonding.conf最后重启网络生效systemctl restart network cat /proc/net/bonding/bond0手动写ifcfg时最容易被忽略的两个点NM_CONTROLLEDno和BONDING_OPTS。前者是防止NetworkManager干扰传统配置后者决定bond的运行参数。如果你漏写BONDING_OPTSbond0也会起来但mode会退回默认的balance-rrmiimon也没设置链路断了不会自动切换。这个坑很隐蔽现场很难第一时间发现。3. Debian 12与研华ECU-579工业电脑上的双网卡绑定实操Debian 12和CentOS的配置体系完全不一样。Debian服务器默认走ifupdown也就是/etc/network/interfaces。虽然桌面版可能装了NetworkManager但服务器和嵌入式场景基本都走interfaces这一套。研华ECU-579这类无风扇嵌入式工控机客户需求往往不是纯冗余而是把两个千兆口绑起来跑更大的流量所以配置动态链路聚合更常见。3.1 /etc/network/interfaces方式配置bonding先装好必要工具apt update apt install -y ifenslave modprobe bonding echo bonding /etc/modules-load.d/bonding.confifenslave是Debian系管理bond从口的小工具不装它interfaces里的bond-slaves字段就不会生效。/etc/modules-load.d/bonding.conf这一行保证重启后bonding模块自动加载否则重启后bond0会消失。然后编辑/etc/network/interfaces。假设两个网口是enp1s0和enp2s0要绑定成bond0IP为192.168.10.5/24采用mode 4auto bond0 iface bond0 inet static address 192.168.10.5 netmask 255.255.255.0 gateway 192.168.10.1 bond-slaves enp1s0 enp2s0 bond-mode 802.3ad bond-miimon 100 bond-xmit-hash-policy layer34 bond-lacp-rate fast allow-bond0 enp1s0 iface enp1s0 inet manual bond-master bond0 allow-bond0 enp2s0 iface enp2s0 inet manual bond-master bond0注意从口这里我写的是allow-bond0而不是auto这是Debian官方推荐的写法目的就是明确启动顺序bond0先启动再从口加入。如果用auto某些情况下会出现从口先起、bond0还没创建导致的启动失败。写完后重启网络systemctl restart networking ip a show bond0 cat /proc/net/bonding/bond0如果你希望主从明确比如希望enp1s0是主口可以在enp1s0的配置里加一行bond-primary enp1s0这个字段对应bonding的primary选项主要在active-backup、balance-tlb/alb这类有主从概念的模式下有意义mode 4下保持默认即可。3.2 工业现场最容易翻车的网口名漂移在ECU-579这类嵌入式设备上有一个非常容易翻车的点网口名漂移。嵌入式主板的网口可能由不同芯片驱动比如Intel I211、Realtek RTL8111甚至还有USB转出的网口。内核加载驱动的顺序不固定导致重启后enp1s0和enp2s0对应的物理口可能互换。更麻烦的是如果你在interfaces里写死了enpXsY名字一变bond0里绑定的两个接口就完全对不上物理口了。解决办法分几步。先用ethtool确认物理口和MAC的对应关系ethtool -P enp1s0 ethtool -P enp2s0把每个网口对应的MAC记下来然后用udev规则固定网口名cat /etc/udev/rules.d/70-net-name-slot.rules EOF SUBSYSTEMnet, ACTIONadd, ATTR{address}xx:xx:xx:xx:xx:xx, NAMElan1 SUBSYSTEMnet, ACTIONadd, ATTR{address}yy:yy:yy:yy:yy:yy, NAMElan2 EOF然后把interfaces里的enp1s0、enp2s0全部替换成lan1、lan2。注意如果Debian 12同时存在systemd的.link文件udev规则优先级更高这条路径是可靠的。固定好名字后再配置bond后续重启才不会出现band口不见了的诡异故障。工业电脑还有一个特殊点不同网卡驱动的链路状态上报机制不一样。Intel网卡对线缆断开检测很灵敏Realtek相对慢。这就导致miimon100在某些网卡上能秒切在另一些网卡上要等好几秒。遇到切换慢可以加一个ARP监控兜底在interfaces里补充bond-arp-interval 1000 bond-arp-ip-target 192.168.10.1bonding会周期性ARP探测网关发现网关不通就切到备用链路。这种链路层网络层双检测是我在工业场景里比较推荐的做法因为只靠物理链路检测时线缆没断但交换机端口down掉的情况不一定能第一时间发现。4. Linux 8系列用team做动态链路聚合的配置思路CentOS 8、Rocky Linux 8、AlmaLinux 8这些系统上除了bonding还有一个叫team的方案。热词里提到linux8配置team动态链路聚合步骤所以单独拿出来讲。4.1 team和bonding不是替代关系team是红帽在RHEL 7时代主推的方案设计目标是在用户态做类似bonding的事情核心进程是teamd。它和bonding的区别在于bonding是内核态直接处理team则是用户态守护进程加内核netlink配合。那是不是team比bonding更先进我的看法是它们在大部分场景下是等价的不要为了换而换。team的优势是runner以JSON配置描述端口状态查询更直观比如teamdctl可以精细控制某个端口是否启用bonding经过这么多年迭代胜在稳定内核态处理性能也更好。所以在Linux 8系列里新部署我建议优先用bonding但如果你的自动化脚本、培训文档或者其他历史原因要求用team下面步骤可以直接抄。team常用的runner如下runner说明activebackup主备模式对应bond mode 1roundrobin轮询对应bond mode 0loadbalance基于流hash的负载均衡类似bond mode 2/6lacp动态LACP聚合对应bond mode 4broadcast所有端口都发对应bond mode 34.2 nmcli配置team的完整步骤用nmcli配置team思路和配置bonding完全一样只是类型变成team。假设把enp1s0和enp2s0组成team0采用lacp动态聚合# 创建team0runner指定为lacp nmcli con add type team ifname team0 config {runner:{name:lacp,active:true,fast_rate:true}} # 加入两块从网卡 nmcli con add type ethernet ifname enp1s0 master team0 nmcli con add type ethernet ifname enp2s0 master team0 # 配置IP nmcli con modify team0 ipv4.method manual ipv4.addresses 192.168.10.10/24 ipv4.gateway 192.168.10.1 # 启用 nmcli con up team0 nmcli con up team0-port1 nmcli con up team0-port2注意从口的连接名可能是team0-port1这种自动生成的具体用nmcli connection show看。如果希望手动指定连接名和bonding一样可以用con-name。查看team状态不能用/proc/net/bonding/bond0而是用teamdctlteamdctl team0 state这个命令会列出runner类型、成员端口、每个端口的link状态和速率输出比bonding的/proc内容更直观。如果要切成activebackup把config改成nmcli con add type team ifname team0 config {runner:{name:activebackup}}想在运行中临时禁用某个口而不down整个team可以直接操作端口teamdctl team0 port config update enp1s0 enabledfalse这个能力在做链路切换演练时非常好用模拟单链路故障不需要拔网线一条命令就能完成而且随时可以恢复。5. 交换机侧对接华为与华三的链路聚合配置实例只配置服务器不配交换机等于白忙。尤其是mode 2和mode 4交换机必须把对应的两个物理口聚合到一个逻辑口里。这一节直接给华为和华三的实机命令以及eNSP里的验证方式。先提醒一个容易忽略的点即使服务器只做mode 1主备如果交换机不做聚合STP会把备用口置为阻塞状态。主口断掉后交换机STP要重新收敛才能放开备用口短则几秒长则三十秒业务中断时间远超预期。所以只要条件允许我建议冗余场景也尽量在交换机侧做静态聚合让切换动作由链路聚合机制来完成而不是依赖STP重新计算。5.1 华为Eth-Trunk配置与eNSP验证服务器是mode 4时华为交换机侧对应lacp-static模式服务器是mode 2静态聚合时对应manual load-balance模式。下面是和mode 4对接的完整配置system-view interface Eth-Trunk 1 mode lacp-static port link-type trunk port trunk allow-pass vlan 10 quit interface GigabitEthernet0/0/1 eth-trunk 1 quit interface GigabitEthernet0/0/2 eth-trunk 1 quit这里有三个细节容易踩坑。第一先创建Eth-Trunk再往里面添加物理口否则某些型号会提示接口不存在。第二VLAN、端口类型这些二层配置要下在Eth-Trunk逻辑口上物理口加入聚合组后物理口自己的二层配置会失效。第三华为较老的版本命令是mode lacp-static新版本可能也接受mode lacp以设备实际支持的命令为准。配置完用以下命令核对display eth-trunk 1 display lacp statistics eth-trunk 1如果看到聚合口状态是Up且两个成员口都是Selected说明协商成功如果成员口是Unselected先查物理口线缆是否有对端再查两端模式是否匹配。eNSP模拟器里配置命令完全一样只是注意模拟器里Eth-Trunk建立后跨设备ping通前还要确认两端VLAN配置放通。5.2 华三Bridge-Aggregation配置与查看命令华三的链路聚合接口叫Bridge-Aggregation命令风格和华为有差异。动态聚合对应mode dynamicsystem-view interface Bridge-Aggregation 1 link-aggregation mode dynamic port link-type trunk port trunk permit vlan 10 quit interface GigabitEthernet1/0/1 port link-aggregation group 1 quit interface GigabitEthernet1/0/2 port link-aggregation group 1 quit注意华三的VLAN放通命令是port trunk permit vlan 10和华为不一样。查状态优先用这两条命令display link-aggregation summary display lacp verbosedisplay link-aggregation summary里AggID 1那一行会显示聚合口状态和Selected端口数。如果两个成员口都显示Selected链路聚合就通了。如果只有一个Selected另一个是Pending或Unselected基本就是物理层没起来或模式不一致。服务器侧和交换机侧的对应关系再总结一次服务器侧华为交换机华三交换机bonding mode 2 (balance-xor)manual load-balancestaticbonding mode 4 (802.3ad)lacp-staticdynamicteam runner lacplacp-staticdynamic如果两边模式不对齐轻则只有一条链路转发重则端口反复UP/DOWN。我在现场见过最隐蔽的情况是服务器改成了mode 4交换机还停在手工聚合结果LACP协商失败两个口都被交换机丢弃业务全断。排查时要从两端同时看不要只看一端UP就以为通了。6. 实测中的典型故障与排查链路最后讲几个实际项目里高频出现的故障和完整的排查思路。6.1 带宽不叠加/单条大流限速最常见的问题是绑了两个千兆口为什么我传一个大文件还是只有千兆这其实不是故障而是链路聚合的hash机制决定的。链路聚合把流量拆到多条链路上拆分的依据是流的hash比如基于源MAC、目的MAC、IP五元组协议、源IP、目的IP、源端口、目的端口。同一条TCP连接的所有报文hash结果相同会固定走同一条物理链路所以单条大流的最大带宽不会超过单口速率。想看到带宽叠加必须产生多条并发流可以用iPerf3多连接测试iperf3 -c 192.168.10.5 -P 4 -t 30-P 4开启4个并发流如果链路聚合生效总带宽会明显超过单个千兆口。如果并发流仍然只有千兆再查hash策略。默认xmit_hash_policy是layer2只基于MAC层hash同一对主机之间的所有流会落在同一个口上改成layer34后会加入IP和端口参与hash让并发流分布更均匀。这个参数在bond和华为/华三聚合口上都有类似设置两边尽量保持一致。6.2 对端协商失败与重启失效如果cat /proc/net/bonding/bond0看到类似这样的信息Bonding Mode: IEEE 802.3ad Dynamic link aggregation MII Status: up Speed: 1000 Mbps ... Slave Interface: eth0 MII Status: up Speed: 1000 Mbps但发现只有eth0在转发eth1虽然是up却没有流量大概率是交换机的成员口没有全部进入Selected状态。排查顺序是先看交换机侧display eth-trunk或display link-aggregation summary确认两个口都是Selected再看两端模式是否一致最后看光模块和线缆质量。不要一上来就改服务器配置先通过两端状态缩小范围。重启失效是另一个高频问题。很多时候配置完当时能跑但服务器一重启bond0就消失或者只有一块网卡起来。原因通常有三个bonding模块没有开机加载比如忘了写/etc/modules-load.d/bonding.conf网络服务启动顺序问题从口先于bond接口启动网口名漂移导致interfaces或ifcfg里写的接口名对不上。针对这三个原因建议按清单核对CentOS上确认NM_CONTROLLEDno和ONBOOTyes写对Debian 12上确认allow-bond0关键字和/etc/modules-load.d/bonding.conf都存在最后用journalctl -u networking或journalctl -u NetworkManager看启动日志里有没有明确报错。6.3 排查工具先用/proc再用抓包排查链路聚合我的习惯是从内核状态开始逐层往外查。首先看cat /proc/net/bonding/bond0关注Bonding Mode、MII Status、Slave Interface、Speed这几个关键字段。team方案用teamdctl team0 state。这一步能确认驱动层是否正常。然后看物理口统计ethtool eth0 ethtool -S eth0 | grep -E rx_errors|tx_errors|dropped如果有大量错误包和丢弃包通常是对端协商或物理链路问题。到这里还没定位就上抓包工具tcpdump -i bond0 -n host 192.168.10.5 tcpdump -i eth0 -n host 192.168.10.5分别在bond0和从口上抓包对比相同业务的报文是否从两个从口都出来能直观验证hash策略是否生效。比如两条并发流eth0和eth1各抓到一些说明负载均衡正常如果全落在eth0上说明hash策略需要调整或者第二条链路没有真正参与转发。LACP协商本身可以在交换机侧抓LACP报文也可以看display lacp statistics里的计数。如果LACP报文一直在发但收不到对端回应基本就是两端模式不匹配或者中间链路设备把组播帧处理掉了。最后说一点我自己的体会做双网卡绑定最怕的不是命令不会敲而是没想清楚就动手。冗余场景优先mode 1或activebackup带宽场景优先mode 4或lacp runner服务器和交换机的模式要严格对齐。如果是在工业设备上做先固定网口命名再配置绑定最后做一次拔线测试和重启测试。这四步都跑通了项目才算真正收尾。
