1. 虚拟化的定义及分类

这一部分是对当期存在的虚拟机技术进行简单的总结与讲解,很多是一句而过的。其实每一个技术都可以重新写出一篇内容丰富的博客,但是每个技术不是本篇文章的重点,所以不对每一个技术进行详细论述。欢迎对每个技术进行评论与纠错。

1.1 虚拟化定义:

虚拟化主要指的是特殊的技术,通过隐藏特定计算平台的实际物理特性,为用户提供抽象的、统一的、模拟的计算环境(称为虚拟机)(IBM 定义)。虚拟化为有效利用大型机的资源提供了技术支持。虚拟机技术也是多种多样,而可以虚拟的层次或者可虚拟的方面也是遍布从硬件到应用层整个计算机系统。如图片所示:

img

1.2 虚拟机分类:

虚拟机的分类也是多种多样。可以通过是否在裸机上部署来分为面向主机的的虚拟机和面向裸机的虚拟机。面向主机的虚拟机是指的在一台已经安装操作系统的主机上安装虚拟机管理 (VMM) 程序,而面向裸机的是指在裸机上直接安装虚拟机管理程序,所有的虚拟机调用都是直接由虚拟机管理程序来负责,没有了操作系统这一步,所以这种方式在效率上要高于面向主机的。不过,比较流行的技术比如 vmware,Xen 都是面向主机的。

然后根据上面的图去分类的话,可以分为对 硬件的虚拟 和对 操作系统或者对软件的虚拟

硬件虚拟化 这个层面,又有三种不同的技术:

  1. Full Virtualization(全虚拟化),几乎是完整地模拟一套真实的硬件设备。大部分操作系统无须进行任何修改即可直接运行在全虚拟化环境中。像 KVM 等技术是全虚拟化。
  2. Partial Virtualization(部分虚拟化),仅仅提供了对关键性计算组件或者指令集的模拟。操作系统可能需要做某些修改才能够运行在部分虚拟化环境中。
  3. Paravirtualization(半虚拟化),不对硬件设备进行模拟,虚拟机拥有独立的运行环境,通过虚拟机管理程序共享底层的硬件资源。大部分操作系统需要进行修改才能够运行在半虚拟化环境中。它的性能要稍微高于全虚拟化。像 Xen。因为需要改动托管系统的内核,所以 Xen 是不支持 win 虚拟机的。

另外还有像硬件辅助虚拟化,就是宿主机的硬件架构在一定程度上提供对虚拟化的支持。像 Intel-VT 与 AMD-V 都提供了这等架构支持,请参考给出的参考资料。

软件层面的虚拟化,往往是指在同一个操作系统实例的基础上提供多个隔离的虚拟运行环境,也常常被称为容器技术。LXC(Linux Container)则是采用了这种技术,它主要是采用了 Linux 本身提供的技术,在一定程度上模拟虚拟化。软件虚拟化也可以理解成进程级虚拟机,其他虚拟化成为系统级虚拟机。在进程级虚拟机中负责虚拟化的软件成为运行时软件,而系统级虚拟机中负责虚拟化的软件成为 VMM(Virtual Machine Monitor)

对于硬件与软件虚拟化两种技术,都是存在优点和缺点。对于硬件虚拟化,我们讨论全虚拟化和部分虚拟化。因为现在大部分的虚拟化技术 Xen、KVM 都支持这两种。硬件虚拟化基本上就是在一台宿主机上虚拟了整个系统,各台虚拟机之间相互不可见。这会很明显导致很多重复的线程和重复的内存页出现,性能上肯定会有影响。所以采用这种技术,一台宿主机上虚拟机的个数肯定会有一定限制。

对于软件虚拟化,我们讨论 LXC,因为只有这一种我用过。LXC 是通过 cgroup 对线程进行隔离,对资源进行限制;通过 Namespace 对调用系统提供的系统调用来进行资源隔离。LXC 介绍。通过此也可以看出,它所有虚拟化出来的虚拟机都是运行在宿主机本身上的,它的线程和资源对宿主机都是可见的。这就不存在很多重复的线程和内存也的问题,所以一台宿主机上可以通过此技术虚拟出更多的虚拟机。

最近非常流行的 Docker 也是软件虚拟化的一种,它的原理也是使用了 Linux 提供的 namespace 对资源进行隔离,不过它提供了比 LXC 更强大的功能实现。

2. 虚拟化技术

2.1 kvm

对于 KVM 来说,其是一款支持虚拟机技术,而且是 Linux 内核中的一个功能模块。它在 Linux2.6.20 之后的任何 Linux 分支中都被支持。它还有一个条件,对硬件要求的条件,必须达到一定标准的硬件架构。对于 Intel-VT 与 AMD-V 都是支持的。对于是否支持也可以通过命令行查看:egrep ‘(vmx|svm)’ –color=always /proc/cpuinfo。如果有任何内容则说明当期硬件架构是支持 KVM 的,否则就不支持。另外,就算支持,但是在 bios 中是默认设置不打开该功能的,所以你还要去 bios 设置其为 enable。当设置成功之后,还需要关机一次,注意是关机而不是重启。否则该设置的更改就不起效。

KVM 是 linux 内核的模块,它需要 CPU 的支持,采用硬件辅助虚拟化技术 Intel-VT,AMD-V,内存的相关如 Intel 的 EPT 和 AMD 的 RVI 技术,Guest OS 的 CPU 指令不用再经过 Qemu 转译,直接运行,大大提高了速度,KVM 通过 /dev/kvm 暴露接口,用户态程序可以通过 ioctl 函数来访问这个接口。

KVM 内核模块本身只能提供 CPU 和内存的虚拟化,所以它必须结合 QEMU 才能构成一个完成的虚拟化技术,这就是下面要说的 qemu-kvm。

2.2 qemu

QEMU 是什么。其实它也是一款虚拟化技术,就算不使用 KVM,单传的 QEMU 也可以完全实现一个虚拟机。那为何还会有 QEMU-KVM 这个名词那。是因为虽然 KVM 的技术已经相当成熟而且可以对很多东西进行隔离,但是在某些方面还是无法虚拟出真实的机器。比如对网卡的虚拟,那这个时候就需要另外的技术来做补充,而 QEMU-KVM 则是这样一种技术。它补充了 KVM 技术的不足,而且在性能上对 KVM 进行了优化。

QEMU 是一款开源的模拟器及虚拟机监管器(Virtual Machine Monitor, VMM),它是构建基于 KVM 上面的,它提供了完整的网络和 I/O 支持。

QEMU 主要提供两种功能给用户使用。 一是作为用户态模拟器,利用动态代码翻译机制来执行不同于主机架构的代码。 二是作为虚拟机监管器,模拟全系统,利用其他 VMM(Xen, KVM, etc)来使用硬件提供的虚拟化支持,创建接近于主机性能的虚拟机。 用户可以通过不同 Linux 发行版所带有的软件包管理器来安装 QEMU。

它向 Guest OS 模拟 CPU 和其他硬件,Guest OS 认为自己和硬件直接打交道,其实是同 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。

由于所有的指令都要从 Qemu 里面过一手,因而性能较差

img

2.3 qemu-kvm

Qemu 将 KVM 整合进来,通过 ioctl 调用 /dev/kvm 接口,将有关 CPU 指令的部分交由内核模块来做。kvm 负责 cpu 虚拟化 + 内存虚拟化,实现了 cpu 和内存的虚拟化,但 kvm 不能模拟其他设备。qemu 模拟 IO 设备(网卡,磁盘等),kvm 加上 qemu 之后就能实现真正意义上服务器虚拟化。因为用到了上面两个东西,所以称之为 qemu-kvm。

Qemu 模拟其他的硬件,如 Network, Disk,同样会影响这些设备的性能,于是又产生了 pass through 半虚拟化设备 virtio_blk, virtio_net,提高设备性能。

img

2.4 libvirt

libvirt 是一系列提供出来的库函数,用以其他技术调用,来管理机器上的虚拟机。包括各种虚拟机技术,KVM、Xen 与 lxc 等,都可以调用 libvirt 提供的 api 对虚拟机进行管理。有这么多的虚拟机技术,它为何能提供这么多的管理功能那。是因为它的设计理念,它是面向驱动的架构设计。对任何一种虚拟机技术都开发设计相对于该技术的驱动。这样不同虚拟机技术就可以使用不同驱动,而且相互直接不会影响,方便扩展。而且 libvirt 提供了多种语言的编程接口,可以直接通过编程,调用 libvirt 提供的对外接口实现对虚拟机的操作。如今流行的云计算中的 IaaS 是与该库联系相当密切的。

它是目前使用最为广泛的对 KVM 虚拟机进行管理的工具和 API。Libvirtd 是一个 daemon 进程,可以被本地的 virsh 调用,也可以被远程的 virsh 调用,Libvirtd 调用 qemu-kvm 操作虚拟机。

img

通过下图可以看出它的架构设计思想。

从该图可以看出,在 libvirt api 之上会有很多个 driver,对于每一种虚拟机技术都会有一种 driver,用来充当该虚拟机技术与 libvirt 之间的包装接口。如此设计就可以避免 libvirt 需要设计各种针对不同虚拟机技术的接口,它主要关注底层的实现,提供对外接口调用,而不同的虚拟机技术通过调用 libvirt 提供的接口来完成自己所需要的功能。

img

Openstack 通过 libvirt 去间接控制 qemu-kvm。libvirt 提供了跨 VM 平台的功能,它可以控制除了 QEMU 之外 的模拟器,包括 vmware, virtualbox, xen 等等。

所以为了 openstack 的跨 VM 性,所以 openstack 只会用 libvirt 而不直接用 qemu-kvm。libvirt 还提供了一些高级的功能,例如 pool/vol 管理。

3. 虚拟机网络

一般虚拟机虚拟网络的设置主要包括三种方式。主要如下:

3.1 NAT 模式

也有人称此种模式为 HOST(宿主)模式。在这种模式下虚拟机可以理解成没有自己的独立网卡。所有访问虚拟机的请求其实是直接发送给宿主机,然后通过访问宿主机转发到虚拟机上的。相应的虚拟机访问其他网络,也是先转发到宿主机然后在转发出去。对于宿主机之外的网络,是不知道该虚拟机存在的。

3.2 Bridge 模式

桥接模式是使用比较多的模式,它是虚拟机拥有自己的独立网卡和 IP,然后通过借用宿主机的网卡对外连接网络。它把宿主机的网卡当作了一种桥,通过这个桥连接外网的世界。在这种模式下,可以简单的理解成虚拟机和宿主机是两个不同的机器,有独立 IP 可以相互访问。对于虚拟机的 IP 获取,一般可以直接指定也可以通过 DHCP 获取得到。

3.3 Internal 模式

这个是把虚拟机之间的网络和主机的网络隔离开来。虚拟机是一片网络,主机也是一片网络,彼此之间不能相互访问。

4. 关系

KVM 虚拟机是基于 Linux 内核虚拟化,自 Linux2.6.20 之后就集成在 Linux 的各个主要发行版本中。它使用 Linux 自身的调度器进行管理,所以相对于 Xen,其核心源码很少。KVM 的虚拟化需要硬件的支持(如 intel VT 技术或者 AMD V 技术),是基于硬件的完全虚拟化。而 Xen 早期则是基于软件模拟的 para-virtualization,新版本是基于硬件支持的完全虚拟化。

QEMU 是一种模拟处理器,现在运用最多的就是将 KVM 和 QEMU 结合起来。

准确来说,KVM 是 Linux Kernel 的一个模块,可以用命令 modprobe 去加载 KVM 模块。加载了该模块后,才能进一步通过工具创建虚拟机。但是仅有 KVM 模块是不够的。因为用户无法直接控制内核去做事情,还必须有一个运行在用户空间的工具才行。这个用户空间的工具,KVM 开发者选择了已经成型的开源虚拟化软件 QEMU。说起来 QEMU 也是一个虚拟化软件。它的特点是可虚拟不同的 CPU。比如说在 x86 的 CPU 上可虚拟一个 power 的 CPU,并可利用它编译出可运行在 power 上的 CPU,并可利用它编译出可运行在 power 上的程序。KVM 使用了 QEMU 的一部分,并稍加改造,就成了可控制 KVM 的用户空间工具了。所以你会看到,官方提供的 KVM 下载有两大部分 (QEMU 和 KVM) 三个文件(KVM 模块、QEMU 工具以及二者的合集)。也就是说,你可以只升级 KVM 模块,也可以只升级 QEMU 工具。这就是 KVM 和 QEMU 的关系。

如下图:

img

Linux Kernel-based Virtual Machine (KVM) 是一款 Linux 开放源码虚拟化软件,基于硬件虚拟化扩展(Intel VT- X 和 AMD-V)和 QEMU 的修改版。KVM 的实现模块又两个,分别是: kvm.ko 是提供核心虚拟化的基础架构;特定于处理器的模块 kvm-intel.ko 和 kvm-amd.ko 。其设计目标是在需要引导多个未改动的 P 操作系统时支持完整的硬件模拟。

一个普通的 Linux 进程有两种运行模式:内核和用户。而 KVM 增加了第三种模式:客户模式(有自己的内核和用户模式)。在 KVM 模型中,每一个虚拟机都是由 Linux 调度程序管理的标准进程。

KVM 由两个部分组成:一个是管理虚拟硬件的设备驱动,该驱动使用字符设备 /dev/kvm 作为管理接口;另一个是模拟 PC 硬件的用户空间组件,这是一个稍作修改的 QEMU 进程。

5. 参考: