<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } H1 { margin-bottom: 0.21cm } H1.western { font-family: "DejaVu Sans", sans-serif; font-size: 16pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt } H1.ctl { font-family: "Lohit Hindi"; font-size: 16pt } H2 { margin-bottom: 0.21cm } H2.western { font-family: "DejaVu Sans", sans-serif; font-size: 14pt; font-style: italic } H2.cjk { font-size: 14pt; font-style: italic } H2.ctl { font-family: "Lohit Hindi"; font-size: 14pt; font-style: italic } A:link { so-language: zxx } --> <!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } H1 { margin-bottom: 0.21cm } H1.western { font-family: "DejaVu Sans", sans-serif; font-size: 16pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt } H1.ctl { font-family: "Lohit Hindi"; font-size: 16pt } H2 { margin-bottom: 0.21cm } H2.western { font-family: "DejaVu Sans", sans-serif; font-size: 14pt; font-style: italic } H2.cjk { font-size: 14pt; font-style: italic } H2.ctl { font-family: "Lohit Hindi"; font-size: 14pt; font-style: italic } A:link { so-language: zxx } -->
进程是准虚拟化的虚拟机—容器虚拟化的原理
by 沈东良(良少)http://blog.csdn.net/shendl
首先声明,我对容器虚拟化并不精通,虽然我们公司也从事Linux Container这个容器虚拟化的研究,但是那是另外一个team的工作。
我这里从原理性的角度分析一下容器虚拟化的原理,可能和实际的容器虚拟化技术并不相同,还请见谅和指正。我只谈原理不谈风月。
进程是准虚拟化的虚拟机
虚拟化技术最早是IBM在上世纪60年代的System/360操作系统中开发的。一般操作系统是用进程来划分资源,而System/360把虚拟计算机当作资源划分的单位。
System/360和后来的vmware,kvm等都是完全虚拟化。
让我们看一下虚拟化的定义,维基百科中这样定义:
虛擬化(Virtualization)是一個表現邏輯群組或電腦資源的子集的進程,用戶可以用比原本的組態更好的方式來存取這些進程。這些資源的新虛擬部份是不受現有資源的架設方式,地域或物理組態所限制。一般所指的虛擬化資源包括計算能力和資料儲存。
我的理解是,虚拟化就是虚拟硬件资源,包括CPU,内存,硬盘,外设等等。
完全虚拟化完全虚拟了计算机的所有硬件。运行于其上的操作系统意识不到它运行在虚拟的计算机上。这样的效果当然是我们所理解的虚拟化。
那么,如果仅仅虚拟化一部分资源呢?算虚拟化吗?
如果虚拟机上的操作系统能够意识到自己运行在虚拟机中呢?算虚拟化吗?
如果虚拟机中不能运行操作系统,但依然虚拟化了若干硬件资源呢?算虚拟化吗?
我的答案是上述种种情况都是虚化化!
Xen的虚拟机中的操作系统意识到自己是运行在虚拟机上,而不是真正的硬件上,它需要通过hypercall调用物理计算机上运行的操作系统提供的API才能完成运行。
Xen是虚拟机管理器吗?是的,它是准虚拟化类型的虚拟机。
KVM使用的virtio,是在虚拟机操作系统中安全了一个驱动。这个驱动知道自己运行在虚拟机中而不是物理机中。它通过hypercall调用物理机操作系统提供的服务,实现了对外设的虚拟化。Virtio属于外设的类虚拟化。
虚拟内存技术,把一小块物理内存虚拟为多块独立的非常非常大的虚拟内存。内存管理模块算不算是hypervisor呢?当然算。
多进程操作系统,分时调度多个进程,每一个进程都认为自己独占CPU。进程调度算不算是hypervisor呢?当然算。
现代操作系统同时支持多进程和虚拟内存技术,进程可以使用虚拟CPU,虚拟内存,共享外部设备,使用的都是虚拟的资源。所以多进程就更是虚拟化技术了。进程就是虚拟机。
进程和xen的虚拟机操作系统一样,它知道自己运行在虚拟资源之上,需要使用hypercall才能完成自己的正常运行。
进程的hypercall就是系统调用!
xen虚拟机通过hypercall要求Host为它提供特权和外部设备。进程也是通过系统调用,要求内核提供特权服务和外部设备。
因此,我们说内核是准虚拟化的hypervisor,进程就是准虚拟化的虚拟机。
容器虚拟化的原理
读者可能对我上面的结论并不信服。可能会说,xen的虚拟机可以跑操作系统,虽然是修改过的操作系统,但也是操作系统。进程这个“虚拟机”可以吗?
【其实也可以啦。qemu/bochs不就是在一个进程中模拟一台计算机。计算机甚至可以是异构的。而且它们不用内核提供任何特别的服务。 qemu/bochs是硬件模拟器。
现代语言,如java,.net,Python,javascript都使用进程虚拟机,虚拟了CPU。它们的源码会被编译成一种虚拟的CPU使用的虚拟的汇编语言。这样,只要在各个平台上实现虚拟CPU的进程虚拟机就可以实现跨平台了。而且,进程虚拟机执行伪汇编代码要比直接解释源代码高效的多!
不过,上述这些技术都是在进程中又玩了一些花样,因此不在本文的谈论范围之内,我就不说了。
】
进程是不可以直接运行操作系统,但虚拟化的定义应该是虚拟硬件资源,没规定一定要运行操作系统啊!
计算机执行的大部分业务任务都是用户空间的进程实现的。内核仅仅是为进程提供服务的。进程虚拟机直接使用内核提供的服务,当然比在虚拟机内部再运行一个操作系统高效的多。不管你XEN的准虚拟化操作系统内核多么牛逼,我根本没这个对于的内核,总比你高效吧!
使用相同内核的虚拟机,听起来是不是和容器虚拟化(又叫:操作系统级虚化化)一样?
容器虚拟化,我的映像是Sun的Solaris操作系统首先提出和实现的。一台计算机上,可以提供上百个独立的进程组。这些进程组的资源是隔绝的。进程组叫做容器。
容器中的进程无法看到容器外的资源。每个容器也不能使用超出限额的资源。
容器虚拟化技术在虚拟主机领域应用非常广泛。使用容器虚拟化,可以严格控制硬盘空间,网络流量等。它比传统的虚拟主机更加灵活。用户想装什么软件就装什么软件。而且对资源的控制更强。很难出现占用他人资源的情况。
知道谁对云计算/虚拟化最起劲吗?就是虚拟主机厂商。rackspace公司就是国际领先的虚拟主机厂商。有了云计算和虚拟化,它运营虚拟主机的成本就更省了!
进程虚拟机和容器虚拟化
其实,容器虚拟化就是基于进程虚拟机实现的。上面已经说了,进程是共用内核的虚拟机,共用了硬件资源。
实现容器虚拟化,关键的就是容器的实现。容器隔离了物理资源。有些资源别人用不了,有些资源用的比我少。
现在我就说说我猜测的实现原理。我就以我最熟悉的Linux为例来说明。
Linux的每一个进程都有一个namespace对象。它保存的就是从root开始的文件系统。子进程会继承父进程的这个对象。因此,一般情况下,整个linux操作系统只有一个namespace对象。看到的都是相同的文件系统。
但是,进程也可以创建自己独立的namespace对象。它创建的子进程就会继承这个namespace对象。
chroot命令可以切换到另一个linux根文件系统执行,容器虚拟化使用的就是这个原理。
容器虚拟化也使用了这个原理。这样,每一个容器中的进程看到的文件系统就是不同的,看到的设备文件也是不同的。因此可以使用不同的硬件资源和文件。
linux的qutoa模块可以实现对文件夹等的大小限制。这样就不能使用超过限制的硬盘资源。
Linux支持tap/tun等机制实现的虚拟网卡。每一个容器可以使用自己独有的虚拟网卡。内核可以对虚拟网卡进行带宽和流浪的限制和统计。
Linux的进程组也可以设置时间片,规定进程只能运行在哪一个或者哪几个CPU上。这样就可以限制容器虚拟机对CPU的使用率。
Linux内核还可以对不同进程组/用户的内存的使用进行限制。
总之,Linux内核可以根据进程组或者用户对资源进行种种限制。而namespace可以设置对文件系统和设备的使用限制。目前LXC等容器虚拟化软件都向Linux内核增加了模块,用于实现更加复杂的容器虚拟化。
据说,LXC的overload只有1%-3%。这应该比任何完全虚拟化技术都要少很多。
当然,容器虚拟化也不是万能的。容器虚拟化不提供操作系统虚拟化。一个容器只是一些进程的集合而已。如果用户需要和Host的内核不同的以内核安装一些驱动,甚至需要不同的操作系统,如在LXC上要跑Windows,那么就需要完全虚拟化技术了。如果使用虚拟主机提供商的产品,那就意味着需要花比容器虚拟化更多的钱。因为虚拟主机提供商的成本更高了。
不过,即使是需要完全虚拟化的场合,我依然不推荐XEN。如果没有支持硬件虚拟化的CPU,那么它不能跑Windows等软件。因为XEN无法修改Windows内核源码。
XEN需要定制版本的Host的Linux内核和定制版本的VM的Linux内核。这些版本的数量是很少的,而且定制版本的Linux内核,会使很多驱动无法运行。如,我的电脑如果运行XEN内核,那么显卡驱动就无法运行了。对内核限制太多,那还不如使用容器虚拟化呢!至少不用改内核,不会导致驱动无法运行。