Linux网卡绑定bond七种模式详解:选型原理与配置避坑
Linux系统下的网卡绑定 bond用哪种方式做运维和系统集成的人几乎都会被问到同一个问题服务器要配网卡绑定到底用哪种模式每次遇到这种问题我都要先反问一句你绑定的目的是什么你的交换机支持什么你的业务承受得起切换时间吗多数情况下提问的人自己也没想清楚这三件事只是听说bond能提高带宽、能冗余就冲上去配了结果不是链路起不来就是带宽没提升甚至网络还更不稳定。这篇文章我就把 Linux bonding 的七种模式逐个拆开讲清楚包括它们的原理、适用场景、选型思路以及我在实际配置里踩过的一些坑。看完之后你应该能自己判断哪种方式最适合当前环境而不是照抄网上的模板配置。1. 做bond之前先搞清楚你到底需要什么1.1 三种核心需求冗余、带宽、还是两者兼顾网卡绑定的核心目的大概只有三类。第一类是链路冗余也就是一根网线断了、一个交换机端口坏了或者物理网卡本身挂了另一条链路能立刻顶上业务不中断。第二类是带宽提升把两块千兆网卡绑在一起期望获得接近 2Gbps 的吞吐能力。第三类是两者兼顾既要冗余也要带宽。这三类需求对应的 bond 模式完全不同。如果只要冗余最稳妥的方案是 mode 1主备模式所有流量走一块网卡另一块热备不需要交换机做任何配置。但如果你想要带宽叠加事情就没那么简单了多半需要交换机配合而且还要看你的流量模型长什么样。单一 TCP 连接能不能跑满聚合带宽取决于哈希算法如果只有少数几个大连接很可能聚合之后带宽还是原来那一份。先想清楚需求再选模式。这个顺序不能反过来。1.2 看懂bond模式的报数字命名Linux bonding 的七种模式在配置里用 mode 参数表示数字从 0 到 6。它们分别是mode 0balance-rr轮询mode 1active-backup主备mode 2balance-xor异或哈希mode 3broadcast广播mode 4802.3ad动态链路聚合LACPmode 5balance-tlb自适应传输负载均衡mode 6balance-alb自适应负载均衡这七个数字看起来简单但每个背后都是一套不同的数据分发逻辑和外部依赖条件。有人记不住就死记0 轮询、1 主备、2 异或、3 广播、4 聚合、5 传输均衡、6 全均衡这样至少能对上号。但真正选型时还要知道哪些模式需要交换机支持哪些是 Linux 本机就能搞定的。需要理解的一点是bond 的工作位置在内核的网卡驱动层之上。它把多块物理网卡虚拟成一个 bond 接口上层应用只看到 bond0。内核负责决定每一个数据包或者每一次连接交给哪块物理网卡发送这就是所谓的发送负载均衡策略而接收方向的流量如何分布很多模式其实控制不了只能靠交换机做负载分担或者靠网卡的 ARP 应答逻辑来做均衡。1.3 决定选型的两个外部边界条件先看交换机。mode 0、mode 2 需要交换机支持静态端口聚合也就是 manually 配置 EtherChannel 或者端口组mode 4 需要交换机支持并启用 LACP802.3ad 动态聚合协议。mode 1、mode 5、mode 6 不需要交换机做任何额外配置。这个差异直接影响网络团队的工作量也是很多服务器管理员首选 mode 1 的原因因为不用求人。再看物理网卡驱动。mode 5 和 mode 6 依赖网卡驱动具备一些特定能力例如支持改 MAC 地址、支持 TSO/GRO 等特性的配合。绝大多数主流服务器网卡如 Intel 的千兆/万兆卡、Mellanox 的网卡都兼容但个别老驱动或特殊虚拟网卡比如某些云平台里的虚拟网卡、低配的 USB 网卡就有兼容性问题。所以选型之前先查一下网卡驱动对 bonding 的兼容情况能省掉后面很多调试时间。还有一个容易忽略的边界条件虚拟化环境。如果这台服务器上跑着 KVM 虚拟机bond0 往往作为 Linux bridgevirbr0/br0的上联口。这种情况下bond 模式的选型要格外谨慎因为 bridge 和 bond 叠加时mac 地址学习、STP 转发延迟、流量对称性都会互相影响。我后面在常见问题部分专门展开讲。2. 七种bond模式逐个拆开讲2.1 mode 0balance-rr轮询转发我一般不推荐mode 0 的工作原理最简单内核对每个数据包按顺序在多个物理网卡间轮流发送。第一个包走 eth0第二个包走 eth1第三个又回到 eth0。这种策略对 CPU 消耗很小代码路径也短理论上可以把多块网卡的发送能力完全叠加起来因为它是包级别的负载均衡不是连接级别的。但问题在于包级别的负载均衡要求接收端也必须配合。如果你在交换机上把两个端口做了静态链路聚合EtherChannel交换机对收到的包会做哈希分发到不同物理链路这时 bond 的轮询发送才能和交换机的接收分发策略匹配。如果交换机没配置聚合两个端口独立工作交换机收到来自同一个源 MACbond0 的 MAC的包出现在两个不同端口上就可能造成 MAC 地址漂移交换机的 MAC 表会在两个端口间来回抖动导致严重丢包。同样服务端收到数据包时如果两个端口都收到了同一个连接的数据也可能出现乱序。还有一个很大的坑mode 0 对单一大流量的聚合效果很差。假设你只有一条 TCP 连接在下载文件这条连接的包会被轮询拆到两块网卡上发送但因为 TCP 严格要求数据包按序到达接收方的 TCP 层要等乱序的包补齐才能继续处理实际上吞吐可能比单网卡还低。这就是典型的看似聚合实则降级。所以除非你的业务是大量小连接并发比如 DNS 查询、短连接 API 调用而且交换机做了正确的 EtherChannel否则不推荐 mode 0。2.2 mode 1active-backup主备冗余最稳妥的基础款mode 1 的逻辑非常朴素同一时间只有一块物理网卡处于 active 状态承载所有流量另外一块或者几块网卡处于 backup 状态不接收任何数据流量。只有当 active 网卡出现链路故障时内核把 MAC 地址切换到 backup 网卡上流量才瞬间切换过去。这个模式最大的优势是零依赖。它不要求交换机支持聚合不要求交换机端做任何配置也不要求物理网卡支持特别的功能。随便拿两台傻瓜交换机分别插一根网线到服务器的两块网卡上配好 mode 1就能实现链路冗余。硬件上只要不做广播风暴防护这两根线都能用坏了其中一根线另一根还能跑。切换速度取决于链路检测方式用 miimon 检测的情况下100ms 到几百毫秒就能完成切换对大部分业务足够。mode 1 的缺点也很明显带宽不能叠加。两块千兆网卡绑定实际还是只能跑 1000Mbps不是 2000Mbps。如果你需要的只是高可用而对带宽没有扩容要求mode 1 是首选。实践中我经常用 mode 1 做混合场景两块网卡分别连接到两台不同的交换机。这样不仅网卡和网线有了冗余交换机单点故障也一并规避了。这种拓扑是 mode 1 最典型的玩法比连同一台交换机的两个端口强得多。2.3 mode 2balance-xor老牌静态聚合正在被LACP取代mode 2 的发送策略是用哈希算法决定数据包走哪块网卡。默认的哈希算法是基于源 MAC 和目的 MAC 做 XOR 运算得到一个索引然后映射到对应的物理网卡。因为同一个连接源 MAC 和目的 MAC 固定的包哈希结果一致所以同一个连接会固定走同一块网卡不会像 mode 0 那样出现乱序问题。这个模式对交换机的要求和 mode 0 一样需要静态配置 EtherChannel 或端口组。交换机会把两个端口绑定为一个逻辑链路同时也会做类似的哈希把流量打散到两条链路上。如果交换机没有配置后果和 mode 0 一样会出现 MAC 地址漂移和随机丢包。mode 2 相比 mode 0 的优势在于它保持连接级一致性这对 TCP 很友好。但问题是它自身不会感知交换机端的聚合配置是否匹配。你必须在 bond 配置里把 xmit_hash_policy 设置得和交换机的哈希算法尽量一致才能让双向流量均匀分布。哈希策略默认是 layer2只按 MAC 哈希如果网络里只有一个网关、所有流量进出都走同一个 MAC哈希结果会非常集中导致负载严重不均。可以考虑改成 layer34按 IP 和端口哈希但这要求交换机也支持三层四层哈希否则还是不均匀。现在新采购的交换机基本都支持 LACP我很少在新项目里推荐 mode 2 了。它的价值主要体现在老设备上交换机的静态聚合配置比较成熟且内核版本老到不支持 802.3ad 协商时mode 2 还能凑合用。2.4 mode 4802.3ad真正的动态链路聚合生产环境首选mode 4 应该是我在生产环境里用得最多的模式了。它基于 IEEE 802.3ad 标准也就是 LACPLink Aggregation Control Protocol。服务器和交换机之间通过 LACP 协议协商动态建立聚合链路互相确认对方能把哪些端口合在一起然后自动开启负载分担。相比 mode 2 的我假装聚合了mode 4 是我们商量好了再一起干。配置 mode 4 的前提是交换机端必须启用 LACP而且通常建议配置为 active 模式主动发起协商或者至少 passive 模式等待对方发起。交换机的聚合端口可以静态指定也可以动态协商。在 Linux 这边bond 的 lacp_rate 参数可以设置成 fast每秒发一次 LACPDU或 slow每 30 秒发一次一般推荐 fast这样链路状态变化时收敛更快。mode 4 的负载均衡效果取决于哈希策略。与 mode 2 一样默认是 layer2我建议在配置里显式设置 xmit_hash_policylayer34让哈希基于 IP 和端口这样多连接场景下流量能更均匀地打散到多块网卡。不过要记住一点即使做了 LACP单条 TCP 连接的吞吐依然受单块物理网卡的带宽限制因为同一个连接固定走同一块网卡。LACP 不改变这一点它只是在并发多连接的情况下把总吞吐叠加起来。很多人的误区就在这里以为绑了两块万兆网卡就一定能跑 20Gbps实际用 iperf 单线程测出来还是 10Gbps就以为配置失败了。这不是配置问题是单连接无法跨网卡并行传输的固有限制。2.5 mode 5balance-tlb和 mode 6balance-alb不用交换机配合的均衡方案如果你的交换机比较老旧或者网工不配合没法配置端口聚合但又想获得多网卡带宽叠加的效果可以看看 mode 5 和 mode 6。mode 5balance-tlb是自适应传输负载均衡发送方向由 Linux 内核根据每块物理网卡的实时负载情况动态分配接收方向仍然只有 active 网卡在工作。因为内核知道每块网卡的队列深度和繁忙程度所以可以把新的发送连接分配给相对空闲的网卡从效果上让多块网卡的发送吞吐都能被利用起来。接收方向单一链路那对下载类流量就没有带宽叠加效果了。mode 6balance-alb在 mode 5 的基础上增加了接收方向的负载均衡。它的原理是让 bond 接口在 ARP 应答时根据源 IP 的不同返回不同的物理网卡 MAC 地址从而让对端把流量分发给不同的网卡。也就是说当来自不同 IP 的请求发来 ARP 询问时bond 会轮流用自己的 eth0 MAC 和 eth1 MAC 去应答这样对端就会把数据发送到两块网卡上。这个机制要求 bond 接口能够修改物理网卡的 MAC 地址而且要求物理网卡在接收时不能有奇怪的硬件过滤策略。现代主流网卡和驱动大多支持。但 mode 6 有一个明显的问题对 ARP 应答的劫持和修改在某些环境里会和交换机端口安全、DHCP Snooping、防火墙的 MAC 绑定策略冲突。比如交换机开启了端口安全只允许第一个学习到的 MAC 通过那 mode 6 的 ARP 应答一改 MAC就可能导致数据被交换机丢到黑洞里。另外mode 6 对虚拟化桥接环境特别不友好br0 的 MAC 学习和 ARP 行为叠加后很容易出现虚机网络闪断。我个人的经验是mode 5 可以在部分场景下用mode 6 尽量少碰除非你明确知道网络设备不限制 MAC 变化。2.6 mode 3broadcast广播模式特殊场景才用mode 3 的机制是把每一个包同时在所有物理网卡上发送一份。接收端会收到重复的数据包一般的协议栈会根据帧的序列或其他信息丢弃重复包。这个模式几乎没有负载均衡的意义带宽无法叠加反而会成倍增加网络流量。它的唯一好处是极高的容错性任何一块网卡还能工作数据就能送出去而且因为是同时发多份切换恢复几乎无感知。实际场景里mode 3 很少被使用除非你对数据冗余的要求极其极端比如某些金融场景的撮合链路宁可流量翻倍也不允许丢包。还有极少数情况协议栈不支持快速检测故障用广播模式可以规避切换时第一个包丢失的问题。但对多数人来说mode 3 属于知道存在就行的模式。3. 选型对照表与决策流程3.1 七种模式对比速查表模式名称带宽叠加高可用交换机要求典型适用场景风险点0balance-rr可以可以静态聚合高并发小包连接乱序、MAC漂移1active-backup不可以可以无一切求稳的环境带宽不变2balance-xor可以可以静态聚合老交换机环境哈希不均3broadcast不可以极强无极端容错流量浪费4802.3ad可以可以LACP生产环境首选单流带宽受限5balance-tlb发送叠加可以无发送密集型业务接收不均衡6balance-alb双向叠加可以无免交换机部署ARP/MAC问题3.2 我自己的选型决策思路我的个人决策流程很固定基本就这么几步。第一步问清楚网络团队能不能在交换机上配端口聚合。如果能配 LACP直接上 mode 4没什么好犹豫的。这是标准答案所有设备都原生支持协商机制成熟运维排障也方便。如果交换机太老只能配静态 EtherChannel那就 mode 2把哈希策略调整好。第二步如果交换机没法配合比如服务器同时接在两台不同的交换机上做跨设备链路冗余那就只能放弃带宽叠加用 mode 1。这种场景下你图的是高可用不是带宽mode 1 最安全。第三步如果既想加带宽又没交换机配合而且业务是发送密集型比如大量对外推流、数据同步发送可以考虑 mode 5。但一定要把网卡驱动的兼容性测一遍尤其是要确认它能不能正确报告链路状态和负载。第四步如果是虚拟化宿主机bridge 加 bond 的组合默认建议 mode 1 或者 mode 4取决于交换机配合度。mode 0、mode 2 这类依赖交换机静态聚合的模式在 bridge 环境下更容易出幺蛾子。通俗点说求稳用 1求快用 4交换机不给力用 5老设备凑合上 2没事别折腾 0 和 6。4. 手把手配置bond4.1 传统ifcfg配置文件方式虽然现在很多系统转向了 NetworkManager但传统的 /etc/sysconfig/network-scripts/ifcfg-* 方式在 CentOS/Rocky 等系统上依然非常好用尤其是不想引入额外服务依赖的脚本化部署场景。以绑定两块网卡 eth0 和 eth1 成 bond0 为例需要创建或修改以下文件。先创建 bond0 的主配置文件 ifcfg-bond0DEVICEbond0 NAMEbond0 TYPEBond BONDING_MASTERyes BOOTPROTOnone ONBOOTyes IPADDR192.168.10.10 NETMASK255.255.255.0 GATEWAY192.168.10.1 BONDING_OPTSmode4 miimon100 xmit_hash_policylayer34 lacp_ratefast然后修改 eth0 的配置文件把 IP 配置全部去掉只留物理网卡和 bond 的隶属关系DEVICEeth0 NAMEeth0 TYPEEthernet BOOTPROTOnone ONBOOTyes MASTERbond0 SLAVEyeseth1 同样处理把 DEVICE 和 NAME 换成 eth1。这里有个细节如果原来的网卡配置里由 NetworkManager 管理可能需要在配置里加上 NM_CONTROLLEDno 来避免冲突。但统一配置完以后我更推荐直接用 NetworkManager 的 nmcli 来做更不容易出现因为配置文件和实际服务状态不一致造成的诡异问题。重启网络服务后用 ip addr show bond0 查看 bond 接口是否正常起来。如果看到 bond0 有 IP、eth0 和 eth1 都处于 state up基本就成了。4.2 使用nmcli配置bond现代的 RHEL/CentOS/Rocky 8/9 系统默认用 NetworkManager用 nmcli 配 bond 比手改配置文件更顺手也更容易避免格式错误。核心命令大概长这样nmcli connection add type bond con-name bond0 ifname bond0 mode 4 \ ipv4.method manual ipv4.addresses 192.168.10.10/24 \ ipv4.gateway 192.168.10.1 nmcli connection add type ethernet con-name eth0 ifname eth0 master bond0 nmcli connection add type ethernet con-name eth1 ifname eth1 master bond0用 nmcli 创建 bond 时可以顺便把 bond 选项写在连接配置里。比如设置 miimon 和哈希策略nmcli connection modify bond0 bond.options mode4,miimon100,xmit_hash_policylayer34,lacp_ratefast创建完以后执行 nmcli connection up bond0 让配置生效。查看状态用 nmcli device status看 bond0 的从属接口是否都处于 connected。有一点要注意nmcli 在创建 ethernet 从接口时如果该网卡之前已经有别的连接配置需要先把旧连接删掉否则会冲突。实际操作里我最常遇见的问题就是网卡被装了云平台自带的 NetworkManager 连接配置结果 master 参数写不进去只能先 nmcli connection delete 清掉旧的。4.3 加载bonding模块和驱动参数配置文件中 BONDING_OPTS 是最直接的参数入口但如果模块加载时就需要指定参数也可以在 /etc/modprobe.d/bonding.conf 里设置alias bond0 bonding options bonding mode4 miimon100 xmit_hash_policylayer34 lacp_ratefast这里要扫一眼 miimon 和 downdelay/updelay 的含义。miimon 是链路检测间隔单位是毫秒100 表示每 100ms 检查一次物理链路状态标准配置一般 100。downdelay 是确认网卡状态从 up 变为 down 的额外等待时间updelay 是恢复 up 时的额外等待时间。这些参数的意义在于防止链路抖动导致 bond 频繁切换。还有个容易被忽略的参数primary。mode 1 下如果希望某块网卡优先作为 active比如 eth0 连核心交换机、eth1 连备份交换机可以设置 primaryeth0。这样 eth0 恢复后会自动切回不至于一直在备用链路上跑。4.4 配置后的验证手段配置完不能只看 IP 通就完事至少要做几项验证。第一查看 bond 模式和当前活动状态cat /proc/net/bonding/bond0这个文件里能看到 Bonding Mode、MII Status、Slave Interface 的具体列表以及 mode 4 下 LACP 的协商状态partner 信息。如果 mode 4 配置成功能看到每个 slave 的 partner 都显示为一个有效的 LACP 系统 ID 和端口号如果交换机没协商成功partner 信息会是空的或者 unreliable。第二用 ethtool 检查每块物理网卡的速率和协商状态确认是同速率比如都是 1000Mbps避免一块千兆一块百兆导致聚合后链路流速不一致。第三做流量的连通性测试和 failover 测试。ping 网关持续跑着然后手动把 active 网卡的网线拔了观察 ping 丢包情况。mode 1 拔掉主网卡后应该几乎无感知mode 4 拔掉一块网卡后剩下的链路继续工作丢包也只是短暂的。这个测试一定要做很多配置问题等到真正故障时才暴露代价太大了。5. 常见问题与避坑经验5.1 链路切换慢ping 丢包几十个最常见的原因是 miimon 设得太长或者没有设 downdelay/updelay 导致抖动误判。miimon 默认值是 0也就是不检测链路状态这种情况下网线断开后 bond 根本感知不到数据照旧往断掉的网卡上发必然大量丢包。把 miimon 设到 100正常切换应该控制在几百毫秒内。如果用的是 mode 1并且接在两台交换机上还要检查交换机端口的 STP生成树协议是否导致端口从 blocking 到 forwarding 延迟过长。很多交换机默认的 STP 收敛时间是 30 秒链路恢复后 backup 网卡要等端口进入 forwarding 状态才能切换回来。这种情况下可以尝试把接入端口配置为 PortFast / edge port或者在交换机侧优化 spanning-tree 的计时参数。5.2 MAC地址漂移导致交换机疯狂刷新转发表这个问题几乎都出在 mode 0 或 mode 2 且交换机未配置聚合的场景。服务器同一 bond0 MAC 在两个物理端口交替出现交换机的 MAC 地址表在两个端口之间来回跳跃表现是整段网络间歇性丢包、延迟抖动。排查方式很直接在交换机上查看该 MAC 地址所在的端口如果频繁变化基本就是聚合配置不匹配。解决方法是先在交换机上做 EtherChannel 或 LACP再启用 mode 0/2/4。如果交换机确实做不了那就切换 mode 1 或 mode 5/6。不要试图用静态 ARP 或者关闭 MAC 学习来糊弄那只会掩盖问题。5.3 虚拟化宿主机 bridge bond 的特殊坑在 KVM 宿主机上bond0 通常被桥接给虚拟机使用。mode 0 和 mode 6 在这种环境下的表现尤其不理想。原因在于 Linux bridge 的转发逻辑会学习虚拟机 MAC 地址如果 bond 在不同物理网卡之间切换bridge 需要时间重新学习结果就是虚拟机时不时断流几秒。经验做法是宿主机上跑虚拟机时bond 用 mode 1 或 mode 4同时确保 bridge 的 stp 模式关闭多数虚拟化场景不需要 STP并且开启 bridge 的 vlan filtering 按需配置。尽量不要在同一个 bond 上同时承载宿主机管理流量和虚拟机业务流量除非你很清楚限流和故障域。5.4 mode 4 下lacp_rate设置不当导致协商异常有些交换机的 LACP 只支持 slow 模式如果 Linux 侧设置了 lacp_ratefast交换机不响应 fast LACPDU设备之间无法协商成功。遇到这种情况先把 lacp_rate 改回 slow再确认交换机对接的端口确实启用了 LACP。还有一个小概率情况交换机的 LACP 端口被配置成了 passive而 Linux 侧因为某种原因没有主动发出 LACPDU。Linux bonding 驱动通常默认会主动协商但如果模块参数有问题或者配置顺序不对也可能出现两边都在等对方先说话的情况链路就是起不来。可以把交换机端改成 active确保至少有一方主动。5.5 单条TCP连接速度始终上不去这个问题我在前面已经提过再强调一次。只要哈希策略是按连接划分的单条 TCP 流永远跑不过单块物理网卡的带宽。测试的时候必须用并发多连接比如 iperf3 加 -P 8 或者 -P 16看到总吞吐接近多网卡叠加才说明配置有效。如果单线程测速不够就去检查哈希策略是否设成 layer34因为仅按 MAC 哈希时所有流量默认都走第一个 slave完全没有均衡效果。5.6 拔了网线状态没变化bond认为链路仍然up这是驱动兼容性的典型表现。部分网卡驱动不主动反馈物理链路断开事件单纯靠 miimon 轮询在某些情况下也检测不到比如对端交换机端口还在 administratively up 状态、光模块和光纤的链路信号未消失只是中间链路中断。此时可以用 arp_ip_target 参数做额外的链路探测让 bond 通过 ping 一个已知 IP通常是网关来判断链路是否真的可用。mode 1 下设置多个 arp_ip_target 可以大幅提高故障感知准确性。写在最后的一些经验我配置 bond 这几年最大的体感是模式选型七分在需求拆解三分在配置参数。很多人在 mode 0 和 mode 4 之间反复横跳其实是没想明白交换机和流量模型的约束。我的习惯是先测通场景再谈调优尤其是生产环境永远先上 mode 1 兜底确认高可用没问题再逐步尝试 mode 4 做带宽叠加。没有绝对的最好模式只有最适合当前网络环境和业务诉求的方案。最后送大家一个排障小技巧不管用什么模式都养成看 /proc/net/bonding/bond0 的习惯。这个文件把链路状态、活跃网卡、LACP 协商信息全都摆出来了比任何图形化工具都直观。每次配置完或者故障时第一件事就是 cat 一下这个文件很多问题的答案都写在里面。