4、OVS QoS配置命令:ovs-vsctl set port qos命令详解
好,咱们接着往下聊。上一节我把QoS的整体框架和限速原理讲清楚了,这一节咱们直接上手——敲命令。
在Open vSwitch里,配置QoS最核心的命令就是ovs-vsctl set port。说白了,就是把一个QoS策略绑定到某个端口上。我刚开始接触OVS时,总觉得这命令很简单,不就是set一下嘛。结果第一次在生产环境配限速,忘了清空旧策略,导致整个出口带宽被打满,差点背锅。嗯,从那以后我再也不敢小看这条命令了。
4.1 命令基本语法
先看最基础的写法:
ovs-vsctl set port <port_name> qos=<uuid>
这条命令的意思很直白:给名为<port_name>的端口,绑定一个UUID为<uuid>的QoS对象。你想想看,QoS对象就像一张限速规则表,端口就是执行这张表的出口。
但实际工作中,我们很少手动去查UUID。更常见的做法是直接内联创建:
ovs-vsctl set port eth0 qos=@newqos \
-- --id=@newqos create qos type=linux-htb \
other-config:max-rate=1000000000 \
queues:0=@q0 \
queues:1=@q1 \
-- --id=@q0 create queue other-config:max-rate=500000000 \
-- --id=@q1 create queue other-config:max-rate=300000000
这条命令一口气做了三件事:创建QoS对象、创建两个队列、把QoS绑定到端口。我个人习惯用这种内联写法,因为逻辑清晰,一条命令搞定,不容易漏掉关联关系。
4.2 参数详解
咱们拆开来看每个参数的含义。我整理了一张表,方便你对照:
| 参数 | 说明 | 必填/可选 |
|---|---|---|
type |
QoS类型,常用linux-htb(层次令牌桶)或linux-hfsc |
必填 |
other-config:max-rate |
端口总带宽上限,单位bps。例如1Gbps就是1000000000 | 可选(建议设置) |
queues |
队列映射表,格式queue_id=@queue_obj |
必填(如果使用队列) |
other-config:min-rate |
队列保证带宽,单位bps。HTB模式下有效 | 可选 |
other-config:burst |
突发流量大小,单位字节。控制瞬时峰值 | 可选 |
other-config:priority |
队列优先级,数值越小优先级越高 | 可选 |
这里有个坑,我曾经踩过:max-rate的单位是bps,不是Bps。1Gbps = 1000000000,不是1073741824。如果你按字节去算,限速会偏小很多。嗯,这个细节很容易被忽略。
4.3 实战:给虚拟机网卡限速
假设你有一台虚拟机,它的虚拟网卡叫vnet0,你想给它限速到200Mbps。怎么做?
ovs-vsctl set port vnet0 qos=@qos \
-- --id=@qos create qos type=linux-htb \
other-config:max-rate=200000000 \
queues:0=@queue \
-- --id=@queue create queue other-config:max-rate=200000000
这条命令执行后,vnet0的出口带宽就被限制在200Mbps了。注意,我这里只创建了一个队列,队列ID是0。如果你不指定队列,OVS会使用默认行为,但那样就失去了精细控制的意义。
我个人建议,哪怕只做一个限速,也显式创建一个队列。为什么?因为后续你要加优先级、加突发控制时,直接改队列参数就行,不用重构整个QoS结构。
4.4 查看和验证配置
命令敲完了,怎么确认生效了?用ovs-vsctl list port:
ovs-vsctl list port vnet0
输出里会有一行:
qos : 8a2f3c1e-... (uuid)
有这个UUID就说明绑定成功了。再进一步查看QoS详情:
ovs-vsctl list qos 8a2f3c1e-...
你会看到类似这样的输出:
type : linux-htb
other_config : {max-rate="200000000"}
queues : {0=3b7d9e2f-...}
嗯,到这里基本就确认配置没问题了。但我想提醒你一句:ovs-vsctl list看到的只是控制面的配置,数据面是否真的生效,还得用tc命令或者实际打流来验证。我遇到过配置写对了,但内核模块没加载的情况,结果限速根本没起作用。
4.5 修改和删除QoS
改配置很简单,重新set一次就行。比如把限速从200Mbps改成500Mbps:
ovs-vsctl set queue 3b7d9e2f-... other-config:max-rate=500000000
注意,这里改的是队列对象,不是端口。如果你要改端口的总带宽,就改QoS对象的max-rate。
删除QoS呢?先把端口上的绑定清掉:
ovs-vsctl clear port vnet0 qos
然后再删QoS对象和队列:
ovs-vsctl destroy qos 8a2f3c1e-...
ovs-vsctl destroy queue 3b7d9e2f-...
顺序很重要。我曾经先删了QoS对象,结果端口还引用着它,导致OVS报错。正确的做法是:先解绑,再销毁。
4.6 常见错误与排查
最后列几个我遇到过的典型错误:
- 错误1:
ovs-vsctl: no row "qos" in table Port
原因:端口名写错了,或者端口不存在。用ovs-vsctl list port确认一下。 - 错误2:限速不生效,但配置看起来都对
原因:可能是内核没加载sch_htb模块。执行modprobe sch_htb试试。 - 错误3:队列优先级不生效
原因:HTB模式下,优先级只在同一层级的队列间有效。如果你搞了多层嵌套,优先级逻辑会变复杂。
tc -s qdisc show dev vnet0看一眼实际生效的队列规则。OVS的配置最终会映射到内核的tc规则上,所以tc的输出才是最真实的。如果tc里看不到你配的规则,那说明OVS的配置没推下去。
好了,这一节的内容就到这。ovs-vsctl set port qos这条命令,说白了就是给端口挂上一套限速规则。你只要记住:先建QoS对象,再建队列,最后绑定到端口。顺序别搞反,参数别写错,基本就不会出大问题。