kvm简介
近年来,由于各种各样的原因,x86系列CPU服务器的虚拟化技术受到广泛关注。服务器虚拟化技术本身已经存在一段时间了,Intel在他们CPU中提供的(Intel VT)1)和AMD在他们CPU中提供的虚拟化(ADM-V)2)使得开发者们能够在x86硬件上以相对廉价的成本使用虚拟化技术,并且基本能满足性能要求。各种基于软件的服务器虚拟化技术也相继出现,其中(KVM)3) 以开放源码软件(OSS)服务器虚拟化技术的形式迅速走在了前列。KVM是基于Intel VT-x note1)和AMD-V的设计,使用相对简单的架构(结构)来获得虚拟化。KVM的基本思想于2006年10月份由Avi Kivity(当时的Qumranet,一家以色列公司)首次公布。Linux内核开发者们被KVM简洁的设计所吸引,迅速采纳并扩展了它的功能。KVM目前得到Red Hat企业版Linux的正式支持,并从版本6开始受到Fujitsu的支持。这篇论文描述KVM的简单机制,并简要介绍硬件及软件各层面对KVM的支持,默认以Intel VT-x CPU的功能为例。
Intel VT-x和敏感指令
KVM会使用到Intel VT-x的功能,KVM的设计者把KVM当作Linux内核的功能来实现.note2)。接下来是对KVM的一个概览,以辅助理解KVM。Intel VT-x可以被看作是一个“检测到敏感指令执行时切换到hypervisor的功能”,如图1所示。Hypervisor是物理机上操控VM(客户机系统)的一个控制程序。敏感指令有两种定义:
1) “控制敏感指令”试图修改系统资源状态。
2) “行为敏感指令”根据系统资源的状态进行操作。
概念上,虚拟机上的程序执行控制敏感指令影响物理机的行为,虚拟机上的程序执行行为敏感指令表现为在虚拟机上执行的效果,和它们在物理机上执行产生不同的效果。如果一个程序试图执行这些指令而不被阻止,将会给hypervisor和客户机系统带来严重的问题。因此,有必要让CPU在检测到一个敏感指令的开始执行并把它转向到hypervisor,让hypervisor替代应用程序去执行这个敏感指令。然而,x86 CPU在设计之初并没有考虑到虚拟化的需求,所以有一些敏感指令试图在客户机系统执行时无法被CPU检测到,结果导致了hypervisor无法代替客户机系统去执行那些指令。Intel VT-x就是为应对这个问题而被开发的,它给处理器添加了新的执行模式,在CPU检测到这些敏感指令时进行模式切换,这样hypervisor就可以代替初始的那个程序去执行敏感指令。
KVM和QEMU
KVM内核模块自己无法创建VM,要创建VM,它必须使用QEMU,QEMU以一个用户空间进程存在 6)。QEMU本质上是一个硬件模拟器,它作为一个开放源码软件,模拟标准的x86 PC和其它的架构,其存在早于KVM也不依赖KVM来运行。作为一个基于软件的模拟器,QEMU逐条地解释和执行CPU指令,意味着性能受限。然而,如果有三个条件能够满足,QEMU可以在保持其创建VM功能的同时大大提升其性能。
1) 目标指令可以直接被CPU执行。
2) 在VMX非根操作模式下,指令可以不经修改的被CPU直接执行。
3) 不能直接执行的指令可被鉴别并传递给QEMU进行模拟处理。
KVM的开发就是基于这个思想,它使得既可以创建虚拟机又能最大化的复用已有的开放源码软件(OSS),只需做最小量的修改。正是这个原因,使KVM得到很多Linux内核开发者的支持。
QEMU/KVM有一个相对简单的结构:
1) KVM内核模块的实现将Linux内核变成一个hypervisor。
2) 每个客户机系统有一个QEMU进程。有多少个客户机系统在运行,就相应的有多少个QEMU进程在运行。
3) QEMU是一个多线程程序,客户机系统的每个虚拟CPU(vCPU)对应一个QEMU线程。
4) 从Linux内核来看,QEMU线程就和普通的用户进程一样。对应于客户机虚拟CPU的线程接受Linux内核调度器的管理,这和其它进程的线程无异。
KVM硬件和软件支持的功能
服务器虚拟化最关注的是性能,理想的情况下,虚拟机的性能不要比物理机性能差。为此,除了上文描述的基本的KVM机制,各种不同的硬件和软件支持虚拟化功能争相出现。最基本的目标就是使用它们来改善KVM的性能。这一节将介绍几个这样的功能。
1) Extended Page Table(EPT)
EPT扩展了CPU提供的地址转换机制(MMU: 内存管理单元)。虚拟机包含两部分结构,一部分是hypervisor,另一部分是客户机系统。以往的MMU结构在设计时没有考虑到虚拟机的需求,不能直接使用。
在EPT之前,需要使用软件方案进行地址转换,这种技术叫“影子页表”。EPT使得虚拟机的“物理地址”由CPU转换成物理机的物理地址,软件转换方案也就不需要了。KVM充分利用了EPT提供的功能,使得虚拟机性能得到大幅提升。
2) VT-d
VT-d是I/O设备(IOMMU)的地址转换机制。它为每种设备功能提供了内存地址转换表(和MMU页表的数据结构完全一致)。有了VT-d,客户机的内存地址可被指定为设备数据传输的目标地址,数据直接被传递到客户机操作系统。VT-d属于芯片级功能,需要固件的支持。相应的,如果固件和Linux内核都支持VT-d,后者会识别VT-d功能并使用它。
3) virtio
虚拟机设备通常由QEMU设备模拟功能进行创建和处理。这种模拟的开销很高,因此I/O性能表现不佳。为了克服这个问题,引入了一种叫“virtio”的机制。Virtio准备一个缓冲区,该缓冲区可同时被客户机系统和QEMU访问。使用这个缓冲区,对多个数据项的I/O处理就可以同时进行,减少了QEMU模拟的开销进而或得高速的处理方案。从客户机系统来看,这种机制就像是访问一个virtio PCI设备一样。通过在客户机系统中实现一个virtio驱动(当然,Windows需要一个virtio驱动),可获得virtio带来的好处并达到高速I/O的效果。
4) Kernel Samepage Merging(KSM)
同一个物理机上不同虚拟机可能在运行同样的操作系统和应用程序。在这种情况下,它们很有可能有些内存区域具有相同的数据。将这些内存区域整合成一个区域将减少内存的使用量。基于这一点,KSM功能 9)被添加到KVM。KSM功能使用一个“ksmd”内核线程定期监控进程内存使用情况并自动将重复的内存页合并成一个公共页。理想的情况下,所有内存页都会被拿来比较看是否有重复数据,但持续地比较所有系统进程使用的所有内存页会极其低效。由于这个原因,Linux提供一种机制,即可以通过madvice()系统调用的第三个参数(advice参数)来指定哪个内存区将被考虑作为KSM进行合并的对象。QEMU在给客户机分配内存时使用这个系统函数,用户就立即享受到KSM的功能。在RHEL6中,这个功能在系统初始化状态下就是有效的。
KVM未来的增强
我们的目标就是使得KVM能够在关键任务系统和应用领域被使用,但为改善功能和质量,还有很多地方需要提升。下面介绍的是Fujitsu的几项开发计划,目的是提升KVM功能。
1) libvirt功能性和质量上的提升
相对于KVM内核模块和QEMU的成熟度,libvirt的功能还远未完整,这使得KVM的功能无法被完全挖掘,而且libvirt还没有达到稳定和质量良好的状态。因此,提升libvirt的功能性和质量是一个紧迫的开发任务。
2) 资源管理功能的提升
按预期,KVM会和Cgroup 10)整合,Cgroup是RHEL6中引进的一个资源管理功能。当前,Cgroup的功能可用于多种资源的分配,如给一个进程分配某个特定数目的CPU。然后,从控制虚拟机系统的角度来看,KVM和Cgroup的整合还是有很多问题需要处理,比如对I/O没法进行足够的控制。因此提升Cgroup功能也是一项计划。
3) Machine-check support(机器检查支持)
物理机不可纠正错误,如multi-bit错误发生的信息要能够被传递给客户机系统。关于这个,一个基本的框架已经被合并到KVM,但是专门针对KVM机器检查的支持还需要提升,以使客户机系统可以进行内存错误的恢复。
kvm实例部署
1、KVM通俗的说就是一台服务器当多台用,首先查看服务器是否支持虚拟化
grep -E '(vmx|svm)' /proc/cpuinfo
2、安装qemu和libvirt工具
yum -y install qemu-kvm qemu-kvm-tools virt-manager libvirt virt-install
3、启动libvirtd,让qemu工具通过这个守护进程和接口来管理虚拟机
systemctl enbale libvirtd.service
systemctl start libvirtd.service
4、创建镜像文件,为下面创建虚拟机做准备
首先将centos6.6-x86_64.iso镜像挂载到vmware虚拟机的光驱上,用dd命令来创建虚拟机的镜像
dd if=/dev/cdrom of=/opt/centos6.iso
5、为虚拟机创建磁盘文件
创建虚拟机镜像文件的模式有:全镜像模式:raw和稀松模式:qcow2
qemu-img create -f raw /opt/centos6-x86_64.raw 5G 这个raw模式创建多大的磁盘就是多大,而且这个模式是不能对虚拟机做快照的
qemu-img create -f qcow2 /opt/centos6-x86_64.qcow2 5G 这个qcow2模式创建5G磁盘,但会根据使用情况来增加磁盘的使用量,而且这个模式支持虚拟机的快照
6、创建一个虚拟机
virt-install --name centos6-goser01 --virt-type kvm --ram 1024 --cdrom=/opt/centos6.iso --disk path=/opt/centos6-x86_64.raw --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
7、windows上安装个vnc,去连接虚拟机
安装第一个虚拟机的的端口为5900,第二个端口就为5901.。。。一次类推
如果安装的是centos7虚拟机的话,最好在安装开始界面中按tab健,然后输入:net.ifnames=0 biosdevname=0 确定 。这样安装完虚拟机后网卡的接口就自动更改为eth0 eth1这样的网卡名称
8、安装完虚拟机后就可以对虚拟机做一些配置管理操作
比如对虚拟机的xml做个备份,防止虚拟机丢失,可以对其还原。命令如下:
virsh dumpxml centos6-goser01 >backend.xml
还原操作:virsh define -f /opt/backend.xml
kvm常用的命令为:
[root@linux-node1 ~]# virt-install #建立kvm虚拟机 [root@linux-node1 ~]# virsh list #查看正在运行的KVM虚拟机 [root@linux-node1 ~]# virsh list --all #查看所有KVM虚拟机 [root@linux-node1 ~]# virsh start name #启动KVM虚拟机 [root@linux-node1 ~]# virsh shutdown name #正常关闭KVM虚拟机 [root@linux-node1 ~]# virsh destroy name #强制关闭KVM虚拟机(类似于直接断电) [root@linux-node1 ~]# virsh suspend name #挂起KVM虚拟机 [root@linux-node1 ~]# virsh resume name #恢复挂起的KVM虚拟机 [root@linux-node1 ~]# virsh dumpxml name #备份虚拟机的xml文件 [root@linux-node1 ~]# virsh edit name #编辑KVM虚拟机的xml配置文件 [root@linux-node1 ~]# virsh undefine name #彻底删除KVM虚拟机,不可逆,如果想找回来,需要备份/etc/libvirt/qemu的xml文件)
9、kvm网络配置
默认情况KVM的网络是NAT模式,但是在生产情况,用的多的都是网桥模式。
添加一个桥接网卡:brctl addbr br0
查看桥接网卡信息
[root@linux-node1 ~]# brctl show bridge name bridge id STP enabled interfaces br0 8000.000000000000 no virbr0 8000.5254009f0311 yes virbr0-nic
把eth0加入网桥,使用桥接模式,给br设置ip
[root@linux-node1 ~]# brctl addif br0 eth0 && ip addr del dev eth0 192.168.182.170/24 && ifconfig br0 192.168.182.170/24 up && route add default gw 192.168.182.2
这时候在桥接网卡信息为:eth0已经加入到桥接网卡br0上了
[root@linux-node1 ~]# brctl show bridge name bridge id STP enabled interfaces br0 8000.000000000000 no eth0 virbr0 8000.5254009f0311 yes virbr0-nic
编辑虚拟机的网络配置使用br0网桥模式
[root@linux-node1 ~]# virsh edit centos6-goser01 <interface type='bridge'> <mac address='52:54:00:22:04:0f'/> #为虚拟机分配MAC地址,务必唯一,如果是dhcp获得同样IP会引起冲突 <source bridge='br0'/> #当前主机网桥名称
然后重启虚拟机、
virsh destroy centos6-goser01 virsh start centos6-goser01
这时候再查看桥接网卡的信息如下:将虚拟机的网卡已经加入到网桥br0中了
[root@linux-node1 ~]# brctl show bridge name bridge id STP enabled interfaces br0 8000.000000000000 no br0 vnet0 virbr0 8000.5254009f0311 yes virbr0-nic
10、对虚拟机的配置注意事项:
分区的时候,只分一个/分区(不需要swap分区)。 删除网卡里面{UUID,MAC} 如果有/etc/udev/rules.d/70-persistent-ipoib.rules 则删除 iptables关闭、selinux关闭 安装基础软件包。(net-tools lrzsz screen tree vim wget)
11、对虚拟机做快照
对虚拟机做快照的过程,虚拟机是暂停状态的,如果是线上操作,这个要慎重。
如果要对虚拟机做快照的话,那么这个虚拟的磁盘必须采用qcow2模式,所以这里重新创建一个以qcow2磁盘模式的虚拟机
qemu-img create -f qcow2 /opt/centos6-x86_64.qcow2 5G virt-install --name centos6-goser02 --virt-type kvm --ram 1024 --cdrom=/opt/centos6.iso --disk path=/opt/centos6-x86_64.qcow2 --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
然后对虚拟机centos6-goser02做快照
virsh snapshot-create-as --domain centos6-goser02 --name goser02-snapshot1
用vnc客户端登录虚拟机centos6-goser02安装apache服务,然后再对centos6-goser02做快照
再虚拟机centos6-goser02中安装apache服务 yum install httpd -y echo 'this is virtmachions and httpd server is starting' curl 127.0.0.1 #测试正常 然后再物理机上再对centos6-goser02做快照 virsh snapshot-create-as --domain centos6-goser02 --name goser02-snapshot2-httpd
查看虚拟机快照的列表
[root@linux-node1 ~]# virsh snapshot-list centos6-goser02 Name Creation Time State ------------------------------------------------------------ goser02-snapshot1 2017-11-23 01:50:40 +0800 running goser02-snapshot2-httpd 2017-11-23 01:56:27 +0800 running
恢复虚拟机centos6-goser02到快照goser02-snapshot1,这个快照的状态是没有安装apache服务的,用curl测试时不成功的
virsh snapshot-revert centos6-goser02 goser02-snapshot1
再恢复到安装完httpd服务的快照,再curl是正常的
virsh snapshot-revert centos6-goser02 goser02-snapshot2-httpd
查看当前虚拟机所处的快照状态
[root@linux-node1 ~]# virsh snapshot-current centos6-goser02 <domainsnapshot> <name>goser02-snapshot2-httpd</name>
当然也可以对快照进行删除操作如下:
[root@linux-node1 ~]# virsh snapshot-delete --domain centos6-goser02 --name goser02-snapshot2-httpd [root@linux-node1 ~]# virsh snapshot-list centos6-goser02 Name Creation Time State ------------------------------------------------------------ goser02-snapshot1 2017-11-23 01:50:40 +0800 running
12、对虚拟机做克隆操作
首先对要做克隆的虚拟机做调整如下:
1、删除虚拟机网卡的配置中的mac地址和uuid
vim /etc/sysconfig/network-scripts/ifcfg-eth0
2、删除70-persistent-net.rules
rm -f /etc/udev/rules.d/70-persistent-net.rules
接着关闭虚拟机,对虚拟机进行克隆
#本机直接克隆 virt-clone -o centos6-goser02 -n goser02-clone -f /opt/goser02-clone.qcow2 virsh start goser02-clone #启动后,修改hostname、IP等
克隆完成后便生成了一个克隆成功的磁盘文件goser02-clone.qcow2
13、cpu热添加操作
kvm虚拟机热添加cpu 注意。只能添加不能减少,而且不能超过设置的个数
修改虚拟机的xml文件,让其支持cpu热添加 virsh edit centos6-goser01 <vcpu placement='auto' current='1'>3</vcpu> 设置虚拟机cpu数 vrish setvcpus centos6-goser01 2 --live #意思讲cpu添加到2个 然后登陆虚拟机,验证cpu添加是否成功 grep 'processor' /proc/cpuinfo |wc -l 2
14、内存热添加
内存的设置拥有一个气球(balloon)机制,可以增大减少,但是也要设置一个最大值,默认并没有最大值,也可以在安装时指定。内存热膨胀和压缩,总数不能超过最大内存
virsh edit centos6-goser01 <memory unit='KiB'>4194304</memory> #修改最大支持内存扩容为4G <currentMemory unit='KiB'>1048576</currentMemory> #当前KVM虚拟机内存为1G 重启虚拟机 [root@linux-node1 ~]# virsh qemu-monitor-command centos6-goser01 --hmp --cmd info balloon #查看当前KVM内存大小 balloon: actual=1024 [root@linux-node1 ~]# virsh qemu-monitor-command centos6-goser01 --hmp --cmd balloon 2048 #热添加 [root@linux-node1 ~]# virsh qemu-monitor-command centos6-goser01 --hmp --cmd info balloon #在次查看 balloon: actual=2048
在热添加或减少内存的时候,可以在虚拟机中通过free -m来查看内存的动态变化
更改虚拟机中存储,硬盘设置(不建议生产环境使用硬盘的扩大收缩模式,很容易产生故障)