1. 为什么突然要把“网卡绑定运行情况”拿出来查
上周五晚上快十一点,我一个做生产环境的朋友打电话过来,语气有点急,说数据库主机从晚上九点开始连接断断续续,每过几分钟就抽风两三秒,业务监控丢包率从0.05%飙到了1.2%。他第一反应是网线或者光模块的物理问题,换了两个口,灯都亮,速率也显示千兆,可症状一点没缓解。
我让他先别折腾光口和网线,打开终端执行一条命令给我看结果:
cat /proc/net/bonding/bond0这一看就明白了。他这台服务器两块千兆网卡做了bond0,模式是active-backup,正常情况下应该是一块网卡处于active状态,另一块ERR候命。但输出里显示当前active的slave是eth0,eth1的MII Status虽然是up,可是Link Failure Count已经涨到了14次。也就是说,备用链路在短短几十分钟内反复断过十几次,只不过设备上层没把这种切换当成“故障”报出来,业务侧的抖动信号却已经传遍全链路。
这也正是我想写这篇分享的原因。“网卡绑定运行情况”这件事,很多人以为是“确认网卡灯亮、ping通网关”就够了,实际完全不是一回事。从这次经历里能清晰看到,物理层面正常、逻辑绑定状态也显示存活,不等于绑定真的在工作,尤其当模式是active-backup或者802.3ad这类依赖协商和切换的聚合模式时,真正的健康度藏在/proc、/sysfs、链路计数器以及事件日志里,不去专门查根本发现不了。
这篇东西适合谁看?主要三类人:日常维护Linux服务器网络的运维、机房巡检时不满足于“看灯”的硬件管理员,以及那些在虚拟化平台或者数据库双机环境里负责网络兜底的人。我会把检查绑定的原理、命令、实战案例、重启不启动的坑,以及一套可以复制走的巡检习惯全部讲清楚,不绕弯。
1.1 绑定“坏掉”的三个典型信号
边界不能搞模糊,先说我判断“绑定运行情况出问题”的三个信号,你可以对照手头环境看:
- 服务器到网关经常丢包,但单独把每块物理网卡断开重测又正常,这种最典型,问题往往不在物理线路,而在绑定逻辑。
- 重启之后服务器IP访问不了,只能进远程管理卡去排查,这是配置与系统启动顺序冲突的经典表现。
- 流量长期只走一块网卡,另一块网卡计数器几乎为零,如果绑定的模式本身就应该分流,那就说明绑定策略没生效或者链路协商有问题。
第一种信号最迷惑人。因为单独测一个口是通的,容易让“直接换线换口”把真正的问题掩盖掉。我见过有兄弟把两台服务器的四根网线全换了还是丢包,最后排查发现是balance-rr模式配在了不支持聚合的交换机上,属于典型的绑定模式应用错误。
1.2 什么时候该主动查,而不是等告警
很多团队习惯“没告警就等于没问题”,但绑定这种状态恰恰是渐进式劣化最容易藏住的。比较常见的劣化路径包括:
- 交换机端口协商变化,速率从千兆悄悄掉到百兆,bond状态照样是up;
- 网线接头氧化松动,carrier频繁up/down,业务表现只是偶尔卡一下;
- 对端交换机LACP配置被网络同事删了,服务器这边还在用802.3ad硬等聚合;
- 两块slave网卡接入的是交换机上两个不同VLAN或不同广播域,流量发出后乱序、错包,但谁也不认为“绑定坏了”。
这些问题都不触发硬告警,但业务系统会先崩。所以真正负责的运维,是把这个检查放在每周巡检计划里,而不是等故障工单砸过来。
2. 分清绑定模式和绑定状态,操作才不会变成乱猜
有朋友问我“该看哪个字段”,我的回答通常是先问另一个问题:你用的哪种绑定模式?不同模式决定底层行为完全不一样,检查时关注的字段重点也跟着变。如果模式没搞清楚,看到MII Status: up就判定一切正常,那基本等于白查。
2.1 mode 0到mode 6,各自的健康侧重点
Linux bonding驱动支持七种模式,我先把每种模式对应的检查重点列出来:
| 模式 | 名称 | 检查时的重点 |
|---|---|---|
| mode=0 | balance-rr | 两块网卡是否都在转发,轮询分发是否均匀 |
| mode=1 | active-backup | 当前active slave是哪块,备用slave链路是否正常 |
| mode=2 | balance-xor | 哈希均衡策略、对端交换机是否支持 |
| mode=3 | broadcast | 所有slave是否同时保持up且都在转发 |
| mode=4 | 802.3ad(LACP) | 对端交换机聚合组、LACPDU协商是否一致 |
| mode=5 | balance-tlb | 出口负载均衡、入流量是否集中在一块卡上 |
| mode=6 | balance-alb | 与tlb类似,另需关注ARP协商是否正常 |
比如active-backup模式下,核心指标是当前active链路和备用链路的MII状态、Link Failure Count,以及切换瞬间产生的丢包数量。而802.3ad模式更要紧的是看LACP rate、Actor Key和Partner Key是否匹配,如果对端交换机那边聚合组只有1个口,即使服务器两个口都上报MII up,实际也无法达到聚合效果。
2.2 绑定状态里最重要的两个底层概念
很多人说“网卡绑定的运行状态”,我习惯把它拆成四个层面:
- 物理层:carrier信号是否存在;
- 链路层:速率、双工协商、LACP/聚合协商是否一致;
- 逻辑层:bond里的slave成员、active角色、切换计数;
- 网络层:IP路由、ARP、业务流量是否正常。
这里面的关键是carrier,你可以直接查看:
cat /sys/class/net/eth0/carrier输出1代表物理链路通,0代表链路断开。bonding驱动的MII状态本质上就是对carrier信号做轮询后的抽象结果。很多监控面板把“链路up/down”说得很玄,底子其实就这层。理解了这一层之后,故障定位就可以严格按顺序从下往上排查,不会一上来就被IP连通性的问题带走。
2.3 网卡灯亮不亮为什么不能当依据
说了像是废话,但现实里太多人靠着网卡灯判断问题。亮灯只能告诉你这个端口有自己的物理链路,并不能告诉你这块网卡是否被正确纳入了绑定逻辑。
我之前处理过一个案例:服务器做了bond0,模式active-backup,结果一块网卡被前台拔了,灯自然灭了。因为策略自动把流量切到了备用口,监控面板上只看到“bond0当前active口变了”,业务零中断,很多数据链路的人压根没注意到备用口曾经的故障。另一次相反,网卡灯亮着,但速率已经掉到100Mbps,链路层协商变异了,绑定还是显示up。按灯去判断,永远发现不了这类“假健康”。
3. 三件套命令检查法:从/proc到sysfs再到ip命令
真正动手检查,我习惯按三个层次依次走。先看绑定驱动自己汇报的状态,再确认内核参数,最后做数据通路的验证。
3.1 核心体检单:cat /proc/net/bonding/bond0
这条命令看的是绑定驱动实时状态,输出内容很丰富,我把典型样例贴出来并逐条拆解:
Ethernet Channel Bonding Driver: v5.15.0-xxxx Bonding Mode: IEEE 802.3ad Dynamic link aggregation Transmit Hash Policy: layer3+4 (XOR) MII Status: up MII Polling Interval (ms): 100 Up Delay (ms): 0 Down Delay (ms): 0 802.3ad info LACP rate: slow Aggregator selection policy (ad_select): stable System priority: 65535 Active Aggregator Info: Aggregator ID: 1 Number of ports: 2 Actor Key: 9 Partner Key: 13 Partner MAC Address: 00:10:94:00:00:01 Slave Interface: eth0 MII Status: up Speed: 1000 Mbps Duplex: full Link Failure Count: 0 Permanent HW addr: 00:e0:4c:xx:xx:xx Slave queue ID: 0 Slave Interface: eth1 MII Status: up Speed: 1000 Mbps Duplex: full Link Failure Count: 0 Permanent HW addr: 00:e0:4c:xx:xx:xx Slave queue ID: 0怎么看这份“体检单”?按优先级排列:
Bonding Mode告诉你绑定现在跑在什么策略下,跟预期配置是否一致;MII Status表示绑定整体、以及每一个slave成员的链路状态;Link Failure Count是最容易被忽视但价值很高的字段,它记录从驱动加载以来该slave发生链路中断的次数;Speed和Duplex负责确认协商结果,当过万兆口却显示100Mbps时,问题就已经存在了;Permanent HW addr用于确认物理网卡的出厂地址,排查交换机那边MAC漂移时非常有用。
如果里面某块slave的Link Failure Count一直稳定增长,即使当前MII Status是up,也要高度警惕,这说明备用路径在持续抖动,绑定随时可能进入切换状态。
3.2 通过sysfs看数值参数
/proc目录给的是给人看的可读状态,sysfs下则是程序和脚本更爱读取的数值化参数。几个常用路径:
cat /sys/class/net/bond0/bonding/mode cat /sys/class/net/bond0/bonding/slaves cat /sys/class/net/bond0/bonding/miimon cat /sys/class/net/bond0/bonding/arp_interval cat /sys/class/net/bond0/bonding/downdelay注意mode这里输出的是数字,比如active-backup 1、802.3ad 4,对应关系就是前文表格里的模式编号。miimon表示MII轮询间隔,常见初始值是100毫秒;如果这个值过大,链路抖动被发现的速度就会变慢,切换恢复时间会拖长。arp_interval同理,表示通过ARP探测确认链路健康的时间间隔,很多生产环境是0,表示不启用。
3.3 用ip和ethtool验证数据通路
状态文件说“up”,不代表数据真的能走通。我会再加两条命令交叉验证:
ip -d link show bond0 ip -s link show bond0ip -d输出里能看到绑定模式、成员接口;ip -s能看到每个接口的RX/TX字节、包数、错误数和丢弃数。比较关键的是看错误包、丢包以及backlog是否异常。如果收发字节数长期一边高一边低,说明流量分布不均,可能与哈希策略不匹配有关。
物理网卡层面也不能跳过:
ethtool eth0 ethtool eth1重点看Speed、Duplex、Link detected。如果Speed显示百兆而交换机口是千兆,那问题可能在网线质量、跳线顺序、或者对端端口配置,绑定这边再健康也白搭。
3.4 一条命令实现绑定的批量汇总
一台物理机可能同时有多个bond接口,逐个cat又慢又容易漏,我习惯用个小循环一次性收集:
for iface in /proc/net/bonding/bond*; do echo "=== ${iface} ===" egrep "Bonding Mode|MII Status|Link Failure Count|Slave Interface|Speed|Duplex" "${iface}" done这个输出非常适合直接追加到巡检日志里。我自己的习惯是让它每小时跑一次并保留七天的历史文件:
echo "$(date '+%F %T')" >> /var/log/bond_health.log for iface in /proc/net/bonding/bond*; do egrep "Bonding Mode|MII Status|Link Failure Count|Slave Interface|Speed" "${iface}"; done >> /var/log/bond_health.log配合cron就能形成简单的趋势数据,哪块卡什么时间点开始抖动,一翻日志就明白了。
4. 一次故障复盘:从“ping通但时断时续”到锁定balance-rr
前面说的都是方法论,这一节我想完整复盘一次真实故障。因为很多东西只有放到具体场景里,才会发现“查到了状态但没意识到问题在哪”。
4.1 现象与初步检查
那套环境是两台服务器跑共享存储,每台机器双网卡组成bond0,模式用的是balance-rr。业务端反馈经常性卡顿,我测了下,ping网关100个包丢4个,Ping服务器本身也是同样的丢包率。丢包率不算高,但很稳定,每次丢包都在同一批临近序号的位置。
按直觉先排除物理层:
ethtool eth0 ethtool eth1两块网卡都是千兆、全双工、Link detected: yes。再看绑定状态:
cat /proc/net/bonding/bond0MII Status全是up,Link Failure Count都是0,看起来“什么问题都没有”。这时如果只是重新插拔线缆,大概率会白白浪费半天时间。
4.2 定位过程:balance-rr遇到非聚合交换机
我怀疑问题在balance-rr这个模式上。balance-rr是逐包轮询模式,第1个包走eth0,第2个包走eth1,来回交替。这种模式要求两个物理端口在交换机侧处于同一个二层出口,且交换机也要支持能力,或者两个端口被配置成同一个链路聚合组。但客户那边只是普通千兆交换机上开了两个独立口,没做聚合配置。
这样一来,交换机会看到来自同一台主机两块不同MAC地址的报文从两个端口进来,等于把它当成了两个独立的终端。结果就是ARP表反复横跳、未知单播风暴、报文乱序,TCP层面表现为大量重传。从服务器自身看到的IP连通性“时好时坏”,但物理和绑定状态全是up。
为了验证这个思路,我临时把其中一个口从交换机DOWN掉,让数据都走单链路,症状立刻消失了一大半。这一步基本完成了确认:问题不是某条链路坏了,而是balance-rr在这种交换环境里根本不适用。
4.3 修复动作:选对模式,还要选对切换路径
这类场景最稳妥的修复方案是mode=active-backup,或者协商后改成802.3ad。我当时的实际建议是先降到active-backup,恢复业务稳定,再和网络组确认交换机是否支持并配置LACP,支持的话再切到802.3ad。
切换模式不能直接在生产环境上硬改。很多人上来就执行:
ip link set bond0 type bond mode active-backup然后发现网络闪断,甚至干脆不通了。因为动态改模式时内核会重新初始化bond的设备队列,两个slave从bond上解绑再绑定。更稳妥的顺序是:确认业务低峰,临时停掉bond上的业务IP,再动态改模式,确认成功后将配置固化到启动文件里。
4.4 状态日志和趋势是真正的破案线索
这个案例里,如果只看当时一个时间点的/proc/net/bonding/bond0,确实什么也发现不了。但把过去几小时的Link Failure Count和系统日志拉出来看,能追溯最早的抖动时刻。很多底层隐性问题,比如光模块间歇性故障、交换机风扇散热异常引起的端口闪断,都是靠场景日志连起来的。这个习惯后来帮我们避免过一次更大面积掉线。
5. 重启之后网卡不启动:绑定场景里最常见的“冷启动坑”
搜索热词里“麒麟v10命令重启后为什么网卡不启动”“linux网卡开机自启”“虚拟机安装没有虚拟网卡”反复出现,说明重启后绑定失效是个普遍折磨人的问题。绑定配置能撑住运行,不代表能撑过重启,这是两套完全不同的机制。
5.1 典型原因:slave网卡启动顺序抢在bond0前面
大部分老系统的网络配置都在/etc/sysconfig/network-scripts/(RHEL系)或者/etc/network/interfaces(Debian/Ubuntu系),对于bond来说有几个铁律:
- bond0的ifcfg文件必须在两个slave之前被网络服务加载;
- 每个slave网卡必须明确标注
MASTER=bond0、SLAVE=yes; - 如果用了NetworkManager,必须把bond配置正确导入NM的连接配置,否则NM会把bond口当成普通网卡处理。
常见的坑是手工改过ifcfg-eth0之后把MASTER=bond0的配置漏了,开机时eth0先于bond0加载,找不到master就干脆以普通网卡身份自己拿了个IP,于是服务器IP直接不对。你通过远程管理卡看系统里bond0存在,但上面没有业务IP,slave网卡却挂着一个没人认识的地址。
5.2 用nmcli管理bond是更省心的现代做法
现在很多发行版默认用NetworkManager,在命令行直接配bond其实并不复杂:
nmcli connection add type bond ifname bond0 mode active-backup miimon 100 nmcli connection add type ethernet ifname eth0 master bond0 nmcli connection add type ethernet ifname eth1 master bond0 nmcli connection modify bond0 ipv4.method manual ipv4.addresses 192.168.1.10/24 nmcli connection up bond0这里有个细节容易被忽略:如果ETC下还躺着老的ifcfg-bond0、ifcfg-eth0等文件,NetworkManager与network服务大概率会产生配置竞争。建议提前确认系统默认接管网络的服务到底是谁,确定后就只走一条路,不要混用。
5.3 重启之前必须做的预检
我在任何绑定环境做重启操作前,都先走一遍检查:
# 确认bond设备当前存在,且成员正确 ip link show bond0 cat /sys/class/net/bond0/bonding/slaves # 确认启动配置文件里slave和bond的主从关系 grep -E "MASTER|SLAVE|ONBOOT|BONDING_OPTS" /etc/sysconfig/network-scripts/ifcfg-* # 确认当前网络服务状态 systemctl status network systemctl status NetworkManager如果条件允许,我强烈建议在业务窗口做一次重启验证。不要等到三个月后再重启才发现配置早已失效。生产服务器的网络配置,只有经过一次完整冷重启才算是真正落地。
6. 值得写进巡检习惯的几个绑定状态检查细节
最后一部分,不讲理论,说一说我现在的团队是怎么把“检查绑定运行情况”变成例行工作的。毕竟再好的命令,不形成习惯就是白搭。
6.1 巡检时直接抄走的命令表
下面这份表格可以直接保存进自己的运维手册:
| 目的 | 命令 |
|---|---|
| 查看所有bond设备 | ls /proc/net/bonding/ |
| 查看一个bond的完整状态 | cat /proc/net/bonding/bond0 |
| 查看绑定模式数字编号 | cat /sys/class/net/bond0/bonding/mode |
| 查看bond下有哪些slave | cat /sys/class/net/bond0/bonding/slaves |
| 查看轮询间隔 | cat /sys/class/net/bond0/bonding/miimon |
| 查看失败切换次数 | egrep "Link Failure Count" /proc/net/bonding/bond0 |
| 验证成员网卡物理链路 | ethtool eth0 eth1 |
| 查看bond数据收发错误统计 | ip -s link show bond0 |
| 查看内核日志里bond相关事件 | `dmesg |
| 查看网络服务日志 | `journalctl -u network |
6.2 如何判断“运行正常”的标准
很多朋友问,到底哪些指标组合起来才能说“绑定没问题”?我提供一个参考组合:
- Bonding Mode与设计一致;
- 每个slave的MII Status均为up;
- Speed和Duplex都协商到预期值(千兆/万兆、全双工);
- Link Failure Count在长时间内保持不增长;
- 数据层面无持续上升的RX/TX错误、丢包、backlog;
- ip -d显示的active slave与你预期的业务路径一致。
这六项全部满足,我才敢在巡检报告里写“绑定运行情况正常”。注意,是“长时间内不增长”,不是“当前为零”。
6.3 一个更稳妥的后续扩展方向
如果你管的是多台服务器,手工一条条敲命令终究太慢,后续可以顺着这个方向自动化:把前面说的for循环写成脚本,通过中心化定时任务拉到日志平台,对Link Failure Count设置趋势告警。比简单地监控“网卡up/down”更能提前发现问题。我自己已经在管理的几十台设备上跑这类的脚本,效果很稳定,省下的排查时间都用在真正需要决策的环节上。
最后再分享一个实操体会:任何时候在bond环境里做切换、改模式、重启网络,先把原状态完整记录下来,哪怕只是输出一份/proc/net/bonding/bond0的结果,都可能帮你在恢复时节省大量时间。绑定这东西,“能通”和“健康”之间的距离,比你想象的大得多。