KVM
Kernel-based Virtual Machine,基于内核的虚拟机;
KVM是作为内核模块嵌入进Linux内核的,它不会像Xen那样剥夺Kernel的CPU以及内存的管理权,所以Kernel尤其钟爱KVM;
KVM被作为模块加载进内核以后,内核俨然就摇身一变成为了Hypervisor,其管理方式是将运来的用户空间作为控制台,用其对KVM进行管理。包括创建、销毁、保存、迁移、配置虚拟机;每个新创建的额虚拟机作为一个进程运行在用户空间,其所拥有的虚拟CPU或虚拟内存则被抽象成为线程,如果我们想关闭一个虚拟机,则直接kill其对应的进行即可;当创建的虚拟机要执行某些特定(可以理解成普通的主机中,在陷入内核模式时所执行的命令,比如执行写操作的时候)的操作时,要通过内核中的KVM模块才能被调度执行(虚拟机会调用自己的内核空间,然后这个虚拟机内核空间在向宿主机内核中的KVM模块发起调用)。如果执行的另外一些命令(比如做一个简单的加法操作)不需要上面的特权指令的话,其所在的用户空间就可以将其直接交给CPU运行,不需要经过内核中的KVM模块调度;
KVM极其依赖HVM(硬件辅助的虚拟化),也即是说:如果你电脑的CPU不支持VT(Intel-VT-x,AMD-V)技术的话,是无法使用创建KVM虚拟机的,当然,现在的绝大多数CPU都已经支持VT功能了;
KVM使用一个设备文件/dev/kvm作为整个KVM的调用接口。/dev/kvm是一个字符设备,工作于Hypervisor(内核空间),在用户空间可通过ioctl()系统调用来完成虚拟机的创建、启动等管理功能(比如创建VM、为VM分配内存、读写VCPU的寄存器、向VCPU注入中断、运行VCPU等);也就是说,如果你编程能力好的话,完全可以通过调用这个文件来自行管理KVM,直接与内核中KVM交互;
KVM虚拟化是建立在操作系统之上的,不像Xen是直接将Hypervisor建立在硬件上;当我们创建一个KVM虚拟机之后,会在原来的操作系统之上又建立一个操作系统,这样就会导致在运来的用户空间有建立一个内核空间和用户空间。为了区分它们,我们将给他们事先定义一下:
宿主机:直接运行在物理机器上的操作系统,也就是加载KVM模块的操作系统;
Guest主机:通过KVM创建出来的虚拟机;其包含自己的Guest用户空间和Guest内核空间;
内核模式:宿主机的内核空间;
用户模式:宿主机的用户空间;一般用于代表Guest OS请求IO类操作;
KVM虚拟化的IO使用方式:
因为KVM只是一个模块,所以它根本就没有提供有关IO调用的方法,因此KVM借助了QEMU,通过它来使用IO设备。
当KVM虚拟机的用户空间要进行IO操作时,首先会将请求发送给自己的内核,然后Guest内核再向宿主机的用户空间的QEMU程序发送请求,让其为自己进行进一步的操作,最后宿主机用户空间的QEMU再对真正的内核进行请求,进而执行IO操作;
KVM的两类组件:
/dev/kvm:上面已经提到了
qemu:工作于用户空间主要用于实现模拟PC机的IO设备;
KVM的特性:
内存管理:
支持将分配给VM的内存交换至SWAP;
支持使用Huge Page(大内存页)机制;
支持使用Intel EPT或AMD RVI技术完成内存地址映射;
支持KSM(Kernel Same-Page Merging);
将多个MV加载的相同的内存页(比如相同的库文件)合并成一个,从而减少内存的占用;类似于共享内存功能;当某虚拟机要修改自己的内存页时,会通过写时复制为其创建一个副本,供其修改;
硬件管理:
取决于该Linux内核;
存储:
支持本地存储
支持网络附加存储
支持存储区域网络
支持分布式存储:GlustFS
迁移:
跨物理主机迁移,可分为热迁移和冷迁移;
冷迁移:线下迁移,关机迁移,服务中断;
热迁移:线上迁移,服务不中断,在虚拟机运行过程中,将其内存中的数据复制(复制时虚拟机会暂停)一份到另一台物理主机上,且挂载其位于共享存储中的磁盘映像文件,从而实现实时迁移,然后原先的虚拟机就可以关掉了;
设备驱动:
支持IO设备的完全虚拟化:模拟硬件
支持IO设备的半虚拟化:在Guest OS中安装驱动,类似于front-end(Guest OS提供)|backed-end(Kernel提供)机制;
常用组件为virtio,其支持块设备(virtio-blk)的半虚拟化、网络设备(virtio-net)的半虚拟化、PCI设备(virtio-pci)的半虚拟化、控制台设备(virtio-console)的半虚拟化、内存空间动态扩展机制(virtio-ballon)的半虚拟化;
KVM的局限性:
过载使用CPU时会导致性能下降,所以一般不建议虚拟CPU的数量(物理机上的所有VCPU数量)大于物理CPU的数量(此处的数量指的是核心数);
时钟不精确,这几乎时所有虚拟机的弊病,其依赖于时间同步机制(比如NTP);
MAC地址可能冲突(虚拟机数量特别多的时候才能遇到的问题);
KVM的工具栈:
QEMU组件:
主要提供了一下功能:
处理器模拟器,用于完成异构;
仿真IO设备;
管理模拟的设备至真实设备;
调试器
与模拟器交互的用户接口;
工具:
qemu-io
qemu-img
qemu-kvm:专门用于管理KVM的工具;
libvirt工具栈:支持远程管理,需要在被管理主机上运行libvirtd服务;
virsh、virt-install:字符命令行管理工具
virt-manager、virt-viewer:图形化的管理工具
创建第一个KVM虚拟机:
开启VMware的虚拟化引擎,让VMware中的虚拟机支持HVM:
~]# grep -E "(vmx|svm)" /proc/cpuinfo 查看主机是否支持虚拟化
装载KVM模块:
~]# modprobe kvm
~]# modprobe kvm-intel 这两个模块一般都是自动装载完毕的,只要加载了这两个模块,此时的Kernel俨然就成为一个Hypervisor了;可以查看一下在/dev目录下是否有kvm文件;
安装qemu-kvm工具:
~]# yum install qemu-kvm 默认安装以后qemu-kvm命令是不在PATH路径中的;
~]# ln -sv /usr/libexec/qemu-kvm /usr/bin/ 为qemu-kvm创建一个链接
格式:qemu-kvm [options] [disk_image]
Standard options:
-name:设置虚拟机的名称;
-machine:指定要模拟的主机的类型;
-m:指定虚拟机的RAM大小;
-cpu:指定CPU类型;
可以通过 ~]# qemu-kvm -cpu ? 查看支持的CPU类型;
-smp:设定虚拟的SMP架构中的CPU个数;
-numa:指定模拟多节点的numa设备;
这种模型会给每个CPU分配器一段其专用的内存,并且它们还具有一块共有内存;这样可以防止多CPU之间的内存占用问题,并且可以通过将某个进程绑定到某一CPU上,提高缓存命中率;
-boot options:用于定义设备的引导次序;
options:
order=:指定引导设备的介质类型,可用取值为:floppy (a), hard disk (c), CD-ROM (d), network (n);默认为c;
once=:指定某引导设备只是用一次,一般是安装系统时只需要指定一次的介质;
例子:-boot order=dc,once=d 表示使用光驱和硬盘引导系统,第一次优先使用光驱引导;
Block device options:
-hda/-hdb file:use 'file' as IDE hard disk 0/1 image
-hdc/-hdd file:use 'file' as IDE hard disk 2/3 image
-cdrom file:use 'file' as IDE cdrom image
Note:-cdrom与-hdc不可同时使用;
-drive options:use 'file' as a drive image,用于取代上面的-hd#;
options:选项之间使用逗号隔开;
file=:指定磁盘映像文件的路径;
if=:指定磁盘设备所连接的接口类型,即控制器类型;比如IDE、SCSI、SD、MTD、virtio等;
index=:设定同一种控制器类型中不同设备的索引号,即标识号;比如sda1、sda2;
media=:定义介质类型为硬盘(disk)还是光盘(cdrom);
snapshot=:指定当前硬盘设备是够支持快照功能;
cache=:指定如何使用物理机硬盘缓存来访问数据;可用取值:writethrough(通写)|writeback(回写)|none(不启用)|directsync|unsafe;
format=:指定映像文件的格式,具体可参见qemu-img命令;
Supported formats: vvfat vpc vmdk vhdx vdi ssh sheepdog rbd raw host_cdrom host_floppy host_device file qed qcow2 qcow parallels nbd iscsi gluster dmg tftp ftps ftp https http cloop bochs blkverify blkdebug
Network options:
用于定义网络设备接口类型以及其相关的各种属性等信息;
-net nic[,options]:为虚拟机配置网卡信息;
options:
vlan=:指定网卡属于哪个vlan中;
macaddr=:指定网卡的MAC地址;
model=:指定网卡类型;可以通过~]# qemu-kvm -net nic,model=?来查看支持的类型;
name=:指定网卡名称,一般用于monitor中;
addr=:指定网卡的IP地址,一般通过DHCP分配:
-net tap[options]:在宿主机内核上配置与虚拟机相对应的网卡(二层设备)信息;
options:
vlan=:指定网卡属于哪个vlan中;
ifname=:指定网卡名称;
script=:使用指定的脚本来配置当前的网络接口,默认为:/etc/qemu-ifup,但是这个脚本默认是没有的,需要自己写,如果是测试的话可以指定script=no;
downscript=:使用指定的脚本撤销当前的网络接口,默认为:/etc/qemu-ifdown;
-net user[,options]:用于配置用户空间的网络功能的;
例子:~]# qemu-kvm -m 128 -cpu host -smp 2 -name "test" -drive file=/root/cirros-no_cloud-0.3.0-x86_64-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic, macaddr=52:54:00:11:22:33 -net tap,ifname=vif0.0
Display options:
-sdl:跨平台且开源的多媒体程序库文件;
-spice:启用spice远程桌面协议;
-vnc display options:启用vnc功能,指定qemu监听在VNC的某一接口上;
display格式:
1.host:Num
这里的Num是以5900为基础,一次递增的;
例子:192.168.80.134:0,192.168.80.137:1,其中冒号后面的0|1表示桌面号;
2.unix:/path/to/socket_file 仅用于本机
3.none
options:
password:连接是需要验证的密码,在monitor接口上使用change设定密码;
reverse:反向连接至某处于监听状态的vncview上;
-vga [std|cirrus|vmware|qxl|xenfb|none]:指定要仿真的VGA接口类型;
Debug/Expert options:
-monitor dev:表示在标准输入输出上显示monitor界面;
例子:~]# qemu-kvm -m 128 -smp 2 -name "test" -hda cirros-no_cloud-0.3.0-x86_64-disk.img -vnc 192.168.80.134:0 -monitor stdio
-nographic:直接在控制台上启动命令接口;
使用Ctrl + a --> c可以在console和monitor之间切换;
下载共有映像文件:
这个映像文件就是一个装好的操作系统,直接加载使用即可;我使用的是cirros-no_cloud-0.3.0-x86_64-disk.img;
安装VNC组件:需要安装桌面环境(yum groups install "GNOME Desktop"-->reboot)
~]# yum install tigervnc.x86_64
启动虚拟机:
~]# qemu-kvm -m 128 -smp 2 -name "test" -hda cirros-no_cloud-0.3.0-x86_64-disk.img
~]# vncviewer :5900 使用VNC链接虚拟机,此处的5900接口是虚拟机test所监听的接口,如果有第二个虚拟机,则端口号会一次递增为5901;
Note:使用Ctrl + Alt + num可以切换到其他窗口
Note:上图中-drive的顺序尤为重要,如果有-boot选项的话,关于iso的drive要放在其后;
KVM-Virtio及管理工具
基础框架:
Note:使用Virtio以后虚拟机中的驱动会显示为相应的Virtio设备(比如virtio_net、virtio_pci等);
virsh、virt-manager、virt-install、libvirtd、libvirt
其中libvirt是一个库文件,可以为虚拟化管理提供各种接口;libvirtd是一个运行在各个支持虚拟化主机上的服务,支持远程管理虚拟机,类似客户端代理,可以执行管理端发来的命令;virsh是基于libvirt的虚拟机命令行管理工具,virt-manager是基于libvirt的虚拟机图形管理工具,virt-install是用于创建虚拟机的工具;一般virt-install会与virsh配合使用;
安装及启动服务:
~]# yum install libvirt-client virt-manager libvirt-daemon virt-install qemu-kvm
~]# systemctl start libvirtd.service
~]# virt-manager
图形化界面,类似Vmware!
默认创建的虚拟机镜像文件存储位置:/var/lib/libvirt/images/
相关命令:
virsh:选项特别多;
~]# virsh help
~]# virsh help interface
~]# virsh help iface-bridge
根据XML文件创建:
create:创建并启动虚拟机;
define:创建但不启动虚拟机;
关闭domain:
destory:强制关闭虚拟机
shutdown:将虚拟机关机
reboot:重启虚拟机
删除虚拟机:
undefine:删除虚拟机
连接至console:
console:连接虚拟机控制台;
附加或拆除磁盘:
attach-disk:为虚拟机附加一个磁盘;
detach-disk:拆除虚拟机上的磁盘;
附加或查出网卡接口:
attach-interface:为虚拟机添加一个网卡接口;
detach-interface:拆除虚拟机上的网卡接口;
保存及恢复虚拟机状态至磁盘文件:
save:保存虚拟机状态至磁盘文件;
restore:恢复虚拟机状态至磁盘文件;
virt-install:
格式:virt-install [options]
options:
General Options:
-n NAME:指定虚拟机名称,全局唯一;
-r MEMORY:指定虚拟机的内存大小,默认单位为MB;
--vcpus [maxcpus=n][,cpuset=][,sockets=n][,cores=n][,threads=n]:指定虚拟机中vcpu的数量;
通过~]# virt-install --vcpus help获取更多参数信息
--cpu CPU Module:指定CPU的模式及特性
Installation Method Options:
-c CDROM,--cdrom=CDROM:使用光盘安装;
-l LOCATION,--location=LOCATION:指定安装源的URL,支持FTP、HTTP等;
--pxe:基于PXE安装;
--livecd:把光盘当做LiveCD;
--os-type=DISTRO_TYPE:指定安装的系统类型;比如linux、Windows等;
--os-variant=DISTRO_VARIANT:指定要安装的操作系统的distribution;比如centos6、redhat7等;
-x EXTRA,--extra-args=EXTRA:根据--location指定的方式安装Guest OS时,用于传递给内核额外选项;例如指定kickstart文件的位置,--extra-args "ks=http://192.168.80.128/Centos6_install.cfg"
--boot =BOOTOPTS:指定安装过程完成后的配置选项,比如指定引导设备次序、使用指定的而非安装的kernel/initrd来引导系统启动;
例子:--boot cdrom,hd,network
--boot kernel=KERNEL,initrd=INITRD,kernel_args="console=/dev/ttyS0"
Device Options:
--disk=DISKOPTS:指定存储设备及其属性;
格式为:--disk /some/storage/path,opt1=val1,opt2=val2;
常用选项:
device:设备类型,如cdrom、disk等,默认为disk;
bus:磁盘总线类型,其值可以为ide、scsi、bus、virtio等;
perms:访问权限,如rw、ro或sh(共享的可读写),默认为rw;
size:新建磁盘映像的大小,单位为GB;
cache:缓存模型,其值有none、writeback、writethrough;
format:磁盘映像格式,如raw、qcow2、vmdk等;
sparse:指定磁盘映像使用稀疏格式,即不立即分配指定大小的空间;
--nodisks:不使用本地磁盘,在LiveCD模式中常用;
-w NETWORK,--network=NETWORK:将虚拟机连入宿主机的网络中;
格式:--network=NETWORK,opt1=val1,opt2=val2
options:
bridge=BRIDGE:连接至名为"BRIDGE"的桥设备;
network=NAME:连接至名为"NAME"的网络;
model:指定Guest OS中看到的网络设备型号,如e1000、virtio等;
mac:指定固定的MAC地址;不指定则使用随机地址,但是对KVM来说前三段固定为52:54:00;
--nonetworks:虚拟机不使用网络模型;
--graphics TYPE,opt1=val1,opt2=val2:指定图形显示相关的配置,此选项不会配置任何显示硬件,而是指虚拟机启动后对其进行访问的接口;
TYPE:指定显示类型,比如VNC、sdl、spice或nooe等,默认为VNC;
port:当TYPE为VNC或spice时,为其指定的监听端口;
listen:当TYPE为VNC或spice时,为其指定的监听地址;默认为127.0.0.1,可以通过/etc/libvirt/qemu.conf进行修改;
--serial=CHAROPTS:附加一个串行设备到当前虚拟机;
--serial pty:创建伪终端;
--serial dev,path=HOSTPATH:附加主机设备至此虚拟机;
Virtualization Platform Options:
-v,--hvm:当虚拟机同时支持使用半虚拟化和完全虚拟化时,指定使用完全虚拟化;
-p,--paravirt:指定使用半虚拟化;
--virt-type:指定使用的Hypervisor类型,比如kvm、xen、qemu等;
Miscellaneous Options:
--print-xml:不创建虚拟机,仅打印XML配置文件的内容;
--force:禁止进入交互模式,需要回答yes或no的默认回答为yes
--dry-run:dry-run模式;
例子:~]# virt-install --name centos6.1 --virt-type kvm --ram 512 --graphics vnc --cdrom /root/CentOS-6.10-x86_64-bin-DVD1.iso --disk path=/images/kvm/centos6.img,size=20
关于Virtio的不错的文章:https://www.cnblogs.com/bakari/p/8309638.html
根据马哥视频做的学习笔记,如有错误欢迎指正;侵删