天天看点

Xen

早些时候,Xen被红帽当做默认虚拟化实现的解决方案。

Xen是由英国剑桥大学所研发的,是开源的虚拟机监视器(VMM)。Xen的主要目的是致力于实现在单个计算机上运行多达128个有完全功能的Guest。但是,早期设计时,在Xen出现的时候,x86平台还不支持硬件辅助虚拟化(HVM),所以那个时候要么只能通过完全虚拟化的方式来实现虚拟化,那个时候比较著名的VMware Workstation就是使用的这种技术。但剑桥大学的Xen项目组他们认为这种技术损失了太多的性能,因此,他们研发了半虚拟化技术,能够使得运行在其上的GuestOS获得接近于物理硬件百分之九十以上的性能表现。不过,他们做出的折中是GuestOS必须修改其源代码,来实现让其适应运行在虚拟化环境上。

Xen

  Xen是Type-I型的虚拟化,Xen其实就是直接运行在硬件之上的,任何一个运行在xen hypervisor之上的主机都是虚拟机。启动主机时,要求如果有硬件的话,首先启动的必须是Xen Hypervisor,Xen采用了一种精巧的设计方式,虽然Xen自己提供了hypervisor,但是它并没有对所有东西都虚拟化,它仅仅虚拟化了计算机五大部件中的CPU和内存,对于IO设备没有虚拟化。

Xen Hypervisor上要直接启动一个虚拟机,这个虚拟机要辅助Xen Hypervisor一块工作,这个虚拟机有两个功用:

1、作为Xen Hypervisor管理其他虚拟机的接口。这第一个虚拟机有用户空间和内核空间,在用户空间中提供一个虚拟机的管控接口,从而通过这个管控接口就可以创建其他虚拟机了,其他虚拟机的启动、关闭也都要通过第一个虚拟机来实现。还要提供一个管理控制台(console),因为Xen Hypervisor并不提供这样的应用程序,所以我们要开发一个能够为Xen Hypervisor管理虚拟机的应用程序。只需要通过调用Linux内核的应用程序来开发就可以了,只要第一个虚拟机运行在Linux上就可以。

2、Xen Hypervisor还要依赖于第一个虚拟机的内核来驱动各种常用IO设备,比如声卡、网卡、显卡等等。Xen Hypervisor直接管理CPU,直接管理内存,但对各种常见IO设备的管理由第一个虚拟机的内核来实现。

Xen

  如果创建了其他虚拟机,其他虚拟机要想使用CPU和内存,都要向Xen Hypervisor直接进行调用,因为CPU和内存的管理权限是由Xen Hypervisor提供的。包括第一个虚拟机要想使用CPU和内存,也是由Hypervisor统一配置的。

  Xen Hypervisor采用了一种精巧的设计方式,它自己为了避免需要开发各种各样的IO硬件设备的驱动程序,所以它在自己启动起来之后,让第一个必须要启动起来的虚拟机来负责管理这个功能。所以如果要使用IO设备,就要向第一个虚拟机发起请求,由第一个虚拟机负责通过软件程序给它模拟出IO设备,而后这些IO设备经由内核驱动以后转换成对这些硬件的调用。如果有多个虚拟机,它会为每一个虚拟机在用户空间模拟出多个IO设备,这个模拟是由QEMU来实现的。所以说,Xen的虚拟化环境并不完全由Xen提供,Xen只是提供了CPU和内存的虚拟化,而所有在虚拟机上提供的IO设备则是由QEMU模拟实现的。

  在xen之上,每一个虚拟机被称为一个“域(Domain)”,这些域是有编号的。第一个被启动起来的叫做“Domain0”,通常被简称为”Dom0“,"Dom0"我们也把它叫做"特权域(Privileged Domain)"。 它拥有管理其他虚拟机,甚至于配置底层IO设备虚拟化的权限。

  其他所有能够被“Dom0”管理的虚拟机,我们把它们统称为“DomU(Unprivieged Domain)“。“DomU”是有编号的,每一个虚拟机实例启动起来以后,它们都有一个唯一的编号,比如“Domain1”、"Domain2"...,除了"Domain0",其他都被称为"DomU"。

  要想让“DomainU”运行为一个虚拟机的话,这个虚拟机得有CPU和内存。

如何给它虚拟化CPU呢?

  要想给它虚拟出一颗CPU,我们通常是在Xen Hypervisor上提供一个进程或线程来当CPU来用,Xen Hypervisor把这个进程或线程调度至CPU某个物理核心上,从而使得它们的代码能够真正运行起来。所以你有n个虚拟机,每个虚拟机都有四颗cpu,底层的物理机器一共才只有4颗CPU,假设有十个虚拟机,那一共就有四十颗CPU。这四十颗CPU在Xen Hypervisor上表现为什么呢?映射到Xen Hypervisor上是一个一个的线程。

那它如何虚拟内存呢?

  任何物理机设备,现在的操作系统,大多数都是对内存分页管理的。其实它内存的虚拟化,也无非就是把底层物理内存当中的某些段空间切割出来以后,形成一个新的虚拟空间供它使用了。只不过进行了二次映射而已,本来在物理内存上很可能是离散的多个段,将会被Xen Hypervisor整合成一个。比如物理内存上的第一段加第二段,和第三段,总体映射为虚拟机整个可用的内存空间。对虚拟机来说,它以为自己的内存是完整且连续的。

每一个虚拟机都还要有一些IO设备,比如网卡,硬盘等,这些IO设备怎么虚拟化?

如果我们要启动n个虚拟机的话,每一个虚拟机都要有这些设备,比如硬盘。底层的真的硬盘可能只有一块,那怎么给它虚拟化?

无非就是这么几种方式:

1、物理硬盘多分几个区,每一个虚拟机给一到两个区。

2、在本地创建磁盘映像文件,把文件当做磁盘设备使用。

  不过我们只是在某一个层级上把它模拟成一个硬件设备。因此,这个时候我们就得依赖运行于“Dom0”当中的”QEMU“来实现模拟了。这个”QEMU“需要为每一个创建的虚拟机用到IO设备时,模拟出一个硬件设备,并映射进真正的实现。比如,多个虚拟机都要用到硬盘的话,可以在”Dom0“挂载好某个硬件设备的某个分区以后,在里边创建多个虚拟的磁盘映像文件,而后为这个磁盘映像文件之上盖上一层软件,这个软件能够模拟出一个控制器芯片,而后把模拟出的这个控制器关联至这个虚拟机上,这个虚拟机看到的就是一个拥有控制器的硬件芯片设备。

这样一来,就会出现一个问题?

Xen

  首先,”DomU“中的GuestOS要驱动这个控制器芯片才能工作。而我们模拟出来的芯片和它底层真正实现的可能并不完全一样。更何况,我们这里只是一个文件,压根就不是硬件设备。

所以我们应该模拟成哪一种芯片呢?所以最好应该是模拟成市面上非常常见的,我们认为GuestOS内核中一定会有它的驱动程序的芯片类型。比如模拟成希捷的硬盘芯片。而后,对应的GuestOS就必须要装载对应的模拟出来的芯片以后,才能驱动这个设备工作。

  这个模拟出来的指令工作起来可能会面临这样的问题。比如说,在用户空间有一个用户进程,这个进程需要写数据了,意味着它要向内核发起系统调用,这个内核系统调用以后,最终层层转换成对应的驱动程序完成对这个硬盘设备的读写操作。这个驱动程序把代码指令转换完了,可以把转换后的结果请求给这个控制器芯片,它认为这个芯片就可以执行物理操作了。但这里不是芯片,而是文件。因此,在转给"Dom0"时,”Dom0“的硬盘芯片有可能和"DomU"的芯片不一样,所以还得依靠”Dom0“的内核去驱动这个物理设备。所以,数据要想存储,第一,虚拟机的内核经过驱动程序驱动假芯片完成一次转换,这个数据最终还要映射为文件,而这个文件是放在”Dom0“当中的真正的硬盘设备上,它又不得不重新驱动一次这个真正的物理设备,转换为物理介质信号再存下来。可以想象,这中间前面的过程是浪费的。这种方式叫模拟。我们可以尝试着让它半虚拟化。

怎么来实现呢?

Xen

  我们把整个设备切割成两段。”Dom0“上仍然模拟出一个设备出来,但这个设备就不再模拟市面上常见的某个IO设备的类型了。而是模拟出一种支持半虚拟化的类型。也就意味着,在前端主机上看来,这个IO设备仅仅是一个简单的向”Dom0“发起调用的接口而已。它把整个过程轻量化了,明确告诉前半段这是一个Xen虚拟化出来的设备。我们知道,”Dom0“要为多个虚拟机都要提供这样的设备,为了避免混乱,它把每个设备都分为两段来实现,一个叫前端(front),一个叫后端(end),用在虚拟机中的就叫前半段,以硬盘为例,它可能就叫做”block front“。

  这个设备在本地不做任何处理,你请求的数据给这个驱动程序,这个驱动程序直接交给对应的后半段。前半段和后半段直接通信,(它不需要驱动硬件设备去寻道,大家知道,驱动一个硬盘去寻道,而那个磁盘本来就是模拟出来的,这个寻道过程就没有必要了),所以,它就直接交给与之对应的后半段,后半段其实也不做多余的处理,而是交给本地硬件的设备驱动程序来完成存储。所以,半虚拟化的这种IO技术就大大的提高了其性能。

还有一个问题?

假如说真正的硬盘只有一个,在这个硬盘上模拟出了多个磁盘映像文件,每一个磁盘映像文件都提供给了一个虚拟机,这些虚拟机都需要执行磁盘IO了,

于是都发起了大量的读写操作。这些读写操作,即便是用半虚拟化技术,最终还是要转换成物理设备的。所以这些虚拟的IO请求的执行就有先后次序,

那么孰先孰后呢?

Xen

  因此,它其实是构建成一个环状缓冲区,每一个环状缓冲就是一个单独的请求单位。因此第一个虚拟机来的时候,它就放在这个缓冲区上找一个槽位将其数据放上去,以此类推, 就排在这个环上。当排满了,也就意味着这个缓冲区满了,新的IO提交的请求就只能被阻塞。大体上是通过这种方式来对IO设备请求速度进行控制的。包括网络设备,也一样使用类似法则进行工作。

(1)Xen Hypervisor

  xen hypervisor即是xen的虚拟化监视器,它直接运行在硬件之上,并将计算能力通过抽象接口(hyper call)提供给运行在其上的任何操作系统。它的首要任务是在各虚拟机之间进行CPU资源的分配、内存资源的分配、中断请求的分配,并负责控制共享处理环境的虚拟机的执行。

(2)Dom0

  在Xen虚拟化环境中,用”Dom“"Domain"来描述各虚拟机,而且每个虚拟机都有一个唯一的ID进行标识。因此每个虚拟机通常标识为”Dom0“、”Dom1“、”Dom2“等。而”Dom0“叫做”Privileged Domain“,也就是指“特权域”。它拥有这个虚拟化环境的管理权限,而且还能够完成I/O资源的分配。所以说“Dom0”是运行在Xen Hypervisor之上的一个独特的虚拟机,其操作系统内核经过改进以后,除了对I/O资源的分配之外,还会提供管理DomU的工具栈,以实现对运行在Xen Hypervisor之上的其他虚拟机进行管理。比如实现对虚拟机进行添加、启动、快照、停止、删除等操作。

  Linux内核自从2.6.37开始就能够支持"Dom0"。但是那个时候仅仅是原始支持,也就意味着,你把它运行在”Dom0“上,但它的性能表现很差。到3.0以后,对关键特性进行了优化,其可以直接运行在Dom0上。

  Dom0提供了两个特殊驱动,为了能够尽可能使用IO的半虚拟化技术,Dom0还负责在I/O的分配上提供两类设备的驱动,一类是网络设备,一类是块设备。这两类设备支持半虚拟化技术,也就意味着,它们有前端和后端,网络设备的前端叫”net-front“,后端就叫做"net-backend"。对于块设备的前端叫做"block-front",后端叫做"block-end"。而且要注意,这两类设备的前端是在GuestOS中驱动的,而后端是在"特权域"中驱动的。

(3) DomU

  其他的非特权域(Unprivileged Domain),也称为"DomU"。DomU没有访问IO资源的权限,主要目的是将DomU隔离开来。

  Xen支持两种不同类型的虚拟模式,一种是PV技术,还有一种是HVM。Xen只有在CPU支持硬件辅助虚拟化(HVM)的前提下,才能够支持使用完全虚拟化,否则,就只能进行半虚拟化。PV指的是对各GuestOS内核需要操作硬件时,它明确知道自己没有运行在物理机上,而是运行在虚拟化环境中,所以就发起hyper call调用,像这种就叫做半虚拟化技术。但是也可以不用半虚拟化,也可以不用让GuestOS内核以为自己是运行在虚拟化环境中。因为它认为自己是直接运行在CPU上,但这个时候,其实CPU的环0已经没有特权指令了,它一旦发起特权指令时,都会引起运行在环-1上hypervisor的警觉。所以,如果硬件支持辅助虚拟化,Xen Hypervisor是运行在环-1上的,这个时候就不需要再将CPU做半虚拟化,就不需要对GuestOS做修改了,像这种就叫做HVM。

  当然了,如果我们要使用完全虚拟化技术,就带来了另外一个问题。要使用完全虚拟化,那GuestOS里边的IO设备通常都是模拟的,而不是完全虚拟化的。所以,有时候可能会这么做,CPU使用完全虚拟化,但IO设备依然使用半虚拟化,像这种就叫做PV on HVM。

Xen的PV技术:

  PV不要求CPU支持硬件辅助的虚拟化,但要求GuestOS的内核作出修改并知晓自己运行在hypervisor上。所以它无需仿真CPU。

  能运行在DomU中的操作系统有:Linux(2.6.24+),NetBSD,FreeBSD,OpenSolaris等。

Xen的HVM技术:

  依赖于Intel VT或AMD AMD-V,还要依赖于QEMU来模拟IO设备。

  能够运行于DomU中的操作系统:几乎所有支持此x86平台的OS。

PV on HVM:

  为了提高性能,HVM客户机也可以使用特殊的半虚拟化技术驱动。这里的驱动是专门优化的PV驱动,从而使得HVM不再依赖于磁盘和网络IO设备进行模拟,依然可以使用半虚拟化。所以在HVM中,CPU基于HVM完成了完全虚拟化,而各IO设备是通过Qemu模拟的。在PV技术中,CPU是半虚拟化的,GuestOS通过hyper call来调用,而各硬件设备虽然通过Qemu做模拟,但它工作为前半段和后半段,依然工作于半虚拟化模式。在PV on HVM技术中,CPU为HVM模式运行,但IO设备为PV模式运行 。

  运行于DomU中的操作系统:只要OS能驱动PV接口类型的IO设备即可。IO设备接口类型为net-front,blk-front。其实现在windows或linux等大多数操作系统都能够驱动xen之上所谓的前半段。

Xen-半虚拟化架构

Xen

  在半虚拟化场景中,每一个Guest中CPU和Memory都是由Hypervisor进行调用的,Hypervisor通过半虚拟化技术向我们提供。对每一个IO设备,都分成前半段(Front end)和后半段(Back End)。

我们在Guest当中,要想能够驱动它的前半段,就要支持在"dom0"当中能够驱动后半段的技术。

Xen-完全虚拟化技术架构

  在完全虚拟化场景中,每一个Guest中的CPU和Memory仍然是通过Hypervisor提供。Hypervisor借助于硬件辅助的虚拟化,并不要求GuestOS的内核通过hyper call进行调用,

而是直接运行指令就可以。但是对于各IO设备的运行,要借助于qemu-dm进程,使得将它所有模拟出来的设备输出给GuestOS,从而完成完全虚拟化。

Xen工具栈中的工具:

xm/xend:

  早期Xen在4.1或4.2时使用的工具是xm,在Xen Hypervisor的Dom0中要启动xend服务,以便接收来自于xm的命令请求,并在本地完成虚拟机的启动和停止等管理操作。xm是一个命令行管理工具,有诸多子命令来实现其管理功能:create, destroy, stop, pause...。但xend这种方式有点重量级,因为它要求在每一个Xen Hypervisor的Dom0中都要启动xend才能工作的。

xl:

  基于libxenlight提供的轻量级的命令行工具栈。Xen在4.2起同时提供xm和xl,从4.3开始,xm被提示为废弃。

xm与xl的区别:

Xen

  xl直接依赖于libzenlight,而xend也依赖于libzenlight,所以从这个角度发现,xm比xl重量级的多。xl不要启动任何服务,直接能够跟libzenlight进行交互,从而能够实现对xen之上所运行的虚拟机进行管理。

除了这个之外,还有一个工具栈,叫xe/xapi。

xe/xapi:

  提供了对xen管理的api,因此多用于cloud环境,而非手动管理虚拟化的环境。目前,Xen Server或XCP(Xen Cloud Platform)默认使用xe/xapi。xen server是由xen所发行的,它自己直接提供了一个操作系统发行光盘,能够直接在光盘上运行xen虚拟化环境,或者你也可以安装后运行xen虚拟化环境的这么一个linux发行版。xen server早期是收费的,现在已经开源了。xcp是一个企业级应用的xen平台。xen是由英国剑桥大学所研发的,后来它的商业级应用(xen server、xcp等)被思杰(Citrix)收购。

virsh/libvirt:

libvirt工具栈的工作方式:

  在每一个运行了hypervisor或vm的主机上,只需要提供了libvirt库并启动了libvirtd服务进程,我们就可以在当前主机或其他主机上使用virsh命令,借助于本地的libvirt库去连接对方主机上运行的libvirtd进程,这个libvirtd进程把它转换成对本地的虚拟机管理接口的调用。因此它能够管理xen的虚拟化环境,也能够管理kvm虚拟化环境,还能管理qemu虚拟化环境。

  不过这个工具比较重量级,因为它需要在每一个主机上部署库而且还要启动服务。其次,这是虚拟化技术之外的另一套工具,也就是说,xen本来就有提供管理工具了,libvirt还要额外配置使用。

  libvirt这套工具使用python语言所研发,而且充分利用了python当中非常容易实现的图形化编程功能。所以它能够借助于virsh、virt-viewer或virt-manager这些工具栈来提供一个图形化的管理界面。我们可以点击图标来管理虚拟的创建、删除等操作。

上面说到的工具,xe或xm它们都是命令行的管理工具,使用起来是很不方便的。因此就有人对这些工具做了扩展。

Xen

  比如当前网络中,有n个物理服务器,这每一个物理服务器上都部署了hypervisor。要启动虚拟机的时候,这么多服务器哪个上面启动虚拟机呢? 所以如果有一个管理组件,它能够直接运行在这四个hypersivor上,并随时监控着这四个hypervisor对各资源的使用状态。当我们需要启动虚拟机实例时,只需要向运行在这四个主机上能够彼此间协调的进程进行请求,由它负责根据你的喜好来决定在哪个服务器上启动虚拟机实例,并把虚拟机实例启动起来之后分配的IP地址、分配的内存,分配的几颗CPU等告诉我们。这个喜好表示:可以根据CPU的空闲与否,根据内存的空闲与否,根据IO的空闲与否为标准等。

  这么一个横跨多个主机节点,实现资源统一管理和分配的应用程序,就叫做云栈。云栈环境它在管理时,就不再单单将物理主机视为单个主机,而是把所有资源抽取出来统一调度。比如第一个物理服务器有4颗物理核心,第二个物理服务器有八颗核心,它最终把这些内容都抽取出来,放在CPU可用核心池里。那所有主机上的内存总结出来放在可用物理内存空间。要启动一个虚拟机实例时,就从CPU里边挑几个,从内存里面挑一点,从各种IO设备提供的资源里边挑一个,凑成一个虚拟来运行。当然,一般而言,CPU和内存是不能分离的,挑选的哪个主机上的CPU。内存就一定是那个主机上的内存,而IO设备可以通过精巧的方式进行规划。所谓的云环境,不过是虚拟化技术更高更抽象层面上离用户更近的更易于用户使用的虚拟化管理程序。

XenStore:

  为各Domain提供的共享信息存储空间;有着层级结构的名称空间;它位于Dom0上。

Xen的工具栈使用对比:

Xen

Dom0 Kernel

Xen
Xen

DomU Kernel

Xen

CentOS对Xen的支持:

  RHEL 5.7之前包括5.7:默认的虚拟化技术为xen。RHEL5它的内核版本是2.6.18,而linux内核能够运行在Dom0中是在3.0以后,2.6.37支持不是很好,所以是在3.0以后。能够运行在DomU中是在2.6.24以后,都不包含2.6.18。所以那个时候要想使用xen的话,就必须向内核打补丁,而红帽替我们做好了,但是它的内核就有了两个版本。RHEL5.7以前,它的内核版本是kernel-

还有一个叫kernel-xen,如果要想使用RHEL5.7之前的系统的话,安装kernel就可以,但如果要想运行xen技术,需要安装kernel-xen内核才可以。

  但后来,红帽收购了以色列的一家公司,那家公司提供了一个叫做KVM的虚拟化技术,好像是10亿美元,从此有了KVM之后,RHEL从5.8开始同时支持xen和kvm,并且到RHEL6以后,Xen就被抛弃了,只支持KVM。不但仅支持KVM,更不可思议的是,他们把某些虚拟化软件当中对Xen的支持功能在编译时还有意剥离了。所以centos6上没办法直接使用Xen的,RHEL7同样不支持Xen,不过虽然不支持Xen,但它支持运行在Xen的虚拟化环境中。

如何在CentOS 6.6上使用Xen:

手动制作的话:

(1)编译3.0以上版本的内核,启动对Dom0的支持;

(2)编译Xen程序;

制作好相关程序包的项目:

  xen4centos

  xen made easy

xen4centos:Xen官方专门为centos发行版额外提供Xen的项目。

配置xen的yum源:http://mirrors.sohu.com/centos/6/virt/x86_64/xen-46/

由于要安装xen就不得不安装一个新的内核,否则要自己编译。这个内核当中要启用对Dom0的支持。

xen hypersivor要自己启动在硬件上,所以我们不能直接启动新版内核。所以,这里不能把它当新版内核来用,我们要额外加一个kernel行

# vim /etc/grub.conf

grub配置:

显示Domain的相关信息

对于xl而言,其创建DomU使用的配置指令可通过“man xl.cfg”获取

常用指令:

PV模式专用指令:

磁盘参数指定方式:

官方文档:http://xenbits.xen.org/docs/unstable/misc/xl-disk-configuration.txt

busybox编译成静态链接格式,方便迁移:

示例:

创建一个pv格式的vm:

如何配置网络接口:

配置桥接的方式

建立虚拟通道:

xl的其他常用命令:

使用DomU自有kernel来启动运行DomU:

制作磁盘映像文件:

/etc/xen/busybox3:

使用xl命令进行创建虚拟机并完成Centos 6.6的系统安装:

(1) 创建磁盘映像文件

(2) 获取安装指定版本的系统所需要的kernel及initrd文件

(3) 创建DomU配置文件,示例如下:

(4) 安装完成后,创建虚拟机的配置文件需要作出修改

启动图形窗口:

在创建虚拟机的配置文件中定义vfb

(1) vfb = [ 'sdl=1' ]

(2) vnc

  (a) yum install tigervnc //使得我们有vncviewer可用

  (b) vfb = [ 'vnc=1' ]

  vnc监听的端口为5900, 相应的DISPLAYNUM为0

使用Dom0中物理磁盘分区为DomU提供存储空间:

使用libvirt实现xen虚拟机管理

继续阅读