ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux Bonding 全解析:链路聚合模式选型与VXLAN叠加实践

Linux Bonding 全解析:链路聚合模式选型与VXLAN叠加实践 搞网络的人迟早都要碰一次接口聚合这件事。不管是服务器双网卡做冗余还是为了让业务带宽从千兆提到两千兆Linux 下的 Bonding 聚合链路几乎是绕不开的标准答案。这篇文章不打算把bonding模块文档翻译一遍而是从实际工程角度把模式选型、配置落地、以及与 VXLAN 叠加网络配合时容易踩的坑讲清楚。适合刚接手服务器网络配置的运维新人也给老手提供一个排查思路的参考。1. Bonding 到底是什么为什么我们还离不开它1.1 一个逻辑接口的诞生Bonding 在 Linux 里的本质是把两块或者多块物理网卡比如eth0、eth1绑定成一个逻辑网卡比如bond0。从上层协议栈看bond0就是一个普通的网络接口IP、路由、iptables 规则都挂在它上面。但数据在底层怎么走是走网卡 A 还是网卡 B或者同时走两块——这套分配逻辑完全由 bond 驱动决定。这不是什么新概念bonding模块在内核里存在了很久了属于经典得不能再经典的网络功能。但经典不代表过时恰恰相反绝大多数生产环境的物理机、虚拟化宿主机至今仍然靠它兜底。我自己维护的服务器里有不少跑着关键业务的机器网卡硬件难免有抽风的时候靠单块网卡撑着实在不踏实。绑定成 bond 之后一块网卡断了另一块几毫秒内就能接管流量业务几乎无感知。1.2 两个核心价值冗余与吞吐冗余很好理解主备模式下一块网卡挂了另一块顶上这是最朴素的用法。但很多人忽略的是bond 的价值不止于此。通过合适的模式可以把流量分摊到多块物理网卡上让链路总带宽从 1G 变成 2G 甚至更高。这里的逻辑不是一根水管变两根而是两个泵同时往一个大水池里灌水水管的粗细没有变但总流量上去了。需要提醒的是很多人把 Bonding 和交换机侧的链路聚合比如 Cisco 的 EtherChannel、华为的 Eth-Trunk混为一谈。严格来说它们是一对搭档Linux 侧做 bond交换机侧做聚合两端配合才能既保住冗余又提升带宽。如果只在服务器侧做 bond交换机不知道这回事某些模式下会出现二层环路、MAC 漂移等问题。这也是为什么 802.3adLACP模式在生产环境最受青睐——它有标准协议支撑两端状态清晰可控。2. 七种模式全解析从轮询到 LACP该怎么选2.1 一张表看懂七种模式Linux 的bonding驱动提供了 7 种工作模式从 0 到 6。每种模式的负载均衡策略、容错能力和对交换机的要求都不同。我在实际项目里逐个用过先把结论放在一张表里模式名称负载均衡容错需要交换机支持0balance-rr逐包轮询支持静态聚合两端手工配置1active-backup无一主一备支持不需要2balance-xor按哈希分流支持静态聚合3broadcast所有包发往所有网卡支持静态聚合4802.3ad按哈希分流支持LACP 动态协商5balance-tlb发送自适应接收由当前网卡负责支持不需要6balance-alb发送自适应接收负载均衡支持不需要2.2 各模式的关键差异与适用场景mode 0balance-rr最直观把数据包一个一个轮着发出去网卡 1 发一个、网卡 2 发一个理论上对单条 TCP 流也能用满两块网卡的带宽。问题在于它要求交换机两端做静态聚合否则交换机从一个端口收到包再从另一个端口发出去会把二层拓扑搞乱。而且在某些场景下逐包轮询会导致同一 TCP 流的乱序TCP 协议对这种乱序非常敏感处理不好反而拉低吞吐。所以 mode 0 在当下生产环境其实用得不多除非你已经仔细验证过业务流量特征。mode 1active-backup是绝大多数人第一套配置的起点简单可靠。比如eth0是主网卡eth1是备网卡正常情况下所有流量走eth0当它 down 掉之后由eth1接管。这里有个容易被忽略的点miimon参数决定了链路检测频率默认 100 毫秒也就是说最长可能需要 100 毫秒 切换时间才能感知到链路故障。对于一般业务100 毫秒的抖动还可以接受如果你的应用对网络极度敏感可以把miimon调到 50 甚至 30代价是检测进程的 CPU 开销略有上升但这点开销完全可以忽略。mode 2balance-xor和 mode 3broadcast在生产环境比较少见。mode 2 按源 MAC、目的 MAC 的异或结果选网卡同一个 MAC 对的流量永远走同一块网卡配置简单但要保证交换机两端聚合模式一致。mode 3 更极端所有包同时发给所有网卡纯粹为了冗余对带宽毫无帮助反而浪费。我当时测试 mode 3 时候的唯一收获就是明白了广播式冗余在什么场景下才有价值——对丢包零容忍的金融场景可能有人愿意这么玩但普通业务真没必要。2.3 我为什么不推荐盲目上 LACP 以外的模式接下来重点说说 mode 4802.3ad。这是目前数据中心里最主流的模式因为它引入了 LACP 协议全称链路聚合控制协议服务器和交换机之间通过交换 LACPDU 报文动态协商聚合关系。任何一端链路断了另一端能在协议层面感知并重新计算绑定关系比本地miimon检测更灵活。LACP 还支持快速模式协商周期从 30 秒压到 1 秒故障切换速度更快。但 LACP 不是银弹。它要求交换机端必须显式开启链路聚合并配置成 LACP 动态模式接口速率、双工模式也要匹配。如果你在服务器上配了 mode 4交换机那边忘开了LACPDU 发过去石沉大海bond 接口虽然还是 up 的但根本不收发数据业务直接不通。这种问题出现时最常见的假象是ip link看 bond0 是 UP物理链路也是 UP于是排查方向跑偏到网络层浪费大量时间。后文我会专门写这个问题怎么揪出来。mode 5 和 mode 6 稍微特殊一点它们不需要交换机配合任何聚合配置。mode 5balance-tlb的发送方向按哈希分流接收方向统统由当前活跃网卡负责mode 6balance-alb在此基础上用 ARP 协商实现了接收方向的负载均衡。听起来很美好但这两个模式极度依赖网卡驱动的支持实测下来驱动不配合的话CPU 占用率高且均衡效果差。我的建议是如果你有办法上 switch 聚合直接上 LACP上不了 switch 聚合宁可 mode 1 active-backup也别冒险用 mode 5/6 承担核心业务流量。3. 实操配置从网卡到协议栈把 bond0 跑起来3.1 配置前的硬件检测与规划动手配置之前先在裸机层面做两件事。第一件是确认物理网卡的驱动和固件版本用ethtool -i eth0能看到driver、firmware-version这些信息。比较老的驱动在 mode 5/6 下会有 bug在 mode 4 下也可能出现 LACP 协商异常提前确认可以省掉后续一堆排障时间。第二件是记录各网卡的 PCI 地址和 MAC 地址确保你不会把两块不相关的网卡绑在一起。还有一点容易被新手忽略如果服务器是双口网卡两个口共享同一颗 PCIe 控制器绑定后提升的总带宽受限于该控制器的总线带宽。比如两块 10G 网卡都挂在 x8 的 PCIe 3.0 插槽上理论总带宽大约 8GB/s 左右两块网卡全速跑一共也就到这个上限。换句话说聚合链路的总带宽不是简单的112硬件总线可能是瓶颈。3.2 基于 nmcli 的快速配置RHEL/CentOS 系如果你用的是 RHEL/CentOS 8 或大多数基于 systemd 的发行版NetworkManager是默认网络管理工具用nmcli来配 bond 最干净。下面是一套 mode 4 静态 IP 的完整操作# 1. 创建 bond0指定模式 802.3ad nmcli con add type bond con-name bond0 ifname bond0 mode 802.3ad # 2. 给 bond0 配置 IP根据你网段调整 nmcli con mod bond0 ipv4.addresses 192.168.10.10/24 nmcli con mod bond0 ipv4.gateway 192.168.10.1 nmcli con mod bond0 ipv4.dns 223.5.5.5 nmcli con mod bond0 ipv4.method manual # 3. 配置 bond 详细参数100 毫秒检测LACP fast 协商L34 哈希 nmcli con mod bond0 bond.options miimon100,mode802.3ad,lacp_ratefast,xmit_hash_policylayer34 # 4. 把两块物理网卡加入 bond 作为 slave nmcli con add type ethernet con-name bond-port1 ifname eth1 master bond0 nmcli con add type ethernet con-name bond-port2 ifname eth2 master bond0 # 5. 启动连接 nmcli con up bond0 nmcli con up bond-port1 nmcli con up bond-port2这里有三个地方需要特别留意。第一xmit_hash_policy需要根据你业务流量的特征来选后面我单独说。第二创建 slave 连接时如果 eth1、eth2 原本有旧的 network 配置一定要先清理掉否则会有配置冲突。第三所有命令都在本地执行的情况下网络可能瞬间中断建议通过带外管理口IPMI/iDRAC操作避免把自己锁在外面。3.3 基于 ifcfg 文件的传统配置方式很多存量服务器还在用network脚本管理虽然趋势是迁移到 NetworkManager但我不建议在跑着业务的老机器上贸然切换管理方式。这种场景下直接改/etc/sysconfig/network-scripts/下的文件最稳妥。/etc/sysconfig/network-scripts/ifcfg-bond0DEVICEbond0 NAMEbond0 TYPEBond BONDING_MASTERyes BOOTPROTOnone ONBOOTyes IPADDR192.168.10.10 PREFIX24 GATEWAY192.168.10.1 DNS1223.5.5.5 BONDING_OPTSmode4 miimon100 lacp_ratefast xmit_hash_policylayer34/etc/sysconfig/network-scripts/ifcfg-eth1DEVICEeth1 NAMEeth1 TYPEEthernet BOOTPROTOnone ONBOOTyes MASTERbond0 SLAVEyesifcfg-eth2的内容与 eth1 几乎相同只是DEVICE和NAME改成 eth2。保存文件后执行systemctl restart network或者ifup bond0然后用cat /proc/net/bonding/bond0确认绑定状态。如果看到两块 slave 都显示Status: up说明 bond 建立成功。如果显示Status: down优先检查物理线缆和网卡ethtool状态。3.4 Ubuntu 的 netplan 写法Ubuntu 环境的用户更常见的是netplan。它的配置是 YAML 格式核心是把物理网卡放进 bond 的interfaces列表再定义 bond 参数network: version: 2 renderer: networkd ethernets: eno1: dhcp4: no eno2: dhcp4: no bonds: bond0: interfaces: [eno1, eno2] addresses: [192.168.10.10/24] gateway4: 192.168.10.1 nameservers: addresses: [223.5.5.5] parameters: mode: 802.3ad mii-monitor-interval: 100 lacp-rate: fast transmit-hash-policy: layer34执行netplan apply之后用networkctl status bond0查看状态。写 netplan 最大的坑是缩进YAML 的缩进错误会导致配置无法解析而且报错信息有时候非常隐晦。我自己的经验是写完先netplan generate做语法校验通过再netplan apply。3.5 验证绑定是否成功的常用命令配置完成后不建议马上认为大功告成至少跑三组验证命令。第一组是cat /proc/net/bonding/bond0看当前模式、成员状态、LACP 状态第二组是ethtool eth1和ethtool eth2确认速率和双工模式一致否则 LACP 协商可能出问题第三组是ip -d link show bond0和ip -d link show eth1检查 bond 的 flags 和落网卡上的 bonding 组信息。吞吐测试我也习惯顺手做一遍用iperf3 -c 对端 -P 4 -t 60验证聚合带宽。注意-P 4开多个并发流是为了让哈希策略能利用到多块网卡如果只开单流mode 4 下按哈希可能始终打在同一块网卡上带宽上不去但那是预期行为不代表配置有问题。4. 结合 VXLAN聚合链路之上跑叠加网络4.1 VXLAN 是什么为什么愿意叠加在 bond 上VXLANVirtual eXtensible Local Area Network是一种在普通 IP 网络上封装二层帧的隧道技术。它把原始以太网帧塞进 UDP 报文里外层目的端口固定为 4789从而在三层网络之上构建一个逻辑二层网络。这在云平台多租户网络里几乎是标配KVM/OpenStack/容器网络都会用到。既然 VXLAN 本身是在 IP 网络上封装的那它底层完全可以走 bond 口。把 VXLAN 隧道的物理出口绑定到 bond0 上链路聚合对上层来说是透明的——上层看到的只有 bond0 这个逻辑接口底层网卡故障切换、带宽叠加所带来的好处VXLAN 隧道都能享受到。这也是为什么在做虚拟化宿主机的网络规划时我通常会把 VLAN、VXLAN 这类虚拟网络都架设在一个可靠的 bond 之上。4.2 VXLAN over Bond 的落地配置思路在 Linux 上用 unix 或 ip 命令建 VXLAN 接口时常见的做法是把它 bind 到 bond0 上例如ip link add vxlan100 type vxlan id 100 \ remote 192.168.100.1 \ dstport 4789 \ dev bond0 ip link set vxlan100 up这里的dev bond0是关键参数表示 VXLAN 隧道的底层承载接口是 bond0。之后 vxlan100 这个接口可以像普通二层端口一样纳入 bridge虚拟机或容器的流量走 vxlan100 进出物理路径由 bond0 承担。需要区分的是如果对端只有一个固定 IP作为最简单的 point-to-point VXLAN 确实够用。但如果要建多租户或者多节点的 VXLAN 网络一般会用组播或者分布式控制平面比如 EVPN 控制平面来管理远端 VTEPLinux 自带的 VXLAN 支持已经足够好关键是底层链路务必稳定这就回到 bond 的核心价值上了。4.3 哈希策略对 VXLAN 流量的影响VXLAN 叠加在 bond 上之后最隐蔽也最影响吞吐的问题在于负载均衡的哈希策略。物理网卡的负载分流是 bond 驱动根据外层的源 IP、目的 IP、源端口、目的端口来做的。但 VXLAN 的机制决定了外层报文的源端口是内层流量哈希出来的结果这一点有讲究。如果xmit_hash_policy设成layer2只按 MAC 分流那么从同一个虚拟机出来的 VXLAN 流量外层 MAC 基本都是相同的bond 会把它们哈希到同一块物理网卡聚合带宽形同虚设。改成layer23会好一些但如果 VXLAN 隧道的对端 IP 集中在少数几个网关上外层 IP 的多样性也很有限。最理想的还是layer34它会把外层 UDP 端口纳入哈希计算。但是这里有个真正的坑有些网卡本身带有流哈希卸载RSS/Flow Steering如果 bond 驱动的哈希和网卡硬件层的哈希策略不一致可能仍然无法均摊流量。这时候需要检查网卡驱动的哈希能力必要时关掉网卡层面的 RSS 哈希让 bond 层的哈希统一决定网卡选择。我在一次 40G bond 调优里实测过同样的流量模式layer2模式下只能跑满 40% 的聚合带宽改成layer34之后直接逼近 95%差距非常明显。4.4 交换机侧的视角VXLAN 底层链路也要做好聚合站在交换机角度看bond 出来的两条物理链路连接的是同一个 Eth-Trunk 或 Port-Channel交换机会把这两条链路当作一个聚合组。VXLAN 报文对交换机来说就是普通的 UDP 包交换机会根据报文头里的源目的 MAC、IP、端口做哈希在聚合组里选一条链路转发。所以如果交换机的哈希算法对外层 UDP 端口不敏感或者哈希因子太少就会出现两条物理链路上流量严重不均的情况。排查这类问题时最直接的方法是看交换机聚合口的统计计数观察每个成员口收发的字节数和速率。如果发现一侧速率很高另一侧几乎为 0先别怀疑 bond 配置去检查交换机的聚合哈希策略是否包含了 L4 端口。不少中低端交换机默认只按 MAC/IP 哈希对 VXLAN 这类 UDP 封装流量的均摊能力很差需要手动启用更细粒度的哈希因子。4.5 xmit_hash_policy 的实战选择综合我自己的运维经验如果 bond 下面要承载 VXLAN、NVGRE 这类隧道流量xmit_hash_policy的优先级是首选layer34把 L3 四元组纳入哈希对 VXLAN 这种外层端口随内流变化的封装最友好。次选layer23按 MAC 和 IP 哈希也能凑合但需要确认外层源目的 IP 分布足够分散。尽量避免layer2按 MAC 哈希在隧道场景下基本废掉聚合效果。当然layer34也不是万能的。有些网卡的驱动实现对四元组哈希的支持不完整表现为大量连接仍集中在某一块网卡上。这种时候可以检查网卡的ethtool -k eth1输出看硬件哈希卸载是否开启或者干脆把硬件的 RSS 关掉强制走软件哈希。5. 常见问题与排查实录踩过的坑都在这里了5.1 第一个坑bond0 起来了但业务不通现象很典型ip link看 bond0 是 UP成员网卡也都是 UPIP 能 ping 通 gateway但应用间互相访问不通。这种场景我见过不下五次八成是交换机侧没做聚合或者聚合方式不匹配。排查的第一步永远是看/proc/net/bonding/bond0。如果 LACP 模式下的 bond0 成员状态是Status: up但LACP rate和Active字段显示异常比如Partner MAC是空的基本就是交换机没回 LACPDU。如果交换机配置了静态聚合Linux 用 mode 4 去协商哪怕物理端口 up逻辑上也不会转发数据。解决方式是要么在交换机上开启 LACP要么把 Linux 侧 mode 改成与交换机静态聚合匹配的模式。5.2 第二个坑LACP 协商成功后流量还是只走一块网卡有次聚合后的带宽始终只有单块网卡的上限/proc/net/bonding/bond0里也看不到问题两块成员都显示 up。后来发现是哈希策略的问题。当时场景是大量虚机流量走 VXLAN 隧道外层包的源 MAC 全是宿主机的目的 MAC 全是网关的哈希结果自然永远落在一块网卡上。解决方法是把xmit_hash_policy改成了layer34然后重启 bond。改完之后同样的并发流量两块网卡终于都有像样的速率了。所以当你发现 bond 带宽提不上去时优先检查哈希策略而不是急着换网卡或改 mode。5.3 第三个坑共用一个 IP 的双网卡被交换机误判在早期测试 mode 1 active-backup 时我遇到过切换没有问题但事后交换机上出现 MAC 地址飘移告警。原因是两块物理网卡共享同一个 MACbond 模式下的正常行为而交换机只在一个物理端口上学习到了这个 MAC当备网卡接管流量后另一个端口也出现同一个 MAC交换机就认为有环路。像华为、Cisco 这类交换机通常有 MAC 漂移检测机制默认会杀端口或者打日志。遇到这种情况第一确认 bond 的两块网卡确实共享 MAC这是预期的。第二在交换机聚合口上关闭 MAC 学习告警或配置相应的防飘移策略。如果交换机不支持关闭检测那就要检查是不是有虚拟机或者容器直接绑了 bond 里的某块物理网卡导致额外学了一遍 MAC 地址。5.4 第四个坑手动拔线测试 failover结果恢复时长超出预期很多人配完 bond 觉得就绪了直接手动把主网卡的网线拔了测业务恢复时间。第一次测你会发现业务中断了 10 秒甚至更久第一反应是 bond 切换慢其实大概率不是切换慢而是网络中的 ARP 缓存没刷新。链路切换后TCP 连接对端的交换机、路由器的 ARP 表项还指向旧端口需要等到 ARP 过期重新学习这个时间由网络设备决定。最稳妥的验证方式是使用arping主动发送免费 ARP或者做一次快速的 ping 触发 ARP 刷新。另外一些高性能环境中会配置 BFD双向转发检测来加速感知链路故障不过那属于另一个话题了。在纯 Linux 环境里bond 的miimon检测 交换机配置合理的情况下failover 时间一般能控制在百毫秒级别远达不到秒级。5.5 日常运维里值钱的几条技巧最后整理几条真正值钱的经验所有 bond 相关的变更操作优先通过带外管理接口做不要在 bond 接口自身会话里改配置否则一旦链路切换瞬间断连你就把自己锁在门外了。xmit_hash_policy对 mode 0 和 mode 4 都有效但 mode 0 是逐包轮询不受哈希影响mode 4 里哈希才是命门。挂 VXLAN 等叠加网络时把bond0的 MTU 同步调大因为 VXLAN 额外增加了 50 字节头部默认 MTU 1500 会引发分片或静默丢包。更换网卡固件或驱动版本之后务重复验证一遍 bond 的 failover 和带宽表现驱动更新有时会改变硬件哈希行为。在配置文件中保留好每块网卡的硬件地址和所在槽位现场排查时能帮你快速定位物理拓扑问题。6. 再聊两句我个人的体会在整个服务器生命周期里bond 配置算是典型的一开始觉得简单、越用越有细节的东西。模式选型、哈希策略、交换机配合、叠加网络的兼容性每一层都有值得深挖的空间。我自己踩过的坑里最深刻的不是配置本身写错而是太相信链路 up就代表网络通。后来排查多了才明白bond 只是一个多网卡汇聚的框架真正决定业务稳不稳的是底层物理链路、驱动行为、交换机策略和上层业务流量特征共同作用的结果。所以如果你刚接触这个领域我的建议很直接先把 mode 1 active-backup 跑通再切换成 mode 4 802.3ad 做完整测试。一套 production-ready 的 bond 配置绝不是敲几条命令那么简单它需要你理解链路从物理层到协议层的完整路径。把这个链路吃透了后面遇到网络相关的疑难杂症你手里就多了一张好打的牌。
返回列表