最近,我们庆祝了 Linux 项目诞生 25 周年。KVM,亦称为 基于内核的虚拟机,是 Linux 内核的一部分,在十月份庆祝了它的十周年生日。KVM 于 2006 年 10 月 19 日由其创建者 Avi Kivity 首次发布在 Linux 内核的邮件列表里。
KVM 补丁集的第一个版本一经发布就支持了英特尔 CPU 刚刚引入的 VMX 指令。对 AMD 的 SVM 指令的支持紧随其后。KVM 补丁集在 2006 年 12 月合并进上游内核,并在 2007 年 2 月作为 2.6.20 内核的一部分发布。
背景
如果没有新的虚拟化扩展,x86 架构上运行多个客户操作系统非常困难:有的指令只能从最高优先级 ring 0 执行,这样的访问不可能在不影响系统上的其他操作系统的操作的前提下给到每个操作系统。此外,一些指令在低优先级执行时不会引发陷阱——尽管他们要求更高的优先级以正确发挥作用——所以在 ring 0 上运行“hypervisor(运行其他操作系统的操作系统)”,而在低优先级的环上运行其它操作系统也不是解决方案。
VMX 和 SVM 指令给 x86 架构引入了一个新的优先级 ring -1。这是虚拟机监视程序(VMM),或 hypervisor 运行的优先级。VMM 仲裁访问硬件的各种操作系统,这样它们可以在常规 x86 环境中持续正常运行。
在一个硬件上运行多个操作系统系统有几个原因:使用可以配置虚拟机(VM)的工具让操作系统的部署和管理变得更容易。通过聚集多个操作系统和相应的应用程序和服务将其运行在更新一些、更强大的硬件上还会减少电力和冷却成本。此外,现在通过 hypervisor 模拟老硬件使得传统的操作系统和应用程序可以运行在新硬件上而不需要任何改动以适应新的硬件成为可能。
KVM 本身的功能分为多个部分。体现 KVM 的架构无关的功能的通用主机内核 KVM 模块;宿主系统上的特定架构内核模块;模拟用以运行客户操作系统的虚拟机的硬件的用户空间部分;以及加强客户机上虚拟化系统性能的可选客户机插件。
在 KVM 出现时,Xen 是开源 hypervisor 的事实标准。由于 Xen 是在 x86 虚拟化扩展可用之前出现的,它不得不使用另外的设计。首先,为了启动虚拟机它需要运行一个修改过的客户机内核。第二,Xen 接管宿主机内核的角色,把 Linux 降级,让它作为 Xen 的特殊 “Dom0” 虚拟机的一部分只管理 I/O 设备。这意味着该系统不能真正被称为 Linux 系统,甚至客户操作系统被修改的 Linux 内核用的是(当时)非上游代码。
Kivity 在以色列新兴公司 Qumranet 修复该公司当时所做的 Xen 相关的工作的问题时开始开发 KVM。原 Qumranet 产品理念是在两个不同的 VM 间复制机器状态实现容错。很快 Qumranet 的工程师就明显察觉 Xen 太有限,拙劣的模型无法满足他们的需求。 AMD 和英特尔 CPU 即将引入虚拟化扩展,所以 Kivity 启动了一个编外计划 KVM,基于新硬件虚拟化规范并将被用作 hypervisor 的容错解决方案。
开发模型
从一开始,Kivity 就想要写可以提交到上游的代码。KVM 模型的目标之一是尽可能重用已经存在的功能:让 Linux 多干活, KVM 仅作为用来控制硬件所提供的新虚拟化指令的驱动。这让 KVM 能获得 Linux 开发者添加到系统其它部分的任何新特性,比如 CPU 调度器、内存管理、电源管理等等的改进。
该模型对于 Linux 生态系统的其它部分也工作地很好。以只有虚拟化开始这样的特性开始变得更加用途更多,并且也广泛适用于通用用途,如透明巨页。社区并没有对于 OS 和 VMM 分成两个;每个部件都作为一个项目整体的一部分。
而且,VM的管理将会更容易,每个 VM 都可以作为常规进程监控,——像 top 和 ps 这样的工具可以直接拿来用。近来,perf可以从宿主机上用来监控客户机活动和识别瓶颈,如果有的话。未来的的芯片集改进将能从宿主机上检测客户机的进程性能。
KVM 的另一边是用户空间,即构建呈现给客户操作系统的机器的地方。kvm-userspace 是 QEMU 项目的一个分支。QEMU 是一个机器模拟器,可以运行它所支持的各种架构的未修改的操作系统镜像,并且在它运行其上的宿主机架构模拟这些架构的指令。这当然非常缓慢,但 QEMU 项目的优势是它已经仿真了 x86 架构的很多设备——比如芯片集,网卡,显示适配器,等等。
kvm-userspace 所做的是短路仿真代码,只允许 x86-on-x86 ,并使用 KVM API 在宿主机 CPU 上实际运行客户机操作系统。客户机操作系统执行特权操作时,CPU 将退出到 VMM 代码。由 KVM 接管;如果它自己可以服务请求,它就服务请求,并将控制交还客户机。这是“轻量级退出”。对于 KVM 不能处理的请求,像设备模拟,它会交给 QEMU。这意味着从主机 Linux 内核退出到用户空间,因此这称为“重量级退出”。
这个模型的缺点之一是 QEMU 分支的维护。早期的开发人员关注重点是内核模块的稳定性,和让越来越多的客户机顺利工作。这意味着开发人员在设备模拟代码花费的时间较少,因此,重复这些 hack 工作使它们适合于上游代码处于较低的优先级。
Xen 也使用 QEMU 的一个分支为它的 HVM 模式进行设备模拟(Xen 使用新硬件虚拟化指令的模式)。此外,QEMU 对于 x86-on-x86 有自己的非上游 Linux 内核加速器模块(KQEMU),消除了模拟层,使 x86 客户机在 x86 硬件上运行得更快。整合所有这些需要一个理解所有项目的各种需求的维护者。Anthony Liguori 是 QEMU 项目的一个维护者,他信任 Xen 和 KVM 的社区。随着时间的推移,这些非上游分支逐渐被淘汰,现在 KVM 和 Xen 都使用上游 QEMU 仿真设备模型。
“做一件事,做到正确”的咒语,和“一切皆文件”的理念,发挥到了极致。KVM API 允许在 Linux 系统上创建 VM——或者,沙盒,然后可在其内部运行操作系统,或者任何代码,而不会干扰正在运行的系统。这也意味着可以有其它的用户空间实施方案,不像 QEMU 那么重量级或者功能丰富。可以快速启动小型应用程序或者特定 OS 的 KVM 虚拟机的工具开始出现——kvmtool 是最流行的一个。
开发者兴趣
自 KVM 项目最初发布时,许多黑客都对探索 KVM 感兴趣。黑客在 KVM 上 Hacking 非常方便:安装一个新的 VMM 并不需要重启系统。重新编译 KVM 模块、删除旧模块和加载新模块,就是这样的简单。这极大地帮助了早期的稳定和改善阶段。调试过程更快了,与编译、安装新的 VMM,更新引导加载程序,并重新启动系统相比,开发人员更喜欢这种工作方式。另一个优点,对于我的工作和开发的笔记本电脑而言,或许重要性没开发系统高但尽管如此却是必要的,就是运行虚拟机不需要 root 权限。
KVM 模块和 QEMU 的分离令另一个方便的调试技巧成为可能,如果在 KVM 模式下不能工作,但可以工作在模拟模式下,错误很可能出在 KVM 模块。如果某客户机在两种模式下都不工作,错误就出在设备模型或者 QEMU。
早期的 KVM 发布模型也有助于消除开发体验的痛点:即使 KVM 项目是上游 Linux 内核的一部分,Kivity 以一个单独的发行队列维护 KVM 代码。新 KVM 定期发布包括 KVM 模块的源代码的发行版,一个小的兼容性层用以在任何支持的 Linux 内核上编译 KVM 模块和 kvm-userspace 块。这确保包含旧版本的 KVM 模块分发版内核仍是可用的,而不用改变内核,只需使用针对该内核的最新 KVM 版本编译模块。
兼容层需要一些精力来维护。它需要通过模拟新的 API,来确保使用新的内核 API 的新 KVM 代码不会带着旧的内核停止工作。增加这样一个 API 兼容功能是一次性成本,而对于新的贡献者进入的困难则显著降低。Hacker 们可以下载最新的 KVM 发布版,针对其所要运行的内核进行编译,然后看看虚拟机能不能启动。如果不工作,开发者可以提供修复 bug 的补丁。
广泛的适用性
芯片厂商开始感兴趣并且移植 KVM 到他们的架构:英特尔添加 IA64 的支持和对 x86 的功能和稳定性进行修复;IBM 添加s390 和 POWER 架构的支持;ARM 和 Linaro 贡献了 ARM 移植;Imagination Technologies 添加 MIPS 支持。不过,这些并不全是立刻就绪的。例如,ARM 的支持来的很晚(“实际上是不及时、不符合预期”,Kivity 在 KVM 论坛主题期间讽刺道,他曾预测在此前一年 ARM 会实现移植)。
开发者的兴趣也可以在 KVM 论坛反映出来,这是一个对 KVM 虚拟化感兴趣的人的年会。2007 年第一个 KVM 论坛只有少数开发人员在一个房间里讨论许多事务的当前状态,和未来往哪里去,会发生什么。由 Rusty Russell 领导的一个小组,接过了白板,开始讨论 KVM 超虚拟化接口将是什么样子。从此 VIRTIO 开始成形。近年来,KVM 论坛成了快速发展的大会,数十演讲者,数百名与会者。
随着时间的流逝,明显 KVM 内核模块变成了大部分的行动的非关注点——所需的指令仿真或多或少都已完成,而且大多数发行版都能在最新的 Linux 内核上加载。之后关注焦点转移到了到用户空间:增加更多的设备模拟,使现有设备表现更好,等等。此时 KVM 发行版更侧重于用户空间部分,兼容层的维护也轻松了。这个时候,尽管存在 kvm-userspace 分支,努力确保新特性进了 QEMU 项目而不是 kvm-userspace 项目。Kivity 也开始用 kvm-userspace 库的小变化供给到 QEMU 项目。
当这一切发生的时候,Qumranet 改变了方向,开始寻求 KVM 作为 hypervisor 实现桌面虚拟化。2008 年 9 月,Red Hat 宣布将收购 Qumranet。自 Red Hat Enterprise Linux 5.0 发行版以来 Red Hat 一直支持 Xen hypervisor 作为官方VMM。从 RHEL 5.4 版本,Red Hat 开始同时支持 Xen 和 KVM 作为 hypervisor。随着 RHEL 6.0 的发布,Red Hat 转向只支持 KVM。KVM 也在其他发行版里持续享受开箱即用的的支持。
现在和未来
现在,有几个项目使用 KVM 作为默认 hypervisor:其中较受欢迎的有 OpenStack 和 oVirt。这些项目关心 KVM 宿主机的大规模部署和多个 VM 的同时部署。这些适用不同的应用场景,因此对 KVM 有不同的要求。由于客户机操作系统规模增大(更多的内存和虚拟 CPU),它们变得更加难以不占用太多的停机时间而实现热迁移,电信级部署需要处理低延迟网络数据包,所以实时 KVM 是一个值得感兴趣的领域,更快的磁盘和网络 I/O 始终是一个值得研究的领域。保持一切安全,减少 hypervisor 影响也是正在努力的方向。恶意的客户机可以突破 VM 沙盒以及如何减轻这种攻击也是一个主要关注领域。
新硬件更新和设备带来了许多优势。但是很多努力也花费在优化当前代码基础、写新的算法、和采用新的方法来提高性能和现有基础设施的稳定性上。
接下来的十年,主要话题很可能不是 hypervisor 的开发。更多兴趣将集中到如何将 Linux 用作 hypervisor,以带来更好的运行非受信代码的沙盒技术,尤其是在手机领域,以及以无所不在的同时又无形的方式运行云基础设施。
校对:wxy
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/54801.html