虚拟化简介

hypervisor

hypervisor是一个虚拟化软件,直接运行在硬件之上,虚拟机搭建在hypervisor之上,多个虚拟机通过hypervisor共享底层的硬件资源。hypervisor的主要功能是对底层的硬件资源进行管理,协调运行在其上的虚拟机对硬件资源的访问,并且保护每一个虚拟机在运行过程中不受其他虚拟机的影响。

完全虚拟化

完全虚拟化即虚拟机运行在模拟的硬件之上。在hypervisor中运行的虚拟机表现为一个运行在用户空间的进程,虚拟机上的进程需要执行特权指令时,即需要对底层的硬件进行访问时,其相关的操作(例如cpu指令)会被hypervisor捕获,由hypervisor完成执行并返回结果。在这个过程中hypervisor会给处理器带来很大的开销。在硬件辅助虚拟化中,这个过程由硬件来辅助完成,大大提升了性能。在完全虚拟化环境中,虚拟机上的操作系统不会意识到自己运行在虚拟化的环境中,客户端的操作系统内核无需修改。对应的实现软件有VMware Workstation,KVM.......

半虚拟化

在半虚拟化环境中,hypervisor将底层硬件资源的功能以API(hyper call)的形式向上输出,虚拟机上的操作系统通过调用这些hyper call来完成特权指令的执行。这减小了hypervisor的开销,但是内核执行相应的操作需要基于hyper call来完成,这需要对内核进行修改,这使得像windows这样的操作系统很难运行在半虚拟化环境中。


Xen基本组件

xen是半虚拟化的一种实现,操作系统的内核需要进行修改才能运行在xen上。Linux的内核中已经集成了这部分代码,能够直接运行在xen的虚拟化平台上。如下是xen的结构图:

xen有3个基本组件:

Xen Hypervisor:直接运行在硬件之上,主要为运行在上方的虚拟机分配cpu和内存资源。虚拟机需要访问cpu和内存资源时通过调用Xen Hypervisor提供的API完成。

Domain 0:运行在Xen Hypervisor上,Dom0本地有IO设备的驱动,能够直接访问底层的IO设备,所有DomU上的IO处理都需要经过Dom0完成对IO设备的访问。在启动时,需要先启动Dom0,然后再启动DomU。Linux-2.6.37之后版本的内核可直接运行在Dom0上。

DomainU:运行在Xen Hypervisor上的客户虚拟机,能够并行运行多个,DomU对硬件资源的访问需要通过Xen Hypervisor和Dom0完成。


Xen的安装部署

安装部署在centOS6上完成。

配置yum源,安装xen的软件包。(使用搜狐的源)

[root@node1 ~]# vim /etc/yum.repos.d/xen.repo[xen]name=xenbaseurl=http://mirrors.sohu.com/centos/6/xen4/x86_64/gpgcheck=0enabled=1cost=100####################[root@node1 ~]# yum install xen

这里使用3.4版本的内核来部署(centos官方提供的最新版本内核3.18貌似存在点问题)

[root@node1 xen4]# lskernel-3.4.68-9.el6.centos.alt.x86_64.rpm           xen-libs-4.2.4-30.el6.centos.alt.x86_64.rpmkernel-firmware-3.4.68-9.el6.centos.alt.noarch.rpm  xen-licenses-4.2.4-30.el6.centos.alt.x86_64.rpmxen-4.2.4-30.el6.centos.alt.x86_64.rpm              xen-runtime-4.2.4-30.el6.centos.alt.x86_64.rpmxen-hypervisor-4.2.4-30.el6.centos.alt.x86_64.rpm[root@node1 xen4]# yum install ./*


修改grub.conf文件:

default=0timeout=5splashp_w_picpath=(hd0,0)/grub/splash.xpm.gzhiddenmenutitle CentOS (3.4.68-9.el6.centos.alt.x86_64)        root (hd0,0)        kernel /xen.gz dom0_mem=512M cpureq=xen dom0_max_vcpus=1 dom0_vcpus_pin        module /vmlinuz-3.4.68-9.el6.centos.alt.x86_64 ro root=/dev/mapper/vg_node1-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=vg_node1/lv_swap rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=vg_node1/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet        module /initramfs-3.4.68-9.el6.centos.alt.x86_64.imgtitle CentOS (2.6.32-431.el6.x86_64)        root (hd0,0)        kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/vg_node1-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=vg_node1/lv_swap rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=vg_node1/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet        initrd /initramfs-2.6.32-431.el6.x86_64.img

dom0_mem:dom0使用的内存。

cpufreq:cpu的工作频率由xen管理。

dom0_max_vcpus:使用虚拟cpu的个数。

dom0_vcpus_pin:把Dom0的虚拟化cpu直接绑定运行在某个物理cpu的核心上。


配置完成之后重启操作系统,启动完成之后,当前的系统就运行在Dom0上。

[root@node1 ~]# reboot........[root@node1 ~]# uname -r3.4.68-9.el6.centos.alt.x86_64

查看当前运行的所有Domain:

[root@node1 ~]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   512     1     r-----      20.3


添加网桥设备,桥设备不支持使用NetworkManager来管理,使用network来管理。桥设备的添加可以使用程序包brctl-utils中的工具来完成,也可以手动添加。

[root@node1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-br0DEVICE=br0TYPE=BridgeONBOOT=yesNM_CONTROLLED=noBOOTPROTO=noneIPADDR=192.168.1.106NETMASK=255.255.255.0GATEWAY=192.168.1.1STP=onDNS1=61.153.81.74DNS1=202.96.104.27USERCTL=no[root@node1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0DEVICE=eth0TYPE=EthernetONBOOT=yesNM_CONTROLLED=noBOOTPROTO=noneBRIDGE=br0USERCTL=no

然后重启网卡:

[root@node1 ~]# service network restart[root@node1 ~]# brctl showbridge name	bridge id		STP enabled	interfacesbr0		8000.000c293331f2	yes		eth0


Xen的环境已经部署完成,接下来开始安装虚拟机。虚拟机操作系统的安装通过网络的方式完成。

提供nginx文件服务器(192.168.1.127),部署安装源。

[root@node2 ~]# yum install nginx -y[root@node2 ~]# vim /etc/nginx/conf.d/default.conf ....location / {        root   /usr/share/nginx/html;        index  index.html index.htm;        autoindex on;    }    [root@node2 ~]# mount /dev/cdrom /usr/share/nginx/html/[root@node2 ~]# service nginx start


在Dom0(192.168.1.106)上为虚拟机提供启动过程中使用的内核及引导文件:

[root@node1 ~]# mkdir /mnt/flash[root@node1 ~]# mount /dev/cdrom1 /mnt/flash[root@node1 ~]# cp /mnt/flash/isolinux/{initrd.img,vmlinuz} /xen/

创建磁盘镜像文件:

[root@node1 ~]# qemu-img create -f qcow2 -o size=30G,preallocation=metadata /xen/xen1_disk.qcow2[root@node1 ~]# ll -h /xen/xen1_disk.qcow2 -rw-r--r-- 1 root root 31G Sep 23 11:44 /xen/xen1_disk.qcow2

编辑Xen虚拟机的配置文件:

[root@node1 ~]# vim /etc/xen/xen1kernel = "/xen/vmlinuz"ramdisk = "/xen/initrd.img"vcpus = 1memory = 512name = "xen1"disk = ['file:/xen/xen1_disk.qcow2,xvda,w']vif = ["bridge=br0"]on_reboot = "destroy"on_crash = "destroy"


启动虚拟机,开始安装操作系统。

这里使用xl命令完成对虚拟机的管理,xl命令使用时最好关闭xend服务。

[root@node1 ~]# xl create -f /etc/xen/xen1Parsing config from /etc/xen/xen1libxl: notice: libxl_numa.c:451:libxl__get_numa_candidate: NUMA placement failed, performance might be affectedDEBUG libxl__blktap_devpath 37 aio:/xen/xen1_disk.qcow2DEBUG libxl__blktap_devpath 40 /dev/xen/blktap-2/tapdev0Daemon running with PID 2908

列出当前所有的虚拟机,可你看到xen1已经启动。

[root@node1 ~]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   496     1     r-----      16.5xen1                                         3   512     1     -b----       4.2

进入虚拟机的控制台完成安装:

[root@node1 ~]# xl console xen1

选择安装过程使用的语言:

选择使用网络的方式获取安装源:

使用DHCP服务器获取IP地址:

指定安装源,这里指向nginx提供的文件服务器:



接下来的步骤与在图形化界面下系统安装的步骤基本一致,根据提示进行即可........

安装完成后,重启操起操作系统。当然这里不会重启,定义domain时,设定on_reboot = "destroy",所以这里的reboot会使虚拟机关机。

系统关机后,修改配置文件,这时系统的启动不需要再依赖Dom0上的内核和ramfs文件,因为虚拟机自身上已经有内核和ramfs文件了。加上bootloader这一项,来引导虚拟机加载内核。

[root@node1 ~]# vim /etc/xen/xen1 #kernel = "/xen/vmlinuz"#ramdisk = "/xen/initrd.img"bootloader="/usr/bin/pygrub"vcpus = 1memory = 512name = "xen1"disk = ['file:/xen/xen1_disk.qcow2,xvda,w']vif = ["bridge=br0"]on_reboot = "restart"on_crash = "destroy"


启动虚拟机,进入虚拟机的控制台为其配置网络环境。

[root@node1 ~]# xl console xen1

如上图所示进入虚拟机的控制台,退出使用“Ctrl+]”。然后配置网络环境重启网卡。

[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE="eth0"BOOTPROTO="dhcp"NM_CONTROLLED="no"ONBOOT="yes"TYPE="Ethernet"UUID="ce31b7c8-9039-4aaa-8b12-3b0e854941d0"[root@localhost ~]# service network restart[root@localhost ~]# ip addr show eth02: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000.....    inet 192.168.1.152/24 brd 192.168.1.255 scope global eth0.....

完成!!!


虚拟机的相关操作

挂起恢复虚拟机

在虚拟机运行过程中可以将虚拟机挂起(类似于VMware),实现过程如下:

查看当前正在运行的虚拟机:

[root@node1 xen]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   496     1     r-----      32.2xen1                                         5   512     1     -b----       6.4

挂起xen1,将虚拟机的运行数据保存至一个文件上。

[root@node1 xen]# xl save xen1 /tmp/xen1.saveSaving to /tmp/xen1.save new xl format (info 0x0/0x0/251)DEBUG libxl__device_destroy_tapdisk 66 type=aio:/xen/xen1_disk.qcow2 disk=:/xen/xen1_disk.qcow2[root@node1 xen]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   496     1     r-----      36.0

恢复xen1:

[root@node1 xen]# xl restore /tmp/xen1.save [root@node1 xen]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   496     1     r-----      38.2xen1                                         6   512     1     -b----       0.1


有别于真实的物理机,虚拟机运行在虚拟环境下,对其可以动态地添加和拆除IO设备而不需要重启系统。

动态添加磁盘

创建一个磁盘镜像文件:

[root@node1 xen]# qemu-img create -f qcow2 -o size=20G,preallocation=metadata /tmp/test.qcow2

动态添加磁盘,添加时指定xen1上的设备名称(前端设备),及对应于Dom0上的后端设备和设备的读写权限。

[root@node1 ~]# xl block-attach xen1 file:/tmp/test.qcow2 xvdb w[root@node1 ~]# xl block-list xen1Vdev  BE  handle state evt-ch ring-ref BE-path                       51712 0   5      4     8      8        /local/domain/0/backend/vbd/5/5171251728 0   5      4     10     867      /local/domain/0/backend/vbd/5/51728

拆除刚刚添加的磁盘:

[root@node1 xen]# xl block-detach xen1 51728DEBUG libxl__device_destroy_tapdisk 66 type=aio:/tmp/test.qcow2 disk=:/tmp/test.qcow2


动态添加网络设备

添加网卡,添加时指定虚拟机名称和桥接的设备。

[root@node1 xen]# xl network-attach xen1 bridge=br0[root@node1 xen]# xl network-list xen1Idx BE Mac Addr.         handle state evt-ch   tx-/rx-ring-ref BE-path                       0   0  00:16:3e:10:87:43     0     4      9   768/769         /local/domain/0/backend/vif/5/01   0  00:16:3e:4c:5e:1c     1     4     10  1280/1281        /local/domain/0/backend/vif/5/1

拆除网卡:

[root@node1 xen]# xl network-detach xen1 1[root@node1 xen]# xl network-list xen1Idx BE Mac Addr.         handle state evt-ch   tx-/rx-ring-ref BE-path                       0   0  00:16:3e:4d:40:3d     0     4      9   769/768         /local/domain/0/backend/vif/6/0


Xen实时迁移

实验环境:

node1:192.168.1.106

node2:192.168.1.127

iscsi节点:192.168.1.132

node1上的虚拟机实时迁移至node2上,这时需要将磁盘镜像文件放在共享存储上。共享存储使用iscsi实现。


首先用同样的方式将node2部署成为Dom0。

iscsi节点上(192.168.1.132

安装iscsi服务端程序

[root@node5 ~]# yum install -y scsi-target-utils

编辑配置文件,指定共享的块设备和允许访问的地址。

[root@node5 ~]# vim /etc/tgt/targets.conf .....<target iqn.2015-09.com.xiaoxiao:server.target1>    backing-store /dev/sdb    initiator-address 192.168.1.0/24</target>[root@node5 ~]# service tgtd start


在node1和node2上

安装iscsi客户端程序

[root@node1 ~]# yum install -y iscsi-initiator-utils

对于客户端而言,每一个initiator都应该有一个自己的名称,设置名称。

[root@node1 ~]# echo "InitiatorName=`iscsi-iname -p iqn.2015-09.com.xiaoxiao`" > /etc/iscsi/initiatorname.iscsi[root@node1 ~]# cat /etc/iscsi/initiatorname.iscsiInitiatorName=iqn.2015-09.com.xiaoxiao:25d3444fe940

发现设备,发现设备的同时会启动客户端服务。

[root@node1 ~]# iscsiadm -m discovery -t st -p 192.168.1.132Starting iscsid:                                           [  OK  ]192.168.1.132:3260,1 iqn.2015-09.com.xiaoxiao:server.target1

建立会话,建立以后会在/var/lib/iscsi/目录下保存此前发现的targets。下一次启动时会自动读取这个目录,并获取此前发现的target。

[root@node3 ~]# iscsiadm -m node -T iqn.2015-09.com.xiaoxiao:server.target1 -p 192.168.1.132 -l[root@node1 ~]# fdisk -l /dev/sdb Disk /dev/sdb: 53.7 GB, 53687091200 bytes64 heads, 32 sectors/track, 51200 cylindersUnits = cylinders of 2048 * 512 = 1048576 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk identifier: 0x00000000


对应设备已经存在,接下来在node1上对其进行分区格式化,并挂载。

[root@node1 ~]# fdisk /dev/sdb.......[root@node1 ~]# mke2fs -t ext4 -b 4096 /dev/sdb1[root@node1 ~]# mount /dev/sdb1 /xen/

将磁盘镜像文件复制到共享的分区上,/xen目录下的文件刚刚备份至了/tmp目录下,在转移磁盘镜像文件时,不要忘了关闭虚拟机!!!

[root@node1 ~]# cp /tmp/xen/xen1_disk.qcow2 /xen/

xen1的配置文件/etc/xen/xen1同步至node2,同时在node2上过载共享设备至相同的目录下:

[root@node1 ~]# scp /etc/xen/xen1 192.168.1.127:/etc/xen/xen1[root@node2 ~]# mount /dev/sdb1 /xen/


开始迁移过程

node1上启动虚拟机:

[root@node1 ~]# xl create -f /etc/xen/xen1###############################[root@node1 ~]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   496     1     r-----     155.7xen1                                         8   512     1     -b----       3.0[root@node2 ~]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   512     1     r-----     123.8


在node2上执行”xl migrate-receive“,准备好接受来自其他节点的虚拟机转移数据。

[root@node2 ~]# xl migrate-receive migration target: Ready to receive domain.xl migration receiver ready, send binary domain data.

在node1上执行”xl migrate xen1 192.168.1.127“将xen1的虚拟机转移至node2节点上。由于xl的实时迁移是通过ssh传输机制实现的,所以在执行这条命令之后需要输入对方主机的root密码,才能开始传输。

[root@node1 ~]# xl migrate xen1 192.168.1.127root@192.168.1.127's password:                           #输入密码migration target: Ready to receive domain.Saving to migration stream new xl format (info 0x0/0x0/251)Loading new save file <incoming migration stream> (new xl fmt info 0x0/0x0/251) Savefile contains xl domain configxc: Saving memory: iter 0 (last sent 0 skipped 0): 131072/131072  100%xc: Saving memory: iter 1 (last sent 130942 skipped 130): 131072/131072  100%xc: Saving memory: iter 2 (last sent 228 skipped 0): 131072/131072  100%      xc: Saving memory: iter 3 (last sent 0 skipped 0): 131072/131072  100%   DEBUG libxl__blktap_devpath 37 aio:/xen/xen1_disk.qcow2DEBUG libxl__blktap_devpath 40 /dev/xen/blktap-2/tapdev0migration sender: Target has acknowledged transfer.migration sender: Giving target permission to start.migration target: Transfer complete, requesting permission to start domain.migration target: Got permission, starting domain.migration target: Domain started successsfully.migration sender: Target reports successful startup.DEBUG libxl__device_destroy_tapdisk 66 type=aio:/xen/xen1_disk.qcow2 disk=:/xen/xen1_disk.qcow2Migration successful.


最下面显示传输完成在各节点上查看虚拟机状态。

[root@node1 ~]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   492     1     r-----     200.7[root@node2 ~]# xl listName                                        ID   Mem VCPUs	State	Time(s)Domain-0                                     0   512     1     r-----     157.6xen1                                        13   512     1     -b----       0.5

在传输过程中,对被转移的虚拟机发起ping操作,仅有一小段时间内无法ping通。