上个月公司机房扩了一台文件服务器,采购的时候按厂商建议配了两张千兆网卡,说好是做 bond 聚合、双倍带宽。机器上架那天我从监控看过去,这台机器的入向流量死死卡在 940Mbps 上下,永远摸不到 1.8G 的天花板。用 iperf3 实测更直接:单线程跑 bond0 只有 940M,改成多线程才勉强上到 1.7G 左右。
如果你正在给服务器做双网卡聚合、或者准备买双口万兆卡,这里可以先看看这几家的机器做参考:RackNerd(全球VPS,特价常推)、狗云DOGYUN(高性价比云服务器,多机房可选),另外还有 Zenlayer(全球多地区节点,海外业务首选) 这类可选。做聚合之前先把交换机的配置摸清楚,别等机器上架了才发现瓶颈在机柜那侧。
客户一开始怀疑是 bond 配错了,网卡驱动、MTU、xmit_hash_policy 我全查了一遍,配置没毛病。真正的根因藏在交换机上那台接入交换机根本不知道这两条线是一组的,它把两个物理口当成两个独立端口,各自跑各自的 MAC 学习表。结果就是服务器把流量从 eth0 出去,回来的时候交换机却可能从 eth1 送,链路一交叉, bonding 就自动把这条链路判定为失效,只剩一条在干活。

bond 的几种模式,先搞清楚你到底想要什么
很多人以为"绑两张卡"就等于"带宽翻倍",这是Linux bonding 里最常见的误解。/etc/sysconfig/network-scripts/ifcfg-bond0 里的 BONDING_MODE 决定了聚合的语义,选错了模式,配置文件写得再漂亮也没用。日常用得上的主要是这么几个:
mode 0(balance-rr,轮询):报文按顺序从各 slave 轮着发出去,不看 MAC 和 IP 哈希。优点是简单,吞吐能叠加;致命缺点是每块网卡都会收到所有流量交换机那边两台机器的 MAC 都得泛洪,容易触发 STP 收敛抖动,老老实实用单 IP 的场景一般不建议。
mode 1(active-backup,主备):同一时刻只有一块卡在发,另一块纯热备。主备切换只花几十毫秒,配置简单,是文件服务器、数据库这种"要稳不要极致带宽"的默认选择。缺点也很明显:带宽始终只有一条链路的水平,两张千兆卡也就是 940M。
mode 4(802.3ad / LACP):这就是我们这次卡了两周的模式。它要求交换机侧必须配好 LACP 聚合组,两边才能协商出一条逻辑链路。两端支持的话,mode 4 既有 mode 0 的带宽叠加,又有 mode 1 的冗余切换能力,是生产环境的正解。问题也正在这里交换机的聚合组没配,服务器的 bond0 就退化成了一条普通链路。

排查第一步:看 /proc/net/bonding,别猜
bond 的运行状态全在 /proc/net/bonding/bond0 里,这个文件是排查聚合问题的第一站,比任何猜测都靠谱。我一般先看三段:
第一段是 Bonding Mode,确认内核实际生效的 mode 跟你写的一致。有些老系统 BONDING_MODULE_OPTS 写错了也不会报错,只会静默不生效。
第二段是 MII Status / Speed / Duplex,看每块 slave 的协商结果。千万要留意 Speed 这一行如果有一块卡是 Unknown 或者 10 Mbps,说明物理链路或者模块有问题,跟 bonding 配置无关。
第三段是 Slave Interface 列表和每条 slave 的状态。我们那台机器当时的状态很微妙:两块卡 MII Status 都是 up,但 slave 2 的 Actor Oper Key 和 Partner Oper Key 一直是空的这正是 LACP 没协商上的典型特征。如果 mode 4 真的协商成功,这里会显示双方一致的 Key 值,而且两边都有独立的 lacp_actor 状态。
顺便说一个坑:/proc/net/bonding/ 下面还有 bond_mono_mode 之类的监控文件,但最实用的其实是在 ip -s link show bond0 里对比各 slave 的 TX/RX bytes。如果两块卡的字节数差异巨大,说明哈希策略把流量全压在了一条链路上。

根因:交换机侧的 LACP 聚合组没建
我们最后定位到的问题很朴素:接入交换机上,服务器接的两个端口都是普通的 access 端口,属于同一个 VLAN,但没有加入任何 LACP 聚合组,更没有配 802.3ad 模式。
服务器这边 BONDING_MODE=4、BONDING_LACP_RATE=fast 都写对了,可交换机那头根本不发 LACP 帧,协商无从谈起。Linux 内核在这种情况下会有个很有意思的表现:它会尝试把 bond 降级成 active-backup,于是一切"看起来都正常"链路是 up 的、IP 是通的、ping 得过去,只是带宽永远只有 940M。我们排查时被这个"假成功"绕了整整两天。
交换机侧的改法:以华为 S5720 为例,先建聚合组把两个物理口加进去,再配 LACP 模式为 lacp(对应动态聚合),端口速率和双工跟单口保持一致,最后把 access VLAN 配成跟原来一样。这里最容易踩的是第三条很多人建了聚合组却顺手把 VLAN 改了,业务立刻断。还有一点,聚合组里的成员口必须属于同一 VLAN,跨 VLAN 不能聚合。
改完交换机,服务器侧不用重装,只是 ifdown bond0 && ifup bond0 重载一次链路,重新协商就能看到 LACP 状态了。为了保险,重启前先 cat /sys/class/net/bond0/bonding/lacp_rate 确认速率设成了 fast(30 秒协商)而不是 slow(30 秒一轮,慢得让人怀疑人生)。

让聚合真正跑满:哈希策略和三个细节
协商上之后,还有几个参数直接决定聚合能不能跑满带宽:
一、xmit_hash_policy 要按业务选。默认是 layer2,只用源 MAC 做哈希意味着同一台客户端的所有流量都会压在同一条链路上,聚合等于白做。改成 layer3+4 之后会加上 IP 和端口参与哈希,多客户端场景下分布会均匀很多。但要注意,如果你的业务是长连接大流量(单连接持续跑满一条线),无论怎么改哈希都还是一个连接一条链路,这时候只能靠业务侧多开连接。
二、miimon 和 updelay/downdelay 决定切换速度。miimon=100 表示每 100 毫秒探测一次链路,downdelay=200 表示确认掉线后等待 200 毫秒再切走。这两个值太小会在链路抖动时频繁切换(对 NFS、数据库这种有状态连接是灾难),太大又会拉长故障切换时间。默认的 miimon=100 / updelay=0 / downdelay=0 适合手工环境,线上建议 downdelay 给到 200 以上。
三、MTU 一定要两端一致。bond 口的 MTU 不会自动继承到 slave 上,得手动在每块 slave 的配置文件里也写上同样的 MTU=9000(如果是万兆组网)。我们这次测 1G 万兆卡时出现过 jumbo frame 一端开了另一端没开的怪事,表现同样是吞吐上不去。
四、arp_interval 在 mode 0/1 下要设成 0。这是官方文档里明确写的:mode 0 和 mode 1 下开着 arp_interval 会导致 ARP 应答在两条链路上来回乱发,MAC 表震荡。

实测数据与最后几条经验
改完之后我们的实测结果是这样的,可以给个参考:
单条千兆链路 iperf3 跑满是 938Mbps 左右(千兆链路的正常损耗,扣掉以太网开销和协议头就是 940 上下);两张千兆做 mode 4、哈希策略设 layer3+4、四个并发流跑,满载能到 1.83Gbps;如果用单流压测,只能到 940M 多一点,这是哈希机制决定的,不是故障。
现在这台文件服务器还挂着一次拔网线的演练:拔掉 eth1 的线,bond0 在 约 210 毫秒内切到 eth0,NFS 会话断 2 到 3 秒自动重连,业务没感知。要是在 downdelay=0 的配置下,同样的拔线只切 20 多毫秒,但代价是链路轻微抖动就误切换。
最后把踩过的坑压成几条:第一,别在没确认交换机支持 LACP 的情况下就用 mode 4,它会静默降级成 active-backup,不看日志根本发现不了。第二,ip link show 里看到 bond 是 up 不代表聚合协商成功,一定要看 /proc/net/bonding/ 里的 Actor/Partner Oper Key。第三,别指望单连接跑满聚合带宽,多流并行才是聚合的正确用法。第四,交换机聚合组的 VLAN 一定要跟原来的业务 VLAN 一致,改 VLAN 前先备份配置。
说到底,双网卡聚合这事儿的难点从来不在 Linux 那一侧nmcli 或者 ifcfg-bond0 配好就完事了。真正花时间的是机柜里那台交换机:谁建的组、成员口是哪些、VLAN 对不对、是不是 dynamic 聚合,这些东西不在交换机上看一眼,谁也别想靠猜。


喜欢
顶
难过
囧
围观
无聊



