
前几天在后端运维群里聊起一件事一台浪潮服务器装了 KeyarchOS上面跑着几个内网应用结果某个备份任务一启动就能吃满整张网卡的带宽其他业务的 API 全在超时重试。有人提议用 wondershaper 限速但实际一操作发现两个坎KOS 默认源里装不上手动装上以后限速又不稳定重启网卡就失效。这篇文章就围绕我在 KeyarchOS 下安装 wondershaper-1.2.1-2 的完整过程讲清楚带宽管理这个活应该怎么干以及怎么把限速这件事做得稳、做得可维护。无论你是刚接触 Linux 流量控制的初学者还是正在给服务器做带宽隔离的运维这个方案都值得参考。1. 为什么是 KeyarchOS 和 wondershaper 这个组合1.1 KeyarchOS 能直接兼容 CentOS 生态省掉一半适配成本KeyarchOS简称 KOS是浪潮信息推出的企业级服务器操作系统。我第一次接触 KOS 时最直观的感受是它的包管理方式、目录结构、服务管理方式和 RHEL/CentOS 这一脉非常接近。对于做运维的人来说这意味着大量已有的 RPM 包、systemd 服务和脚本都能直接拿过来用不需要像遇到某些完全不兼容的发行版那样重写部署流程。我在实际部署中用的是一台浪潮双路服务器KOS 版本是 8 系列。系统装好后cat /etc/os-release能看到 NAME 是 KeyarchOSID_LIKE 指向 centos/rhel这就确认了兼容性基线。基于这个前提凡是给 CentOS 8 生态准备的 rpm 包在 KOS 上基本都可以直接用。这也解释了为什么 wondershaper 1.2.1-2 这个原本为 EPEL 仓库打包的版本能顺滑地跑在 KOS 上。另外KOS 默认带了较完整的内核模块和网络工具链。带宽管理依赖的tc命令由 iproute2 提供KOS 默认已经安装。至于内核的流量控制模块默认也是可用的只有个别精简安装的场景才需要手动加载。这意味着我们安装 wondershaper 之前不需要折腾一堆前置依赖。1.2 wondershaper 1.2.1-2 到底是什么靠不靠谱wondershaper 本质上是一个 shell 脚本它把 Linux 内核里的 tcTraffic Control和 HTBHierarchical Token Bucket队列机制封装成了人能看懂的命令。以前我们要限速得自己敲一长串tc qdisc add、tc class add之类的命令漏一个参数就报错wondershaper 把这一切收敛成一行命令指定网卡、下行带宽、上行带宽完事。1.2.1-2 这个版本号前段 1.2.1 是上游软件版本后面 -2 是 RPM 打包版本号。换句话说这是基于上游 1.2.1 的第二个 RPM 构建专门为 RHEL 系发行版包括 CentOS、KOS准备的。相比某些仓库里随意打包的版本1.2.1-2 带了正规的 systemd 服务单元、默认配置文件、帮助文档安装后可以直接用systemctl管理。这对生产环境很重要因为一个软件如果只能靠手动敲命令运行那它就不具备可维护性。当然wondershaper 不是什么神兵利器。它只能做网卡级别的带宽整形不能精确到进程、不能识别应用类型。但它的好处是透明、简单、可改。整个脚本只有几百行出问题可以直接看源码定位这对于运维来说比黑盒方案安心得多。1.3 为什么不用其他限速方案在决定用 wondershaper 之前我也对比过常见的带宽管理方案方案原理适合场景主要问题直接用 tc 命令手写 HTB 队列规则需要精细控制流量时命令复杂维护成本高trickle基于 LD_PRELOAD 的库注入限速单台机器上少数进程对静态链接程序无效netem内核网络模拟模块模拟丢包、延迟不适合带宽整形iptables 限速通过 match 和 limit 控制包速率简单包级限速不精确只看包数wondershaper封装 tc HTB网卡级带宽分配粒度粗不能识别应用实际场景中我要解决的是“某个服务把整张网卡打爆”的问题影响面在网卡层面所以网卡级限速足够了。trickle 那种按进程限速的方式得逐个启动命令配置没法覆盖后台 fork 出来的子进程iptables 的 limit 模块基于速率平均算法突发控制能力很弱。wondershaper 用 HTB 做一个根队列下面挂多个 class每个 class 一个速率上限正好适合给整个接口设置一个可信总带宽。2. 安装前的检查先把地基打好2.1 确认系统版本和网卡命名别急着装软件先摸清楚系统底细。我用这几条命令cat /etc/os-release uname -r ip link show第一眼看系统版本第二眼看内核版本第三眼看网卡命名。在 KOS 上现代网卡一般叫 ens192、ens3f0、enp2s0 这类名字和 CentOS 的命名规则一致。要注意如果服务器上有多张物理网卡或者网卡上还挂着 VLAN 子接口后面配置 wondershaper 时就要特别小心别把流量限制到错误的接口上。确认网卡物理链路状态也值得做一下。用ethtool ens192能看到协商速率和双工状态。我曾经遇到过一台机器的网卡因为强制千兆导致限速效果看起来总是不对实际是物理链路本身只剩 1Gbps我给的限速值反而比物理带宽高根本不产生约束。2.2 确认 tc 命令和内核 HTB 模块可用wondershaper 的所有限速逻辑都建立在内核的 tc 子系统之上安装前必须确认 tc 命令可用、HTB 调度器模块已加载tc -s qdisc show dev ens192 modprobe sch_htb lsmod | grep sch_htb如果tc命令不存在说明 iproute2 包缺失用 dnf 补上即可。如果modprobe sch_htb报错说明内核版本太老或者模块被裁剪了。KOS 默认内核一般不需要额外加载但精简安装的服务器可能没带全模块这一步检查不能跳过。另外建议顺手看一下当前接口的默认队列规则。多数网卡的默认 qdisc 是pfifo_fast它不参与带宽整形。等 wondershaper 启动之后再来看这里会发现变成htb到时候你能直观感受到变化。注意sch_htb是内核模块如果你使用的是云上虚拟化网卡或某些老内核可能模块名略有差异。确认模块加载成功的标准只有一个tc qdisc add dev eth0 root htb不报错。2.3 确认软件源配置在 KOS 上安装 wondershaper-1.2.1-2最推荐的方式是从 EPEL 仓库装。先看一下当前启用的软件源dnf repolist如果里面没有 EPEL安装方式有两条路网络通畅的环境直接dnf install epel-release然后再次刷新源内网隔离环境则需要从能访问互联网的机器上下载对应的wondershaper-1.2.1-2.el8.noarch.rpm包拷贝到服务器上离线安装。不要试图跳过这个步骤去网上随便找一个 rpm 硬装因为不同构建版本的依赖声明可能不同装到一半报依赖缺失很难处理。对于内网环境我的习惯是准备一个本地目录保存常用 rpm 包作为离线仓库。这样不仅 wondershaper以后装别的工具都能用同一套流程比每次临时找包靠谱得多。3. 安装过程RPM 与源码两条路线实录3.1 路线一通过 dnf 在线安装如果服务器能访问外网这是最省事的路线dnf install -y epel-release dnf install -y wondershaper执行完之后确认版本rpm -qi wondershaper正常情况下你会看到版本号是 1.2.1-2.el8或类似的带 .el8 后缀版本。这个版本在 KOS 的兼容性表现不错依赖非常简单只有bash、iproute2、coreutils这些系统默认组件所以安装过程基本不会卡壳。3.2 路线二离线 RPM 安装内网环境下我在一台能联网的 CentOS 8 机器上执行yumdownloader wondershaper拿到 rpm 文件也可以通过 EPEL 的镜像目录手动下载。拷到 KOS 服务器后dnf install -y ./wondershaper-1.2.1-2.el8.noarch.rpm用./前缀是为了明确告诉 dnf 这是本地文件避免它去源里匹配同名包。安装完后用rpm -qa | grep wondershaper验证。这种方式的优点是不需要给服务器开放外网访问权限合规要求严格的内网环境也能顺利部署。3.3 路线三源码安装如果你需要修改 wondershaper 的行为比如自定义限速算法、增加日志、对接监控系统建议走源码安装。上游 GitHub 仓库里能拿到最新源码git clone https://github.com/magnific0/wondershaper.git cd wondershaper make install注意源码安装默认使用的版本可能不是 1.2.1 系列但这不影响核心用法。源码方式唯一的麻烦是升级不好管所以我的建议是能用 rpm 就用 rpm源码安装只保留给确实需要改动脚本逻辑的场景。经验无论哪条路线装完后第一件事不是急着配置而是rpm -qc wondershaper看配置文件到底在哪个路径。不同打包版本之间配置文件的位置可能不同以实际安装结果为准。3.4 安装后的文件结构wondershaper 安装完成后的核心文件大致如下/usr/sbin/wondershaper # 主脚本 /etc/conf.d/wondershaper.conf # 全局配置文件部分打包版本在 /etc/wondershaper/ /usr/lib/systemd/system/wondershaper.service # systemd 服务单元主脚本是核心它做的事情就是解析配置文件里的网卡名和带宽然后调用 tc 命令创建 HTB 队列。systemd 服务单元让限速可以开机自启也能用 systemctl 统一管理。我安装完习惯先执行一下wondershaper --help确认脚本能被正常解析。这一步能提前发现脚本依赖缺失或者权限问题比直接配置后重启服务时再报错要快得多。4. 配置、启动与稳定性增强4.1 最简单的三行配置打开配置文件一般只需关注三个参数IFACEens192 # 要限制的网卡 DOWNLINK100Mbps # 下行带宽 UPLINK20Mbps # 上行带宽这里的上下行概念容易搞反。对服务器来说DOWNLINK 和 UPLINK 的定义取决于脚本习惯建议直接看源码里变量的用途。多数版本里DOWNLINK 对应的是从互联网下载方向进入服务器的流量UPLINK 是服务器对外发送的流量。如果业务流量方向单一你可以只限制一个方向另一个填一个大值或不填写。带宽单位支持 kbps、mbps、gbps 等预设。需要注意wondershaper 在内部会把人类可读的单位换算成 kbps再传给学生队列。写配置时不要写小写 b脚本对大小写敏感填错了会报参数解析错误。4.2 启动服务并验证限速效果配置好之后启动服务systemctl enable --now wondershaper然后立刻验证队列规则是否真的落到了网卡上tc -s qdisc show dev ens192 tc -s class show dev ens192如果输出里能看到qdisc htb说明限速已经生效。这时候再用 iperf3 做一个双向测试下行和上行速率应当被限制在设定值附近。有个细节iperf3 测试时请把窗口和并发流数调到合理值。单线程可能达不到带宽上限容易被误判为限速失效反过来如果你开 30 个并发流看到的聚合带宽应当被平滑地控制在设定值附近这才是 HTB 起作用的标志。4.3 稳定性问题tc 规则为什么容易丢怎么守住这是整篇文章里最重要的一节。wondershaper 属于一次性配置工具它启动时把 tc 规则写到内核之后脚本就退出了。问题在于很多运维操作会让这些规则消失NetworkManager 重启网络服务网卡接口 down 再 up服务器重启一旦发生这些操作tc 规则被内核清除wondershaper 又不会自动重新执行带宽限制就失效了。表现就是业务高峰期带宽又被打满你还以为是限速配置没生效。要解决这个问题有两个层面的手段。第一层让 systemd 服务在网络就绪后再启动。查看/usr/lib/systemd/system/wondershaper.service确保 Unit 段里有Afternetwork-online.target Wantsnetwork-online.target这样可以避免服务器刚开机时网卡还没就绪wondershaper 就往一个不存在的接口上挂队列。第二层加一个守护脚本定时检查 tc 规则还在不在不在就重新拉起。我写了一个简单的脚本放在/usr/local/bin/wondershaper-check.sh#!/usr/bin/env bash IFACE$(grep ^IFACE /etc/conf.d/wondershaper.conf | cut -d -f2) if ! tc qdisc show dev $IFACE | grep -q htb; then systemctl restart wondershaper logger -t wondershaper-check htb qdisc missing, restarted wondershaper on $IFACE fi配合 crontab 每分钟执行一次* * * * * /usr/local/bin/wondershaper-check.sh这套方案我跑了几个月效果很稳。核心思想是不要信任一次性脚本要用系统机制保证最终状态。如果你服务单元里带wondershaper.service模板也可以用 systemd timer 机制达到同样效果原理类似。4.4 配置防火墙注意点在 KOS 上firewalld 默认可能是 enable 状态。防火墙本身和 tc 是两条独立的链路互不干扰但有两个情况容易混淆一是如果防火墙有 NAT/转发规则并且你想限制的是转发流量wondershaper 的网卡级限速依然有效因为 tc 工作在网卡队列层先于 iptables 处理。二是如果你的自定义脚本里调了 iptables 写动态规则SELinux 可能会干预需要看/var/log/audit/audit.log。KOS 默认 SELinux 是 enforcing遇到限速脚本执行权限问题时优先检查审计日志而不是直接关 SELinux。5. 常见问题与排查技巧实录5.1 限速完全不生效遇到限速不生效先按这个顺序排查现象可能原因排查命令tc 显示没有 htb 队列服务没起来systemctl status wondershaper队列存在但速率不降网卡名写错限制到了空接口ip link show逻辑接口和物理接口混淆流量走的是子接口或网卡 bondtc -s qdisc show dev 各接口限速值比物理带宽还高配了 1000Mbps 但物理链路只有 100Mbpsethtool ens192我碰到最多的情况就是配了逻辑网卡比如 bond0 上有业务流量但 wondershaper 限制的是 bond0 的某个 slave 物理口。流量根本不会从那个口走等于白干。所以配置前用ip route看一下默认路由的出口接口务必确保 IFACE 就是实际承载流量那一侧。5.2 限速效果时有时无速率忽高忽低这通常不是 wondershaper 的问题而是 HTB 参数没调好。wondershaper 默认会给 class 配置一定的 burst 余量这是为了允许短时突发流量。但如果你把 burst 设得过大而应用的流量模式本来就是脉冲式的就会造成速率波动很大看起来像限速不稳定。减小 burst 的办法是修改 wondershaper 主脚本里burst相关的 tc 参数或者用tc qdisc change实时修改。我建议先跑tc -s class show dev ens192观察每个 class 的发送字节数是不是集中在某个速率附近。如果 class 的速率一直在设定值以上波动再考虑调低 burst。另一个容易被忽略的因素是网卡中断合并coalescing。某些服务器网卡的 adaptive coalescing 会在流量突增时改变中断频率导致 tc 的速率控制采样不够平滑。通过以下命令临时关闭后测试ethtool -C ens192 adaptive-rx off如果关闭后限速稳定了那就可以在 BIOS 或网卡驱动层面固化配置。不过这个只影响极端精度要求的场景普通限速场景可以忽略。5.3 重启后所有配置都丢了这是标准的“没做开机自启”或者“服务启动太早”问题。先确认systemctl is-enabled wondershaper如果是 disabled执行 enable。如果是 enabled 但重启后依然失效大概率是服务单元里没有依赖 network-online.target。按 4.3 节的方式修改服务单元然后执行systemctl daemon-reload重新加载。还有一种情况服务器重启过程中NetworkManager 在 wondershaper 之后才接管网卡导致网卡被重新配置了一次把 tc 规则冲掉。这种情况下 systemd 的依赖关系解决不了只能用 4.3 里的守护脚本来兜底。这也是为什么我一直强调守护脚本比单纯 enable 更可靠的原因。5.4 多网卡和 VLAN 场景wondershaper 默认只处理一个网卡。如果你有多个业务网卡或者网卡上挂着 VLAN 子接口处理方式不同多网卡场景如果服务单元支持模板实例可以按iface.service的格式启动多个实例如果不支持就多写一个 systemd service 文件复制一份改一下 IFACE 配置。VLAN 子接口场景需要特别注意tc 规则加在主接口上会影响所有子接口的流量通常这不是你想要的。更精细的做法是在子接口上分别限速比如ens192.10限一个速率ens192.20限另一个速率这样业务间才能隔离。6. 生产环境里的几个进阶建议6.1 把突发流量精确控住默认的 wondershaper 配置更偏向“能跑就行”如果业务要求严格流量整形建议手动调整 HTB 的 burst 量。在 wondershaper 主脚本里通常有类似这样的 tc 命令tc class add dev $IFACE parent 1: classid 1:$class htb rate $UPLINK burst 15k这里的burst 15k就是突发余量。单位是字节15k 大约突发 12 个 1500 字节的包。把它调小到burst 6k能明显降低速率尖峰但要提醒一下burst 过小会拖垮 TCP 长连接吞吐因为 TCP 的突发本来就是窗口机制驱动的。调整后务必用 iperf3 做长流测试自己眼睛看到的曲线才是最可靠的标准。6.2 按时间段定时限速有些场景不需要全天限速比如凌晨备份时段放开带宽、高峰期限制大流量下载。用 cron 就能实现# 每天 23 点到次日 7 点放开带宽 0 23 * * * /usr/sbin/wondershaper clear ens192 0 7 * * * /usr/sbin/wondershaper ens192 100Mbps 20Mbps注意wondershaper clear是清除限速规则不是删除网卡配置。如果没有 clear 子命令的版本用systemctl stop wondershaper也可以达到同样效果。这种定时方案的可靠性取决于 cron 服务是否存活生产环境建议用 systemd timer日志更统一还能查触发历史。6.3 和监控联动自动限速比定时限速更高级一点的玩法是和监控数据联动。我在 KOS 上部署过一个简单脚本通过 vnstat 或 netdata 周期性读取网卡实时速率连续 N 次超过阈值就自动调用 wondershaper 降速流量回落后自动 clear。逻辑并不复杂但要注意加一个冷却时间防止脚本在限速和恢复之间频繁抖动。联动脚本一定要有日志输出。我用 logger 写进 syslog事后排查问题时能看到每一次自动限速是什么时候、因为什么触发的否则这个功能就是个黑盒出了事故反而不如手动控制好排查。6.4 升级与卸载wondershaper 版本迭代不算频繁但如果要升级RPM 方式直接在覆盖安装即可dnf upgrade wondershaper升级前最好备份一下配置文件。卸载则执行dnf remove wondershaper卸载后 tc 规则会自动清掉不会残留队列。这个和其他网络工具不一样wondershaper 卸载还算干净利落。最后说一个自己的实操习惯每次在 KOS 上部署完带宽管理我都不会直接交付而是做三件收尾的事第一用tc -s qdisc show把限速后的统计信息抓一份存档这样后续性能下降时能对比判断 tc 是否正常工作第二在配置文件的注释里写上这个限速策略的变更日期和原因方便几个月后回看第三故意重启一次网络服务验证守护脚本能自动恢复限速。这三步看着简单但能避开绝大多数“装好了但不知道什么时候失效”的坑。带宽管理这个领域真正难的不是把规则配出来而是让规则在服务器的各种变化里始终存活。wondershaper 给了我们一个轻量的起点配合 KOS 的 systemd 和 shell 能力它完全可以变得比想象中可靠得多。