type
status
date
slug
summary
tags
category
icon
password
https://tonydeng.github.io/sdn-handbook/linux/tc.html
Vdsm 中,vm 的流量控制与 host 的流量控制有不同的接口和调用链。
fq_codel 是一种流量控制算法:https://queue.acm.org/detail.cfm?id=2209336
## QOS
服务质量(英语:Quality of Service,缩写QoS)是一个术语,在分组交换网络领域中指网络满足给定业务合约的几率;或在许多情况下,非正式地指分组在网络中两点间通过的几率。QoS是一种控制机制,它提供了针对不同用户或者不同数据流采用相应不同的优先级,或者是根据应用程序的要求,保证数据流的性能达到一定的水准。QoS的保证对于容量有限的网络来说是十分重要的,特别是对于流多媒体应用,例如VoIP和IPTV等,因为这些应用常常需要固定的传输率,对延迟也比较敏感。
## Ovirt 中的 QOS
在 ovirt 中,可以针对磁盘、主机网络、虚拟机网络、cpu设置 qos 。
### Host 网络 Qos
#### 代码分析
Ovrit 中设置网络相关的,基本都由一个函数(setupNetworks)作为入口。
https://www.ovirt.org/develop/developer-guide/vdsm/network.html
在 ovirt-engine 代码中,以下几种情况会调用 setupNetworks:
1、创建主机、更新主机,或者手动调用主机的重新安装会执行;
2、在主机的网络编辑页面对网络适配器的增删改会调用;
3、复制主机网络;
4、主机网络启用/禁用;
5、给网络配置打标签;
首先,在 API.py 中暴露 rpc 接口给 engine: 代码相对路径
lib/vdsm/API.py
Networks 的接口通过 supervdsm-api 暴露出来,所以非 supervdsm 服务在调用时需要使用 getProxy() 去调用,被调用的函数位置为:lib/vdsm/network/api.py -> _setup_networks
继续跟着 setup 的函数进去,会来到一个名为 _setup_nmstate 的函数,位置在: lib/vdsm/network/netswitch/configurator.py
这里调用了 _setup_qos 的方法去设置 host 网络
_setup_qos 又去调用了 _configure_qos,而 _configure_qos 最终调用了 qos 模块的 qos.configure_outbound
注意:这里只有设置 outbound,没有 inbound,对应到 ovirt-engine,在设置主机网络的 qos 时,也只支持 outbound,不支持 inbound,原因是网络没有办法限制外部的设备往自身发送网络包,所以 inbound 规则本身能做的事情非常少,合理的方式是去限制网络数据包的发送方。
一直到 configure_outbound 这个函数,终于看到跟网络控制相关的一些代码了。
root_qdisc 获取了网卡设备的 qdisc。
然后 _fresh_qdisc_conf_out 会去更新 qdisc,当没有 root_qdisc 时会调用 _qdisc_conf_out 去新增一个 qdisc。
接着看一下 _qdisc_conf_out 方法,这里面就是在拼接一些规则,然后调用 tc 的命令去完成主机网络的配置。
_fresh_qdisc_conf_out 也是类似,拼接 tc 的规则,然后去完成主机网络的配置。
VM 网络 Qos
vm qos 由 libvirt xml 定义,参考官网定义:https://libvirt.org/formatnetwork.html#quality-of-service
#### 代码分析
vm 网络的 qos,由 lib/vdsm/API.py 中的 hotplugNic 设置网络接口的 inbound 和 outbound 的带宽。
在 ovirt-engine 中,在插入和拔出网络接口时,会调用 hotplugNic 方法。
首先,由 API.py 中的 hotplugNic 调用了 self.vm.hotplugNic(params)
去查看 self.vm.hotplugNic(params) 的代码:
其中主要就是解析 params 中的数据,然后拼接出来一个 xml 数据,并调用 libvirt 去操作。
dev_from_xml 在 lib/vdsm/virt/vmdevices/network.py 中有对应的实现 from_xml_tree。
attachDevice 最终是调用的 libvirt,官网中有对应的方法 https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainAttachDevice
attachDevice 的调用链:vm.self._dom,而 self._dom 是 在 vm._run 中的
VM Qos(cpu limits和 IO limits)
vdsm 更新 cpu limits 和 IO limits(磁盘 iops) 是通过调用 libvirt 去更新 vm 的 xml 实现的,更新 vm 的方法有多个。其中一个是 updateVmPolicy,在修改已有的 qos 时,会调用这个方法。
还有一个是 hotplugDisk,这是在附加磁盘时会调用,也是去更新 vm 的 xml。
在网页上设置了 cpu qos 和 磁盘 qos以后,需要附加到虚拟机上,才会调用 updateVmPolicy 方法,使得 qos 生效。没附加到虚拟机之前,这些修改不会在 vdsm 的日志中体现。
updateVmPolicy:
- vm 探活时执行:探活过程中有判断,判断数据有变化(可能是根据时间戳对比)时调用,探活频率是5秒一次。页面上点击更新是直接触发。
- 手动移除 qos 时会执行,移除 storage 和 cpu 的 qos 时会触发。
hotplugDisk:
- 目前已知在附加磁盘时,会调用。还有一个 AddDiskComand,猜测是在新建虚拟机时点击新建磁盘,最后也会调用到这里。
代码分析
针对虚拟机的资源限制,入口函数为 lib/vdsm/API.py 中的 updateVmPolicy。然后调用了 lib/vdsm/virt/vm.py 中的 updateVmPolicy 函数。
updateVmPolicy 函数如下:
最终 vdsm 是调用了 libvirt 的 setMetadata 方法去更新 vm 的信息,有关 vm 的 xml 定义可以参考:
https://libvirt.org/formatdomain.html
- 作者:阿杰鲁
- 链接:http://blog.zaunist.com/article/5a0d4a54-8560-4ffc-a96d-94a3f9446adb
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。