共计 8073 个字符,预计需要花费 21 分钟才能阅读完成。
导读 | 大家好,本次肖力分享的主题是 KVM&Libvirt 基本概念及开发杂谈,内容有些凌乱松散,主要基于自己早期整理的笔记内容和实践感悟,有些内容难免有失偏颇,望见谅。前面先介绍下需要了解的基本知识,大部分内容在肖力著作中都有更详细的解释,可阅读参考。 |
1. 内核模块 kvm.ko, 用于核心虚拟框架。2. 包含与处理器相关的模块 kvm-intel.ko,kvm-amd.ko
3.kvm 需要使用经过修改定制的 qemu 软件提供用户空间工具
* 内核组件已经包含在 Linux 内核 2.6.20 中了
* 部分操作系统在 kvm 中运行仍然存在某些问题,可以查看 KVM 官网提供的操作系统运行兼容性状态列表
1.qemu-kvm-release.tar.gz
2.kvm-kmod-release.tar.bz2, 自己编译内核模块的需要这个东东
3. 支持 VT 技术的 Intel 处理器或支持 SVM 技术的 AMD 处理器
1.zlib 库及头文件
2.sdl 库及头文件
3.alsa 库及头文件,这个是用来提供虚拟化音频相关功能,默认是禁用的,现在不知道什么状态了,可以使用 --enable-alsa 来启用
4.gnutls 库及头文件,可选的 VNC TLS 支持,默认此功能是开启的,可以用 --disable-vnc-tls 关闭
5.kernel 头文件
* 创建,安装,运行 KVM 虚机,需要使用 QEMU 提供的用户空间工具,以前是分开发布的,现在分支已经合并,成为 qemu-kvm。*libvirt 为用户提供了同不同虚拟化技术交互的抽象接口。
1. 同 linux 虚拟化技术进行交互
2. 免费,自由
3. 稳定的 C 语言 API
4. 其他通用语言的绑定开发接口(java,python,perl,php。。。)5. 针对 DMTF 虚拟风格
6.QMF 代理,用于 AMQP、QPID 信息系统
虚拟技术:kvm/qemu, XEN, LXC, OpenVZ, UserModeLinux, VB, ESX, HyperV, PowerVM, Parallels, Bhyre
虚拟网络:桥接,NAT,VEPA,VNLINK
存储:IDE、SCSI,USB,FC,LVM,ISCSI,NFS,FS
1. 直接支持 c 和 c ++,其他通过绑定支持
2.C#,JAVA,OCAML,Perl,PHP,Python
3.libvirt 直接支持 python,如果是通过安装包安装而不是源码编译的,需要确保安装合适的包,在 RHEL 中,叫 libvirt-python,在 ubuntu 中叫 python-libvirt,其他平台可能有不同的名字。
1. 指定 URI 连接到 libvirt:通过把 name 参数传递到 virConnectOpen 或 virConnectOpenReadOnly 方法:virConnectPtr conn = virConnectOpenReadOnly("xxx:///default");
2. 为节省管理员时间,可以在 libvirt 客户端配置文件中配置 URI 别名,配置文件位置 /etc/libvirt/libvirt.conf(针对 root 用户) 或 $XDG_CONFIG_HOME/libvirt/libvirt.conf(针对非特权用户),可用下面语法设置别名 uri_aliases = ["miaomiao=xxx://xxx@www.xxx.com.cn/system", "wangwang=xxx://xxx@www.xxx.com/system"] 别名由 a -z,0-9,_等字符组成,URI 别名会应用到任何打开 libvirt 连接的应用中,除非把参数 VIR_CONNECT_NO_ALIASES 传给 virConnectOpenAuth,如果别名中包含非法字符,则不做任何别名查找。如果 URI 传递给 virConnectOpen 参数为 NULL,则 libvirt 会用下面规则确定 URI:1. 环境变量:LIBVIRT_DEFAULT_URI
2. 客户端配置文件:uri_default 参数
3. 探测每个虚机管理器知道找到一个可用的
node:节点,宿主机,一个 node 是一个单独的物理机,用于运行虚机
hypervisor:一个软件层,可以把一个物理机用不同的配置虚拟化为多个虚机的集合
domain:虚拟机,在容器级虚拟化情况中,是一个子系统,运行在由 hypervisor 提供的机器上
libvirt:提供一个通用的软件层,安全高效的管理 node 上的 domain,同时实现远程管理功能。
* 在 windows 系统中使用 libvirt java 绑定,需要使用 libvirt java 库,jna.jar 库及对应平台的 dll 文件,如果报错:找不到 dll 或找不到相关模块时, 需要安装 virtviewer 在 java 代码中加入:System.setProperty(“jna.library.path”, “c:\\program files\\VirtViewer\\bin”); 并需要在上面路径放置一份 virt-0.dll 文件副本,命名为 virt.dll
SPICE 服务端是一个用 libspice 实现的 VDI 库,VDI 定义了一系列接口来发布虚拟设备。(如:显示设备,键盘,鼠标)并且能让不同的 spice 组件和这些设备交互,从一方面来说,服务端使用 spice 协议同客户端通信,从另一方面来说,服务端同 VDI 主机应用进行交互如 QEMU。SPICE 客户端是最终用户所面对的接口。
当 libspice 与 qemu 结合使用时,QEMU QXL PCI 设备可以用来提升远端显示性能,增强客户机的图形系统。QXL 设备需要客户机 QXL 驱动支持。SPICE 协议支持一种通信信道,此通道连接客户和服务端的代理,当使用 QEMU 时,SPICE 代理位于客户机,VDI 端口是一个 QEMUPCI 设备,可以与此代理进行通信。
主通道:控制与配置
显示通道:图形命令,图形,视频流
输入通道:键盘和鼠标输入
光标通道:定位设备的位置与光标形状
回放通道:服务端的声音在客户端播放
录制通道:从客户端进行音频捕获
SPICE 本身提供了多种图像压缩算法,可以在服务器初始化时进行选择,也可以在运行期动态选择. QUIC 是 SPICE 专有的图像压缩算法,此技术基于 SFALIC 算法,Lempel_zip(LZ) 算法同样也是 SPICE 支持的算法。QUIC 和 LZ 都是本地算法,独立编码每一个图像。全局 LZ(GLZ)是另一个 SPICE 专有算法,与 LZ 同基于历史的全局字典表共同使用,GLZ 可以在大量图像之间使用重复表达式来降低流量消耗,从而保存带宽。特别适合在低带宽的广域网环境中使用。SPICE 同样提供了一个针对每一个图像自动选择压缩算法的工作模式,通过图像属性启发式的选择 LZ,GLZ,QUIC 算法。从理论上讲,LZ、GLZ 更适合压缩合成图像,QUIC 更适合压缩真实图像.
SPICE 使用低损压缩算法压缩发送到客户端的图像,但是视频流却是使用不同的方法来处理。SPICE 服务端使用自启发方式标记动态视频区域并把他们作为视频流发送出去,编码使用 mjpeg,这种处理方法在某种程度上节约了流量,提高了 spice 性能,尤其在广域网环境中。可是在某些情况下,这种启发行为可能会导致低质量的图像效果,比如把不断更新的文本区域识别为视频区域,从而导致部分区域图像效果质量低下。
*qpixman:一个控制像素区域的通用库,包括低级别像素控制程序,同时也被 cairo 库使用,cairo 是一个用于支持多输出设备的 2D 图形库,qpixman 是 pixman 的轻量级修改版
*qcairo:cairo 是一个矢量图形设备无关库,qcairo 是 cairo 的轻量级修改版 *celt:CELT 是一种音频压缩算法,以高质量传输音乐,信号会有非常小的延迟 *ffmpeg:是一个用于音频和视频重编码,转换,流传输的库。包括 libarcodec 音频视频编码库 *log4cpp 是一个灵活的日志记录库,可以针对文件,syslog 等,继 log4j 之后成型
* 关于 windows 虚机安装 virtio 硬盘驱动的问题,一种方式是在安装系统的过程中加在 virtio 驱动光盘或软盘(winxp),如果系统已经装完,可以先创建一个小磁盘镜像,qemu-img create -f qcow2 xxx.img 1G 编辑虚机配置文件,加入此硬盘镜像,设置参数 dev=’vdc’ bus=’virtio’ 启动系统后会发现新硬件,选 ISO 镜像中对应的 virtiosto 驱动选 virtioscsi 驱动关闭 vm,修改虚机配置,删除小硬盘镜像,把原磁盘改为 dev=’vda’ bus=’virtio’ 并删除地址部分,启动系统查看驱动情况。
* 关于已有 libvirt 时自己编译 libvirt 时导致 libvirt-sock 不存在情况,该位置在 /run/user/1000/libvirt/libvirt-sock 或 /usr/local/var/run/libvirt/libvirt-sock, 编译后加在 libvirtd 守护进程,用 netstat 查看 libvirt-sock 是否在配置文件制定位置侦听。
* 在使用 java 程序编写 libvirt 应用时,当虚机处于 pmsuspended 状态时是无法获取 domainInfo 信息,会出现数组越界的错误提示。
* 使用 attachDevice 方法添加设备时要注意,flag= 0 时,表示执行结果影响当前状态,当前状态为运行状态,则只有运行时存在,当前状态为关闭状态则影响关机配置文件。flag= 1 时,表示影响运行时状态,执行此方法时,虚机必须处于 Active 状态。flag= 2 时,表示影响虚机持久配置文件,但是在 qemu 环境中 flag= 1 会不支持,程序会爆出不支持热插拔,可以使用 domainUpdateDeviceFlags 进行换盘操作。更新持久配置文件后,需要关机重新启动以使新配置生效。domain.getXMLDesc() 方法获取的是虚机的运行时配置,而不是持久化配置,所以会看到被删除的设备仍然还在。
* 使用 DomainUpdateDeviceFlags() 方法更新虚机配置时,使用 updateFlags 0 或 1 都会更新处于 Active 状态的虚机运行时配置,在虚机重启后会保持这种更新,因为重启虚机不会重新加载持久化配置,关机之后重新开机,配置会还原为原先配置。当使用 updateFlags 为 2 时,会出现无法更新的情况,虽然方法会执行成功,但无法更新持久配置文件。在关机状态下,使用 updateFlags= 1 时,会报错,因为更新 Live 状态只能在 domain 的 active 状态下执行。
* 需要注意的是 Libvirt 不支持 cdrom、floppydisk 驱动器的热插拔,使用 attachDevice() 方法时,制定 flags 为 0 或 1 时,某些设备类型如 CDROM 对运行时修改可能会返回失败,原因是 hypervisor 底层驱动不支持。如果对正在进行块复制的设备进行 detach() 方法操作,hypervisor 可能会阻止 detach() 的操作,在这种情况下,需要先使用 domainBlockJobAbort() 方法先停止该复制操作即可。
* 根据 hypervisor 和设备类型的不同,在一个处于 active 状态的 domain 中去除一个设备的操作可能是异步执行的,也就是说,当你执行 detach() 方法时,仅仅是请求去除一个设备,实际去掉此设备的时间可能是之后的一段时间,这是根据虚拟层与客户 os 配合完成的。这往往容易被忽略,因为有时会看到在配置文件中此设备已经被删除了,但 hypervisor 可能还没有真正删除这个设备,这可能会导致某些后续操作的失败。想要检查设备是否真的被成功删除了,要么重新使用 domainGetXMLDesc() 方法,要么为 DOMAIN_EVENT_ID_DEVICE_REMOVED 增加一个事件处理器,如果当 detachDeviceFlags() 方法返回时,设备已经被删除,事件会在 API CALL 结束之前触发。为了帮助现有的客户端在大多数情况下更好的工作,这个 API 会尝试把在请求之后过了一段时间才完成的异步删除操作转变为同步删除操作,换句话说,API 在异步操作的情况下会等待一会儿来让删除操作得以完成。注意,热插拔设备不会保持,一旦 domain 进入 S4 状态即 hibernation 状态,除非同样修改了 domain 的持久配置文件。
* 使用 setMaxMemory() 方法设置虚机最大内存时,默认使用的是 AFFECT_CURRENT,也就是说当 domain 关闭时,修改持久化配置文件,当 domain 处于 active 状态时,修改运行时配置或运行时持久化配置都修改,这个要看 hypervisor 的行为而定。例如,在 libvirt 中当 domain 处于 active 状态时,修改最大内存时会报错,必须关闭 domain 再修改持久化配置。
如果某虚机创建快照时使用的是内部快照或系统检查点,则该虚机所有硬盘都必须创建内部快照,qemu 不支持创建混合快照,即一部分硬盘创建内部快照,一部分创建外部快照,当然只读盘如光驱默认是不创建快照的。
系统检查点默认所有可读写硬盘使用内部快照(关机状态下,会忽略 disks 标签内容)。
如果在创建快照方法中指定了 flags 为 16(disk-only),则没有明确指定快照方式的硬盘默认使用外部快照,qemu 目前不支持内外部混合快照。
使用系统检查点快照时,对 cpu 特性集有要求,当 domain 配置中 cpu 特性集有 invtsc 特性时,在 domain 运行时执行系统检查点快照会报错,解决办法,去掉 invtsc 特性或将 cpu model 改为 custom。
当执行系统级快照时(开机状态下),如果配置文件标签制定 snapshot=internal 则硬盘快照默认也会使用 internal 方式执行,反之如果标签制定为 external 则硬盘默认也会使用 external 方式执行。这是因为 qemu 快照机制目前不支持内外部快照混合模式,libvirt 内部机制会自动把硬盘快照方式调整为与内存相同方式。
使用外部快照要注意,执行外部快照文件是指向原硬盘快照(base 盘)的从镜像,执行完外部快照后,libvirt 会将 domain 配置文件中的硬盘镜像改为新创建的外部快照文件,这样此文件可以用来存储执行快照后所有差异化内容,所以,libvirt 不允许直接删除外部快照。外部快照会与之前创建的外部快照形成一个差异存储链,内部快照不会与外部快照形成一个差异存储连。创建快照之后,快照配置文件会包含虚机配置文件的全部内容用于还原。
外部快照 内部快照
win7————————->win7_snap——————–>win7_snap2(包含在 win7_snap 文件内部)
vm 外部 vm
|———————>win7_snap3
vm
win7 是 win7_snap 的 backingstore,win7_snap2 快照存在于 win7_snap 文件中,win7_snap 是 win7_snap3 的 backingstore,内存外部快照可重复覆盖。* 在关机状态下,执行任何快照,不能包含有内存状态,需要把内存 snapshot 设置为 no,因为关机状态下没有内存运行状态,内存都清空了。* 创建系统检查点时,在关机状态下,默认创建内部快照,而且必须使用内部快照,创建外部快照会报错,但是使用 disk-only 模式快照,则在关机状态下允许创建外部快照同时也允许创建内部快照。外部快照声称的默认文件名称为原始硬盘镜像. 快照名称 * 使用 disk-only 方式针对正在运行的虚机创建快照,必须使用 external 方式,并且标签的 snapshot 必须为 no,使用内部快照会报错,内部快照和系统检查点快照要求所有硬盘都必须参与执行快照,使用 disk-only 和 external 方式并用执行快照才能针对不同硬盘单独执行快照策略。* 使用系统检查点快照方式对处于 active 状态的虚机执行快照,快照生成的是内部还是外部取决于 memory 标签的 snapshot 值。* 使用 diskonly 模式或关机状态下创建快照,标签 snapshot 必须为 no,因为以上两种快照都无法保存内存状态。
1. 虚机关机状态,diskonly 模式:memory=no(必须),disk 可以使用内部或外部快照,并且外部快照可以对每个盘分别定制创建策略,默认创建 external 快照。2. 虚机运行状态,diskonly 模式:memory=no(必须),disk 快照只能使用 external 模式创建,不支持创建内部快照。3. 系统检查点,虚机关闭状态:memory=no(必须),disk 快照只能使用内部快照,而且是真对所有硬盘,无法针对每个盘定制快照创建策略。4. 系统检查点,虚机运行状态:memory=internal 或 external,disk 快照的创建模式根据内存快照创建方式而定,不管内部还是外部快照都只能对所有硬盘创建快照,不支持对每个硬盘定制创建策略。为什么快照机制这么混乱,因为 libvirt 和 qemu 对快照机制持有不同观点,但是那种观点更好,这是见仁见智的,我们可以根据情况选择使用。ps:内部快照优点:不单独声称额外文件,没有存储连(其实是内部元数据,机制类似),降低了文件管理复杂度,libvirt 对内部快照有良好支持。ps:内部快照缺点:创建速度较慢,qemu 上游较少维护,必须使用 qcow2 之类支持级联快照功能的文件格式。运行时创建快照虚机有明显停顿感。ps:外部快照优点:创建速度较快,支持各种源文件格式(后续快照需使用 qcow2 之类),在运行时创建客户机几乎没有停顿时间,上游 qemu 在外部快照开发方面较积极
ps:外部快照缺点:快照多了后会形成大量存储文件及存储连,每一层级都使用 cow 方式读写,严重影响性能,文件管理复杂,libvirt 对外部快照支持不太积极。
答:快照建议根据我列出的特性进行选择,不建议把快照功能做得太多太复杂,快照多了会影响性能,如果必须要做外部快照,因为文件使用 backingstore 方式存储,最好对不用的快照进行 commit, 内存复用可以做快照,大规格内存做快照需要定制源码做优化,其实 kvm 虚拟化只是给我们一个基本功能,很多功能如果要满足客户需求需要对 qemu 和 kvm 源码进行定制开发。
答:spice 的 usb 设备识别指的是将终端机上连接的设备识别为虚机上设备的功能,这是有 spice 的一个子功能 usb redirect 实现,至于宿主机外设,这是对 qemu 配置的问题。
![post-qrcode](https://www.xgss.net/wp-content/uploads/2023/07/二维码-微信公众号256x256.jpg)