做服务器高可用改造时,H3C交换机的S-MLAG配合Linux bond4是我目前比较推荐的一套组合。这个方案可以让服务器用两张物理网卡分别上联两台独立的交换机,任何一台交换机宕机、任何一根网线故障,服务器IP不漂移、业务连接不断。听起来很美好,但我在实际配置和验证过程中踩了不少坑,尤其是交换机侧跨设备链路聚合的配置细节、服务器bond4与交换机LACP协商的匹配关系,以及拔线测试时的各种意外。这篇文章就把从设计思路、拓扑规划、命令配置到故障切换实测的过程完整记录下来,给准备做服务器双上联高可用的同行一个可以直接参考的案例。如果你是网络运维、系统工程师,或者正在纠结"服务器到底该用bond4还是主备bond"的人,这篇应该能帮你省下不少排查时间。
1. S-MLAG与IRF的选择题:为什么服务器双上联最终选了S-MLAG
1.1 服务器高可用最初看起来很简单
服务器侧做高可用,最基础的需求是"一块网卡挂了业务不能断"。于是大部分人会先做网卡bond,也就是把服务器上的两到四块物理网卡绑定成一个逻辑网卡,IP只配在bond口上。
但问题很快就来了:如果这两块网卡都插在同一台交换机上,那这台交换机一旦宕机或者升级重启,服务器再高的网卡冗余也白搭。要解决交换机层面的单点,就必须把服务器的两根网线分别插到两台不同的交换机上。
麻烦在于,传统的链路聚合(静态聚合或者LACP动态聚合)定义在单台交换机上,聚合口的所有成员口必须属于同一台设备。想让服务器的bond跨两台交换机,最初我只能想到堆叠:把两台交换机用IRF堆叠成一台逻辑设备,跨设备的端口就可以放到同一个聚合口里了。
1.2 IRF堆叠在高可用交付中的三个"暗坑"
IRF堆叠确实能解决跨设备链路聚合的问题,但在真实交付场景里,它并不永远是最优解。我在多个项目里遇到过同样的情况,总结下来主要是三个坑。
第一个是控制面耦合。IRF堆叠后两台设备共享控制平面,版本必须严格一致,配置同步也是整机级同步。一旦出现版本Bug,往往两台同时中招,反而把"高可用"变成了"高故障率"。而且在运维审计角度,堆叠后所有配置都从主设备下发,从设备完全透明,出了问题复盘非常难受。
第二个是升级窗口长。IRF堆叠升级时,为了避免脑裂通常需要整机升级或者主备逐台升级,操作过程中要求很苛刻——主备切换、版本回退、配置兼容性检查,任何一个环节出错都可能引发业务中断。生产环境的维护窗口往往只有三四个小时,这个压力很大。
第三个是组网限制。IRF要求参与堆叠的设备型号、硬件版本、软件版本尽量一致。如果现场本来就有两台不同型号的H3C交换机,或者一批旧设备一台新设备,想堆叠就得更换硬件,成本一下就上去了。
1.3 S-MLAG(DRNI)如何实现"跨设备聚合且控制面独立"
S-MLAG(在H3C Comware V7平台上对应功能叫DRNI,分布式中继)解决的就是上面这几个问题。它的核心思路是:两台交换机依然保持各自独立的控制平面,不需要统一版本,也不需要型号完全一致,但通过一条专门的peer-link链路把两台设备"连接"起来,让服务器侧看起来像是对接了一台逻辑交换机。
具体工作机制大致是这样的:两台设备各自配置一个相同的DRNI系统MAC和系统优先级,让下游服务器认为它们是一个LACP系统中的两个端口;同时通过keepalive链路互相检测对方的存活状态;peer-link用于同步必要的MAC表项、ARP表项以及转发跨设备流量。
这样做的好处很明显:控制平面隔离,一台设备升级或者宕机,另一台不受影响;可以逐台升级、逐台重启;设备型号不完全一致也能接受。对服务器bond来说,它感知不到对端是两台独立设备,只认为自己的两块网卡聚合到了一个逻辑交换机上。
所以我在这个项目里最终选择了S-MLAG而不是IRF。当然,S-MLAG也不是万能的,它适合的场景比较偏向服务器双上联、跨设备二层聚合这类需求。如果你需要的是高性能转发、统一管理、单台设备配置同步,那IRF可能更合适。后面我还会提到一些S-MLAG的局限性。
2. bond4与LACP:服务器侧高可用真正依赖的"握手"
2.1 七种bond模式速览
Linux下bond模式一共有7种,数字从0到6。很多系统工程师在配置bond时习惯直接抄模板,但我强烈建议至少知道自己选的是哪种模式,因为服务器bond模式必须和交换机侧配置匹配,否则就是"看起来通了,一拔线就断"。
下面这个表是我在方案选型时经常用的对照表:
| 模式 | 名称 | 基本原理 | 是否需要交换机配合 | 适用场景 |
|---|---|---|---|---|
| mode=0 | balance-rr | 轮询按包分发 | 不需要,但可能乱序 | 基本不用 |
| mode=1 | active-backup | 主备模式,只有一块网卡工作 | 不需要 | 简单高可用 |
| mode=2 | balance-xor | 按源/目的MAC做异或选路 | 不需要,但交换机需能看到同一个MAC | 很少用 |
| mode=3 | broadcast | 所有包从所有网卡发出 | 不推荐 | 基本不用 |
| mode=4 | 802.3ad | 动态链路聚合,LACP协商 | 必须配合交换机动态聚合 | 主流高可用方案 |
| mode=5 | balance-tlb | 发送负载均衡,接收由网卡自主决定 | 不需要 | 老环境 |
| mode=6 | balance-alb | TLB+接收负载均衡 | 不需要 | 老环境 |
高可用场景我首选mode=4,也就是802.3ad动态链路聚合。原因很简单:它通过LACP协议和交换机实时协商链路状态,交换机知道自己有几个成员口在线、链路质量如何,拔线和恢复都能快速感知。mode=1虽然简单,但主备切换时备份网卡完全不工作,浪费了一台交换机的冗余能力;而且没有LACP的主动通知,很多时候是靠网卡link down才触发切换,收敛速度慢。
2.2 bond4为何要求交换机侧也必须是"动态聚合"
bond4工作的基础是LACP协议。服务器上的bond口会周期性地向对端发送LACPDU帧,帧里携带了本端的系统MAC、系统优先级、端口号、端口优先级、操作Key等信息。交换机收到LACPDU后,会根据这些参数判断哪些端口可以聚合成一个聚合口,然后回复自己的LACPDU。双方都认为端口被选中(Selected),聚合才算建立成功。
这里最关键的一点是:bond4要求交换机侧配置的是动态聚合(LACP模式),而不是静态聚合。静态聚合下交换机会强制把所有成员口加入聚合口,根本不理会LACP协商结果。服务器这边发出去的LACPDU交换机可能只做透传甚至直接忽略,结果是服务器侧看到对端Partner信息是空的,聚合口一直处于down状态,或者一面倒认为链路不可用。
我见过很多新人把交换机的Bridge-Aggregation配置成静态聚合(默认)就去对接服务器的bond4,结果bond0显示MII Status: down,半天下不去。排查了半天才发现是聚合模式不匹配。
2.3 哈希策略决定负载均衡效果
bond4本身只负责链路协商和故障切换,真正的负载均衡靠哈希算法完成。Linux bond的xmit_hash_policy有三个常见选项:layer2、layer2+3、layer3+4。
- layer2:按源MAC和目的MAC做异或选路,对于服务器到核心交换机的流量来说,MAC基本固定,很容易所有流量都哈希到同一条链路。
- layer2+3:加上源IP和目的IP做计算,比layer2好一些,但还是容易受地址影响。
- layer3+4:在IP基础上再加上源端口和目的端口,对于TCP/UDP多连接的业务来说均衡效果最好,也是我最常用的配置。
需要特别说明的是:无论哪种哈希策略,单条TCP流始终只能走一条物理链路。也就是说,如果业务本身只有一个大连接在传输,bond4并不能把它拆成两份分别走两台交换机。这个限制是LACP聚合的天然特性,不是配置问题,做方案时一定要和业务方讲清楚。
3. 拓扑设计与H3C交换机侧配置实录
3.1 推荐拓扑与接口规划
我这次改造的典型拓扑是两台接入交换机(Leaf-1和Leaf-2)下挂若干台Linux服务器。每台服务器用两块万兆网卡分别上联两台交换机,服务器上做bond4,交换机侧做S-MLAG跨设备聚合。
关键链路的规划如下:
| 链路 | 用途 | 说明 |
|---|---|---|
| 服务器eno1 -> Leaf-1 | 业务成员链路 | 加入业务聚合口 |
| 服务器eno2 -> Leaf-2 | 业务成员链路 | 加入业务聚合口 |
| Leaf-1 <-> Leaf-2 peer-link | DRNI控制/数据通道 | 建议至少两根物理线聚合成一个peer-link |
| Leaf-1 <-> Leaf-2 keepalive | 心跳检测 | 独立三层链路,建议单独规划互联地址 |
注意peer-link和keepalive是两条完全不同的链路。peer-link承载的是两台设备之间的MAC表项同步、跨设备流量转发,带宽要求高;keepalive只传心跳报文,带宽要求低,但必须物理独立。如果keepalive和peer-link走了同一条物理线路,一旦这条线路故障,两台设备同时失去对端状态,S-MLAG会立刻进入分裂状态,直接翻车。
3.2 S-MLAG(DRNI)核心配置过程
下面以H3C Comware V7平台为例,给出DRNI的配置思路。不同型号、不同版本命令细节可能会有差异,我实际配置时也遇到过有的版本把DRNI写成M-LAG的情况,落地前一定以设备对应版本手册为准。
Leaf-1上的核心配置大致如下:
system-view sysname Leaf-1 # 配置DRNI系统参数,两台设备必须一致 drni system-mac 0000-fc00-0001 drni system-priority 100 # 本机在DRNI系统中的编号,两台设备分别配1和2 drni system-number 1 # 创建peer-link聚合口 interface Bridge-Aggregation 1 description DRNI-PEER-LINK port link-type trunk port trunk permit vlan all port drni peer-link quit # 将peer-link物理成员加入 interface Ten-GigabitEthernet1/0/1 port link-type trunk port trunk permit vlan all port link-aggregation group 1 quit # 创建业务聚合口,interlace编号两台设备要一致 interface Bridge-Aggregation 10 description DRNI-SERVER-BOND port link-type access port access vlan 100 port drni interlace 10 quit # 将服务器上联口加入业务聚合口 interface Ten-GigabitEthernet1/0/2 port link-type access port access vlan 100 port link-aggregation group 10 quit # keepalive心跳配置(示例使用Vlan-interface) interface Vlan-interface 300 ip address 10.10.10.1 30 quit drni keepalive destination 10.10.10.2 source 10.10.10.1Leaf-2上的配置基本一样,差异只有两处:drni system-number 2,以及keepalive的源目地址互换。
这里要强调一个容易忽略的点:业务聚合口的port drni interlace 10这条命令,目的是让两台设备上编号相同的业务聚合口建立对应关系。如果Leaf-1上配了interlace 10,Leaf-2上却配成interlace 20,那LACP协商会成功,但实际转发流量会出问题,因为服务器认为自己在和一个聚合系统通信,但两台交换机各自维护各自的DRNI实例,对应关系错位。
3.3 两台交换机上必须保持一致的参数清单
S-MLAG配置完成后,我最担心的不是命令敲错,而是两台设备上的"隐含参数"不一致。下面这些是我在实际排障中一条条核对过的:
- DRNI system-mac和system-priority必须完全一致,否则对端服务器通过LACP看到的"系统身份"不一致,聚合口无法选中。
- 业务聚合口在两台设备上的VLAN配置必须一致。如果Leaf-1上成员口是access vlan 100,Leaf-2上配成access vlan 200,LACP协商依然可能成功,但服务器发出来的流量进了两个不同的VLAN,同VLAN内二层不通,排查起来非常隐蔽。
- 成员口建议关闭STP边缘检测或者配置为边缘端口,否则交换机刚启动时STP收敛需要几十秒,服务器那边bond已经认为链路down过一轮了。
- 上联到核心的接口、路由配置、ACL策略,只要会影响服务器所在VLAN转发,也尽量保持一致,避免出现"故障切换后能通,但策略放行不一致导致部分流量被丢弃"的诡异问题。
我在现场做配置复查时习惯写一个对照清单,两台设备逐条diff,不要相信自己记忆力。
4. 服务器侧bond4配置与验证手段
4.1 动手前先确认网卡与驱动
服务器侧配置bond4之前,我建议先看一眼网卡驱动和固件版本。因为LACP协商依赖网卡对多播帧和LACPDU的处理能力,某些老旧网卡驱动在收到LACPDU时不把它上送到协议栈,而是直接丢弃,导致bond口一直无法和交换机握手。
用下面几条命令做基础检查:
lspci | grep -i ethernet ethtool -i eno1 ethtool eno1 | grep -i "link detected"如果确认网卡和驱动没问题,再开始配置bond。否则你可能会陷入"交换机配置没问题、服务器配置没问题、但就是聚合不起来"的循环里,最后才发现是驱动Bug。
4.2 ifcfg方式配置bond0(CentOS/RHEL系)
以我最常用的CentOS 7/8环境为例,使用ifcfg文件配置bond0。先加载bonding模块并设置默认参数,编辑/etc/modprobe.d/bonding.conf:
alias bond0 bonding options bonding miimon=100 mode=4 lacp_rate=1 xmit_hash_policy=layer3+4然后创建/etc/sysconfig/network-scripts/ifcfg-bond0:
DEVICE=bond0 NAME=bond0 TYPE=Bond BONDING_MASTER=yes BOOTPROTO=none ONBOOT=yes IPADDR=10.1.1.10 PREFIX=24 BONDING_OPTS="mode=4 miimon=100 lacp_rate=1 xmit_hash_policy=layer3+4"接着修改两张物理网卡的配置文件。以eno1为例:
DEVICE=eno1 NAME=eno1 TYPE=Ethernet BOOTPROTO=none ONBOOT=yes MASTER=bond0 SLAVE=yeseno2配置同理。最后重启网络服务:
systemctl restart network这里需要提醒一点:如果服务器上跑的是NetworkManager,建议直接在NetworkManager里用nmcli创建bond,或者在这些ifcfg文件里加上NM_CONTROLLED=no。否则NetworkManager可能会在重启后把ifcfg配置"接管"过去,导致bond起不来。
另外,如果对切换延迟容忍度低,可以把lacp_rate=1再显式写一遍,让LACP走快速模式(1秒发一次LACPDU),交换机侧也把LACP超时时间配成fast。两边必须匹配,否则效果打折。
4.3 状态验证:读懂几个关键输出
配置完成后,先别急着上业务。我习惯用这几条命令做"体检":
cat /proc/net/bonding/bond0 ip -d link show bond0 ethtool eno1 | grep -i "link detected" tcpdump -i eno1 -e -n -vv 'ether[0:2] == 0x8809'看/proc/net/bonding/bond0的输出时,重点看几个字段:
Bonding Mode: IEEE 802.3ad Dynamic link aggregation:确认确实工作在mode=4。LACP rate: fast:确认快速LACP模式生效。Aggregator ID和Partner Mac Address:如果能看到具体的聚合器ID和交换机侧MAC,说明LACP协商已经完成。Slave Interface列表里两块网卡的MII Status都是up,且Link Failure Count没有持续增长。
tcpdump抓LACP帧可以确认LACPDU确实在链路上跑。如果抓不到任何ethertype为0x8809的帧,那就是bond4没有真正使能LACP,或者网卡驱动把LACPDU丢了。
5. 故障切换实测:如何科学地"拔线"和升级
5.1 故障注入矩阵
配置完成只是一个开始,真正让我放心的是故障切换实测。我习惯按下面的矩阵逐项测试,每一项都要记录切换时间和服务影响。
| 故障注入方式 | 预期现象 | 业务影响 |
|---|---|---|
| 拔掉服务器到Leaf-1的网线 | bond0从两块网卡变成一块工作,IP不变,ping只有短暂丢包 | 通常1秒以内 |
| 在Leaf-1上shutdown业务口 | 同拔线,但交换机侧LACP会主动通知,服务器感知更快 | 通常更短 |
| 直接poweroff Leaf-1 | peer-link失效、keepalive检测到对端故障,Leaf-2继续提供服务 | 可能有一次秒级震荡 |
| 逐台重启Leaf-1(升级场景) | 服务器bond保持在线,Leaf-1重启完毕后自动重新聚合 | 业务不中断 |
这里要说一下"科学拔线"的含义:很多人在测试时直接用手拽网线,这其实是最不标准的方式。因为物理拔线过程中铜缆可能会有接触不良的抖动,导致链路反复up/down,服务器bond会误判为多次故障,触发不必要的切换和回切。我建议优先用交换机侧shutdown接口、服务器侧ip link set eno1 down这种方式做可控故障注入,最后再模拟物理拔线。
5.2 收敛时间如何估算与调优
故障切换时间主要由三部分组成:链路状态检测时间、LACP协商时间、服务器协议栈收敛时间。
- 链路状态检测:Linux bond里配置的
miimon=100表示每100毫秒检查一次链路状态,拔线后MII检测到link down的时间大概在100到200毫秒。 - LACP协商:如果配了
lacp_rate=1,交换机侧也配了fast超时,LACP检测到成员口消失的时间在1秒左右。 - 协议栈收敛:服务器上IP、路由表、ARP表项基本不变化,所以这部分时间很短。
综合下来,物理拔线场景下业务ping丢包普遍在几个包以内。如果配置了slow LACP(默认30秒超时),拔线后可能要10秒以上才能完成切换,这个差异在生产环境里是致命的。所以我对mode=4的建议很明确:lacp_rate必须用fast,交换机侧LACP超时也必须配fast。
5.3 一次真实升级复盘
印象最深的一次是Leaf-1做版本升级。因为DRNI场景下两台设备控制平面独立,我可以在维护窗口内先升级Leaf-1,再升级Leaf-2,理论上业务无感知。
实际操作时,Leaf-1重启期间,服务器bond0的所有活跃流量都走到了Leaf-2上,ping测试只丢了1个包。leaf-1启动完成后,bond0自动把eno1加回聚合器,流量重新分散到两条链路。全程不需要重启服务器,不需要动IP配置。
但那次也暴露了一个问题:Leaf-1刚起来时,业务聚合口的STP还在收敛,服务器侧eno1的MII状态是up,但交换机侧端口还没开始转发,导致部分流量超时。后来我在成员口上配置了STP边缘端口,再测试就稳定了。这个细节强烈建议提前处理,否则升级窗口内的"秒级中断"会让你很被动。
6. 避坑指南:从握手失败到控制台被锁的完整排障链路
6.1 现象:bond0一直显示down,或聚合口没有active成员
这种是最常见的问题。服务器侧bond0显示类似下面这种状态:
Bonding Mode: IEEE 802.3ad Dynamic link aggregation MII Status: down排查顺序我建议是"先看物理、再看交换机、最后看协议":
- 用
ethtool eno1确认服务器网卡的link是up的。 - 在交换机上
display link-aggregation verbose,看成员口是否在聚合组里、Aggregation状态是否为Selected。 - 如果交换机侧没有任何聚合组,检查成员口是否加入了正确的Bridge-Aggregation,以及聚合适配模式是不是动态。
我遇到过一次比较隐蔽的情况:交换机上同一个物理口既被加进了peer-link聚合组,又手工配置了access vlan 100,导致端口配置冲突,服务器侧怎么都协商不上。后来把物理口从peer-link聚合组里移除,重新加到业务聚合组才解决。
6.2 交换机侧成员口一直"未选中"的根因
如果交换机聚合口能看到成员口,但状态不是Selected,通常有以下几种原因:
- 成员口的链路类型在交换机侧是trunk,但VLAN放行列表和DRNI对端不一致,导致LACP报文的VLAN封装对不上。
- 两台设备上的业务聚合口interlace编号不一致,DRNI认为这是两个不同的逻辑接口。
- STP把成员口阻塞了,尤其是刚配置完、生成树还没收敛时。这时可以
display stp interface Ten-GigabitEthernet1/0/2看端口状态,确实被阻塞就检查STP配置。
解决思路是不要只看聚合口状态,要把二层链路、VLAN、STP逐层查一遍。聚合协商成功只代表"物理上能聚合",不代表"转发路径通畅"。
6.3 控制台密码忘记与设备恢复现场
这个坑虽然和S-MLAG没有直接关系,但凡是接手旧的H3C设备,几乎都会遇到。现场有台S7506,交接时控制台密码已经丢了,根本进不了系统,只能做恢复。
我的处理流程是:
- 确认设备上已有配置是否需要保留。如果能通过网管或历史配置文件获取到运行配置,先想办法备份一份;如果完全无法登录,只能从重启阶段恢复。
- 通过console口连接设备,重启设备,在启动阶段根据提示按Ctrl+B进入BootROM菜单(不同型号按键和菜单提示不同)。
- 在BootROM菜单里选择跳过配置文件加载,或者清除console登录密码的选项,进入系统后重新设置密码。
- 如果只是忘了密码但配置还要用,选择"跳过console认证"而不是"恢复出厂配置",否则配置全丢,重建成本非常高。
- 操作完成后保存新配置,并立即导出一份配置备份。
需要说明的是,这种恢复手段一定要用于自己有权管理的设备,并且在操作前确认设备已经不在业务路径上,或者业务影响可控。设备在跑业务时千万不要随意重启。
6.4 S-MLAG双主/单活的本质与防范
S-MLAG最怕的是两台设备同时认为自己是主设备,进入"双活分裂"状态。正常情况下keepalive链路和peer-link链路都在,两台设备能感知对端存在。但一旦keepalive链路故障,同时peer-link因某种原因震荡,两台设备可能都认为对端挂了,各自独立运作,转发行为就会冲突。
防范措施有几点:keepalive必须走独立物理链路,不要和业务口共用;peer-link建议至少双物理口聚合,降低单点风险;有条件的情况下,在汇聚层做相应的策略兜底,避免双主时形成环路。
我在一次排障中还遇到过"双主后peer-link不自动恢复"的情况,原因是对端设备重启后DRNI状态没有完全清掉。解决办法是两台设备都执行reset drni相关复位操作,让DRNI重新建立。这个操作有业务中断风险,一定要在维护窗口做。
6.5 单流哈希不均与"带宽上限"问题
很多业务方对bond4有误解,以为两块万兆网卡bond后吞吐就是20G。实际上单条TCP流只能走一块网卡,最多10G。只有并发连接数足够多、哈希分布足够均匀时,总吞吐才能接近20G。
如果你测出来bond0的总流量一直卡在10G上不去,先别怀疑链路有问题,用ethtool -S查看每块物理网卡的收发计数,看流量是不是集中在一块网卡上。如果确认是哈希不均,可以尝试调整xmit_hash_policy,或者在应用层增加并发连接。不要指望bond4能把单流拆开,这是协议限制。
6.6 容易踩的配置一致性坑汇总
最后把我在多个项目里积累的"一致性清单"放这里,每次S-MLAG交付前逐项过一遍:
- 两台设备的DRNI system-mac、system-priority、system-number配置正确。
- 两台设备的业务聚合口interlace编号一致。
- 服务器成员口在两台设备上的VLAN配置完全一致。
- peer-link放通了所有需要的VLAN,且peer-link本身聚合正常。
- keepalive链路物理独立,能互相ping通。
- 两台设备的STP模式、成员口边缘端口配置一致。
- 服务器侧
lacp_rate和交换机侧LACP超时时间匹配。 - 升级维护前确认两台设备的启动文件、版本兼容性,避免逐台升级时出现一台起不来的情况。
这套组合用到现在,最深的体会是S-MLAG本身不复杂,复杂的是"跨设备一致性"。交换机侧两台设备只要在VLAN、聚合编号、STP、LACP参数上有一处不一致,故障切换时就会产生各种隐蔽的丢包和震荡。而服务器侧的bond4相对稳定,一旦配置正确,后续几乎不用管。如果你也准备在生产环境上这套方案,强烈建议先搭一套测试环境把故障注入矩阵完整跑一遍,再安排业务割接。我在每个新项目里都会这样做,这比任何配置检查都更能发现问题。