前言
如果是刚开始接触虚拟机技术的话, 对上述的概念肯定会有所混淆, 傻傻的分不清. 尤其在看虚拟化技术文档时导致理解能力下降, 所以在开始学习虚拟化技术之前对这些概念有一个整体的认识和清晰的理解, 就显得很有必要了.
KVMKVM(Kernel-basedVirtual Machine,基于内核的虚拟机),狭义 KVM 指的是一个嵌入到 Linux kernel 中的虚拟化功能模块,该模块在利用 Linux kernel 所提供的部分操作系统能力,如:任务调度、内存管理以及硬件设备交互的基础上,再为其加入了虚拟化能力,使得 Linux kernel 具有了成为 Hypervisor(虚拟化管理软件)的条件。
简而言之,KVM 为 Linux 提供了硬件辅助虚拟化的能力,这依赖于 CPU 的硬件虚拟机支撑。
- KVM 内核模块本身只能提供 CPU 和内存的虚拟化。
- KVM 需要在具备 Intel VT 或 AMD-V 功能的 x86 平台上运行,所以 KVM 也被称之为硬件辅助的虚拟化实现。
- KVM 包含一个提供给 CPU 的底层虚拟化可加载核心模块 kvm.ko(kvm-intel.ko、kvm-AMD.ko)。
但一般所说的 KVM 是广义 KVM, 即:一套 Linux 虚拟化解决方案。由于 KVM 内核模块本身只能提供 CPU 和内存的虚拟化,所以 KVM 需要一些额外的虚拟化技术组件来为虚拟机提供诸如:网卡、IO 总线、显卡等硬件的虚拟化实现。最终变成了我们所使用到的 Linux 虚拟化解决方案.
QEMUQEMU(Quick Emulator) 是一个广泛使用的开源计算机 仿真器和虚拟机. QEMU 作为一个独立 Hypervisor(不同于 KVM 需要嵌入到 kernel), 能在应用程序的层面上运行虚拟机. 同时也支持兼容 Xen/KVM 模式下的虚拟化, 并且当 QEMU 运行的虚拟机架构与物理机架构相同时, 建议使用 KVM 模式下的 QEMU, 此时 QEMU 可以利用 kqemu 加速器, 为物理机和虚拟机提供更好的性能.
-
当 QEMU 作为仿真器时, QEMU 通过动态转化技术(模拟)为 GuestOS 模拟出 CPU 和其他硬件资源, 让 GuestOS 认为自身直接与硬件交互. QEMU 会将这些交互指令转译给真正的物理硬件之后, 再由物理硬件执行相应的操作. 由于 GuestOS 的指令都需要经过 QEMU 的模拟, 因而相比于虚拟机来说性能较差.
-
当 QEMU 作为一个虚拟机时, QEMU 能够通过直接使用物理机的系统资源, 使虚拟机能够获得接近于物理机的性能表现.
KVM 作为 Linux 的内核模块, 需要被加载后, 才能进一步通过其他工具的辅助以实现虚拟机的创建. 但需要注意的是, KVM 作为运行于 CPU 内核态 的内核模块, 用户是无法直接对其进行操作的. 还必须提供一个运行于 CPU 用户态 的对接程序来提供给用户使用. 而这个对接程序, KVM 的开发者选择了已经成型的开源虚拟化软件 QEMU.
KVM 开发者在对 QEMU 稍加改造之后, QEMU 可以通过 KVM 对外暴露的 /dev/kvm
接口来进行调用, 官方提供的 KVM 下载有 QEMU 和 KVM 两大部分, 包含了 KVM 模块、QEMU 工具以及二者的合集 qemu-kvm 三个文件.
在 Linux 全虚拟化解决方案 中, KVM 负责提供 CPU 虚拟化和内存虚拟化, 但是 KVM 对于一些计算机硬件设备还是无法进行完美的虚拟(如: 网卡/磁盘/ IO 设备…). 于是就引入了 QEMU, QEMU 负责提供硬件设备的虚拟化, 以此弥补来 KVM 的缺陷. 同时, 为了提高 QEMU 虚拟出来的虚拟硬件设备性能, 于是产生了 pass through 半虚拟化设备virtio_blk/virtio_net. KVM + QEMU 才能实现真正意义上虚拟化. 而 qemu-kvm 就是将两者整合到了一起的媒介.
qemu-kvm 通过 ioctl 调用 KVM 的 /dev/kvm
接口, 将 KVM 内核模块相关的 CPU 指令传递到内核模块中执行.
在 RHEL6/CentOS6 系统中, qemu-kvm 存放在 /usr/libexec 目录下, 由于 PATH 环境变量默认不包含此目录, 所以用户无法直接使用 qemu-kvm. 这样做是为了防止 QEMU 替代了 KVM 作为物理机 Hypervisor 的角色. 如果希望使用 QEMU 虚拟机, 可以通过将 /usr/libexec/qemu-kvm
链接为 /usr/bin/qemu
来实现.
Libvirt 是目前使用最为广泛的异构虚拟化管理工具及 API, 其具有一个 Libvirtd Daemon, 可供本地或远程的 virsh 调用.
libvirt 由 应用程序编程接口库、libvirtd 守护进程、virsh CLI 组成. 其中 libvirtd 守护进程负责调度管理虚拟机, 而且这个守护进程可以分为 root 权限的 libvirtd和普通用户权限的 libvirtd 两种. 前者权限更大, 可以虚拟出物理主机的各种设备.
开启 root 权限 libvirtd: sudo libvirtd --daemon
- Domain:虚拟机的一个运行实例
- Hypervisor:指的就是虚拟化管理程序
Libvirt 本质上是一些被提供的库函数(C语言), 用于管理物理机的虚拟机. 它引用了面向驱动的架构设计, 对所有的虚拟化技术都提供了相应的驱动和统一的接口, 所以 Libvirt 支持异构的虚拟化技术. 同时 Libvirt 提供了多种语言的编程接口, 可以通过程序调用这些接口来实现对虚拟机的操作. 由此可见, Libvirt 具有非常强的可扩展性, OpenStack 就与该库联系得相当密切.
在 KVM 中, 可以使用 virsh CLI 来调用 libvirtd, libvirtd 再通过调用 qemu-kvm 来操作虚拟机.
Libvirt的控制方式:
- 本地控制管理: Management Application 和 Domain 在同一个 Node 上.
(左图是没有应用 Libvirt 的虚拟化架构)
- 远程控制管理: Management Application 和 Domain 不再同一个 Node 上. 该模式使用了运行于远程节点上的 libvirtd 守护进程, 当在其他节点上安装 libvirt 时 Management Application 会自动启动, 并且会自动确定本地虚拟机的监控程序和为虚拟机安装驱动程序, Management Application 通过一种通用协议从本地 libvirt 连接到远程 libvirtd。
#Libvirt 在 OpenStack 中的应用
OpenStack 原生使用 KVM 虚拟化技术, 以 KVM 作为最底层的 Hypervisor, KVM 用于虚拟化 CPU 和内存, 但 KVM 缺少对 网卡/磁盘/显卡 等周边 I/O 设备的虚拟化能力, 所以需要 qemu-kvm 的支持, 它构建于 KVM 内核模块之上为 KVM 虚拟机提供完整的硬件设备虚拟化能力.
OpenStack 不会直接控制 qemu-kvm, 而是使用 libvirt 作为与 qemu-kvm 之间的中间件. libvirt 具有跨虚拟化平台能力, 可以控制 VMware/Virtualbox/Xen 等多种虚拟化实现. 所以为了让 OpenStack 具有虚拟化平台异构能录, OpenStack 没有直接调用 qemu-kvm, 而是引入了异构层 libvirt. 除此之外, libvirt 还提供了诸如 pool/vo l管理等高级的功能.