KVM(第51天)

 KVM:Kernel-based Virtual Machine 基于内核的虚拟机,依赖于HVM(比如intel VT-x, amd ADM-V),KVM寄宿于内核中。所以,把加载KVM模块的内核称之为Hypervisor,由此可知该Hypervisor直接运行于硬件平台之上,内核之上的用户空间还是原来的用户空间。创建出来的虚拟机运行于Hypervisor之上,有自己的内核和用户空间

KVM加载后的系统的运行模式:

内核模式:执行GuestOS的IO类操作,或者其他的特殊指令的操作,称为来宾的内核模式

来宾模式:执行GuestOS的非IO类操作,称为来宾的用户模式

用户模式:代表GuestOS请求IO类操作

KVM Hypervisor:加载KVM模块的内核


KVM的组件:

/dev/kvm:工作于Hypervisor,在用户空间可通过ioctl()系统调用来完成VM创建,启动管理功能,他是一个字符设备,功能包括为VM分配内存,读写VCPU的寄存器,向VCPU注入中断,运行VCPU等等

qemu进程:工作于用户空间,kvm需要借助qemu模拟IO设备


KVM的特性:

内存管理:

    支持将分配给VM的内存交换至SWAP

    支持使用Huge Page

    支持使用INTEL EPT和AMD RVI技术完成内存地址的映射:Guest虚拟地址到guest物理地址到宿主机物理地址

    支持KSM(Kernel Same-page Merging)


KVM继承了Linux系统管理内存的诸多特性,比如,分配给虚拟使用的内存可以被交换至交换空间、能够使用大内存页以实现更好的性能,以及对NUMA的支持能够让虚拟机高效访问更大的内存空间等。

KVM基于Intel的EPT(Extended Page Table)或AMD的RVI(Rapid Virtualization Indexing)技术可以支持更新的内存虚拟功能,这可以降低CPU的占用率,并提供较好的吞吐量。

此外,KVM还借助于KSM(Kernel Same-page Merging)这个内核特性实现了内存页面共享。KSM通过扫描每个虚拟机的内存查找各虚拟机间相同的内存页,并将这些内存页合并为一个被各相关虚拟机共享的单独页面。在某虚拟机试图修改此页面中的数据时,KSM会重新为其提供一个新的页面副本。实践中,运行于同一台物理主机上的具有相同GuestOS的虚拟机之间出现相同内存页面的概率是很的,比如共享库、内核或其它内存对象等都有可能表现为相同的内存页,因此,KSM技术可以降低内存占用进而提高整体性能。


硬件支持:

    取决于Linux内核


存储:

    支持本地存储

    支持网络附加存储

    支持存储区域网络

    支持分布式存储:例如GlustFS


实施迁移:从一个hypervisor迁移到另一个hypervisor


支持的GuestOS:

    Linux,Windows, OpenBSD,FreeBSD,OpenSolaris;


设备驱动:

    支持模拟IO设备来完全虚拟设备

    支持IO设备的半虚拟化,需要在GuestOS中安装驱动程序,把IO设备分成两段式,一半在GuestOS上,另外一半在Hypervisor上;比如virtio,virtio-blk,virtio-net,virtio-pci,virtio-console,virtio-ballon


KVM局限性:

过载使用CPU(overcommit)

事件记录难以精确,依赖于时间同步机制

MAC地址冲突,VM数量大可能冲突

实时迁移

性能局限性


KVM的管理工具:qemu和libvirt





qemu:qemu本身是模拟器,可以模拟所有硬件完成完全虚拟化

    qemu-kvm

    qemu-img 


libvirt:

    GUI:virt-manager,virt-viewer

    CLI: virt-install, virsh


qemu包括以下部分:

处理器模拟器

仿真IO设备

关联模拟的设备至真实设备

调试器

与模拟器交互的用户接口


使用KVM:

grep -E --color=auto "(vmx|svm)" /proc/cpuinfo    查看是否支持HVM,vmx是intel cpu,svm是amd cpu

modprobe kvm           加载kvm模块

modprobe  kvm_intel  加载kvm_intel模块

ls /dev/kvm    查看 是否有/dev/kvm文件


yum install qemu-kvm  安装qemu-kvm,默认放在/usr/libexec/目录下

ln -sv  /usr/libexec/qemu-kvm  /usr/bin/qemu-kvm   在/usr/bin/ 目录下创建链接,即可直接使用qemu-kvm命令  


qemu-kvm -h   查看帮助信息

qemu-img -h 查看帮助信息,qemu-img用于创建磁盘镜像文件,虚拟机可以直接导入使用。支持的格式有:blkdebug blklogwrites blkverify compress copy-before-write copy-on-read file ftp ftps gluster host_cdrom host_device http https iscsi iser luks nbd null-aio null-co nvme preallocate qcow2 quorum raw rbd ssh throttle vhdx vmdk vpc


cirros :https://download.cirros-cloud.net/  

             https://download.cirros-cloud.net/0.6.0/cirros-0.6.0-x86_64-disk.img

下面示例使用该磁盘镜像文件来启动虚拟机。

cd /root 

wget -c  https://download.cirros-cloud.net/0.6.0/cirros-0.6.0-x86_64-disk.img


启动一个虚拟机命令如下:内存使用128m,基于cirros镜像文件,默认基于vnc启动,监听在本机127.0.0.1:5900

qemu-kvm -m 128m -smp 2 -name 'myos' -hda /root/cirros-0.6.0-x86_64-disk.img


安装vnc客户端:通过vnc客户端连接上去操作虚拟机myos,命令如下:

yum install tigervnc  

vncviewer  :5900   使用vncviewer  连接到5900端口

进入之后,ctrl+alt+2切换    ctrl+alt+1  


启动虚拟机:用-drive指定磁盘映像文件,使用virtio(半虚拟化)

qemu-kvm -m 128 -name 'test' -smp 2 -drive file=/root/cirros-0.6.0-x86_64-disk.img,if=virtio,media=disk,cache=writeback,format=qcow2


qemu-kvm命令

qemu-kvm命令使用格式为“qemu-kvm  [options]  [disk_image]”,其选项非常多,不过,大致可分为如下几类。

标准选项;
USB选项;
显示选项;
i386平台专用选项;
网络选项;
字符设备选项;
蓝牙相关选项;
Linux系统引导专用选项;
调试/专家模式选项;
PowerPC专用选项;
Sparc32专用选项;


考虑到篇幅及使用需要,这里介绍的选项主要涉及到标准选项、显示选项、i386平台专用选项及Linux系统引导专用选项等相关的选项。


qemu-kvm的标准选项主要涉及指定主机类型、CPU模式、NUMA、软驱设备、光驱设备及硬件设备等。

-name name:设定虚拟机名称;

-M machine:指定要模拟哪种类型,如Standard PC、ISA-only PC或Intel-Mac等,可以使用“qemu-kvm -M ?”获取所支持的所有类型;

-m megs:设定虚拟机的RAM大小;

-cpu model:设定模拟哪种CPU模型,如coreduo、qemu64等,可以使用“qemu-kvm -cpu ?”获取所支持的所有模型; 例如  -cpu host 表示模拟宿主机的cpu

-smp n[,cores=cores][,threads=threads][,sockets=sockets][,maxcpus=maxcpus]:设定模拟的SMP架构中CPU的个数等、每个CPU的核心数及CPU的socket数目等;PC机上最多可以模拟255颗CPU;maxcpus用于指定热插入的CPU个数上限;

-numa opts:指定模拟多节点的numa设备;

-fda file

-fdb file:使用指定文件(file)作为软盘镜像,file为/dev/fd0表示使用物理软驱;

-hda file

-hdb file

-hdc file

-hdd file:使用指定file作为硬盘镜像;

-cdrom file:使用指定file作为CD-ROM镜像,需要注意的是-cdrom和-hdc不能同时使用;将file指定为/dev/cdrom可以直接使用物理光驱;

-drive option[,option[,option[,...]]]:定义一个硬盘设备;可用子选项有很多。

file=/path/to/somefile:硬件映像文件路径;

if=interface:指定硬盘设备所连接的接口类型,即控制器类型,如ide、sd、mtd、floppy、pflash及virtio等;

index=index:设定同一种控制器类型中不同设备的索引号,即标识号;

media=media:定义介质类型为硬盘(disk)还是光盘(cdrom);

snapshot=snapshot:指定当前硬盘设备是否支持快照功能:on或off;

cache=cache:定义如何使用物理机缓存来访问块数据,其可用值有none、writeback、unsafe和writethrough(每一层都写一遍)四个;

format=format:指定映像文件的格式,具体格式可参见qemu-img命令;

-boot [order=drives][,once=drives][,menu=on|off]:定义启动设备的引导次序,每种设备使用一个字符表示;不同的架构所支持的设备及其表示字符不尽相同,在x86 PC架构上,a、b表示软驱、c表示第一块硬盘,d表示第一个光驱设备,n-p表示网络适配器;默认为硬盘设备;

-boot order=dc,once=d   order表示顺序,once表示仅第一次启动会使用


-usbdevice devname

            devname 取值有tablet等



举个粒子:

做一个虚拟机安装windows xp

mkdir -pv /root/images/winxp

cd  /root/images/winxp

创建磁盘镜像文件winxp.qcow2 :格式qcow2

qemu-img  create  -f qcow2  /root/images/winxp/winxp.qcow2  -o size=5G,preallocation=metadata

下一步把winxp安装到这个磁盘镜像文件里 此处/root/windows_xp.iso是我的操作系统镜像文件,你们自己找一个windows xp操作系统,启动虚拟机如下:

qemu-kvm -m 512 -smp 2 -cpu host -usbdevice tablet -drive file=/root/images/winxp/winxp.qcow2,media=disk  -drive file=/root/windows_xp.iso,media=cdrom -boot order=dc,once=d


使用vncview  :5900 连接上去操作





qemu-kvm的显示选项

显示选项用于定义虚拟机启动后的显示接口相关类型及属性等。

一般使用-vnc,或者-nogriphic,具体如下:

-nographic:默认情况下,qemu使用SDL来显示VGA输出;而此选项用于禁止图形接口,此时,qemu类似一个简单的命令行程序,其仿真串口设备将被重定向到控制台;

-curses:禁止图形接口,并使用curses/ncurses作为交互接口;

-alt-grab:使用Ctrl+Alt+Shift组合键释放鼠标;

-ctrl-grab:使用右Ctrl键释放鼠标;

-sdl:启用SDL;

-spice option[,option[,...]]:启用spice远程桌面协议;其有许多子选项,具体请参照qemu-kvm的手册;

-vga type:指定要仿真的VGA接口类型,常见类型有:

cirrus:Cirrus Logic GD5446显示卡;

std:带有Bochs VBI扩展的标准VGA显示卡;

vmware:VMWare SVGA-II兼容的显示适配器;

qxl:QXL半虚拟化显示卡;与VGA兼容;在Guest中安装qxl驱动后能以很好的方式工作,在使用spice协议时推荐使用此类型;

none:禁用VGA卡;

-vnc display[,option[,option[,...]]]:默认情况下,qemu使用SDL显示VGA输出;使用-vnc选项,可以让qemu监听在VNC上,并将VGA输出重定向至VNC会话;使用此选项时,必须使用-k选项指定键盘布局类型;其有许多子选项,具体请参照qemu-kvm的手册;


display:

(1)host:N

172.16.100.7:1, 监听于172.16.100.7主的5900+N的端口上

(2) unix:/path/to/socket_file

(3) none


options:

password: 连接时需要验正密码;设定密码可以通过monitor接口使用change vnc password

reverse: “反向”连接至某处于监听状态的vncview上;


-monitor stdio:表示在标准输入输出上显示monitor界面

-nographic

Ctrl-a, c: 在虚拟机的console和monitor之间切换

Ctrl-a, h: 显示帮助信息



qemu-kvm的i386平台专用选项

-no-acpi:禁用ACPI功能,GuestOS与ACPI出现兼容问题时使用此选项;

-balloon none:禁用balloon设备;

-balloon virtio[,addr=addr]:启用virtio balloon设备;



使用qemu-vm的网络属性之前的补充材料:

补充资料:TUN与TAP

在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备。不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行于操作系统上的软件提供与硬件的网络设备完全相同的功能。

TAP等同于一个以太网设备,它操作第二层数据包如以太网数据帧。TUN模拟了网络层设备,操作第三层数据包比如IP数据封包。

操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序也可以像操作硬件网络设备那样,通过TUN/TAP设备发送数据。在后种情况下,TUN/TAP设备向操作系统的网络栈投递(或“注入”)数据包,从而模拟从外部接受数据的过程。

以上材料有助于理解qemu-kvm   -net tap选项


qemu-kvm的网络属性相关选项

给虚拟机添加网络设备,使之可以连接外部网络或者外部网络可以连接至虚拟机中


网络属性相关选项用于定义网络设备接口类型及其相关的各属性等信息。这里只介绍nic、tap和user三种类型网络接口的属性,其它类型请参照qemu-kvm手册。

这里的nic表示虚拟机网卡的前半部分(在虚拟机里一般显示eth0),tap表示虚拟机网卡的后半部分

-net nic[,vlan=n][,macaddr=mac][,model=type][,name=name][,addr=addr][,vectors=v]:创建一个新的网卡设备并连接至vlan n中;PC架构上默认的NIC为e1000,macaddr用于为其指定MAC地址,MAC地址最好指定一下(mac地址中的52:54:00表示qemu厂商标识符),name用于指定一个在监控时显示的网上设备名称;qemu可以模拟多个类型的网卡设备,如virtio、i82551、i82557b、i82559er、ne2k_isa、pcnet、rtl8139、e1000、smc91c111、lance及mcf_fec等;不过,不同平台架构上,其支持的类型可能只包含前述列表的一部分,可以使用“qemu-kvm -net nic,model=?”来获取当前平台支持的类型;

-net tap[,vlan=n][,name=name][,fd=h][,ifname=name][,script=file][,downscript=dfile]:创建虚拟机网卡的后半段,ifname指定该后半段接口的名称,通过物理机的TAP网络接口连接至vlan n中,使用script=file指定的脚本(默认为/etc/qemu-ifup)来配置当前网络接口,并使用downscript=file指定的脚本(默认为/etc/qemu-ifdown)来撤消接口配置;使用script=no和downscript=no可分别用来禁止执行脚本;(脚本要自己写,自己定制)

写脚本让虚拟机的后半段也就是tap这一段加入桥设备的简单示例如下:

cat <<EOF > /etc/qemu-ifup

#!/bin/bash

bridge=br0   #必须先在该宿主机上虚拟出来一个桥设备br0

if [ -n "$1" ];then   #这里的是$1表示脚本的第一个参数,qemu-kvm会使用-net tap里创建的虚拟机网卡的后半段传递给$1,所以qemu-kvm自动传递的,不需显示调用

    ip link set $1 up  #激活虚拟机网卡的后半段

    sleep 1

    brctl addif $bridge $1  #把虚拟机网卡的后半段添加到桥设备上

    [ $? -eq 0 ] && exit 0 || exit 1

else

    echo "Error: no interface specified!!!"

    exit 1

fi

EOF


关闭脚本示例如下:

cat <<EOF > /etc/qemu-ifdown

#!/bin/bash

bridge=br0

if [ -n "$1" ]; then

    brctl delif $bridge $1

    ip link set $1 down

    exit 0

else

    echo "Error:  no interface specified!!!"

fi

EOF


举一个栗子来吧上面的qemu-kvm过一遍:前提是宿主机上添加了桥设备br0(brctl addbr br0 ),并且准备好了/etc/qemu-ifup脚本来定制某些工作,chmod +x /etc/qemu-ifup 给脚本赋予执行权限,定制的工作如上文脚本内容所示:

做好上面的工作之后启动虚拟机:

qemu-kvm -m 128m -cpu host -smp 2 -name 'myos' -drive file="/root/cirros-0.6.0-x86_64-disk.img",if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic,macaddr=52:54:00:23:23:22-net tap,ifname=vif0.0,script=/etc/qemu-ifup

启动完成该虚拟机之后,在宿主机中使用ifconfig命令可以可以看到vif0.0作为虚拟机的网卡的后半段出现在宿主机中,使用brctl show 可以看到vif0.0被添加到br0桥设备上。


再启动一个虚拟机:记得要指定一个mac地址给虚拟机的网卡设备,注意粗体和上一个虚拟机的不同

qemu-kvm -m 128m -cpu host -smp 2 -name 'myos1' -drive file="/root/cirros-0.5.2-x86_64-disk.img",if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic,macaddr=52:54:00:23:23:21 -net tap,ifname=vif1.0,script=/etc/qemu-ifup



-net user[,option][,option][,...]:在用户模式配置网络栈,其不依赖于管理权限;有效选项有:

vlan=n:连接至vlan n,默认n=0;

name=name:指定接口的显示名称,常用于监控模式中;

net=addr[/mask]:设定GuestOS可见的IP网络,掩码可选,默认为10.0.2.0/8;

host=addr:指定GuestOS中看到的物理机的IP地址,默认为指定网络中的第二个,即x.x.x.2;

dhcpstart=addr:指定DHCP服务地址池中16个地址的起始IP,默认为第16个至第31个,即x.x.x.16-x.x.x.31;

dns=addr:指定GuestOS可见的dns服务器地址;默认为GuestOS网络中的第三个地址,即x.x.x.3;

tftp=dir:激活内置的tftp服务器,并使用指定的dir作为tftp服务器的默认根目录;

bootfile=file:BOOTP文件名称,用于实现网络引导GuestOS;如:qemu -hda linux.img -boot n -net user,tftp=/tftpserver/pub,bootfile=/pxelinux.0


brctl addbr br0

brctl addif br0 eth0


brctl addbr br1



KVM的网络模型之隔离模型:

隔离模型解释:Guest1表示虚拟机1,Guest2表示虚拟机2,它们各自有自己的网卡eth0,在宿主机上虚拟出一个网桥设备,或者交换机,在交换机上虚拟两个网卡,vnet0和vnet1,分别连接Guest1的eth0,Guest2的eth0。可以把vnet0理解成Guest1上的eth0网卡的后半段,把vnet1理解成Guest2上的eth0网卡的后半段。如此一来,两个虚拟机就可以互相通信,但是不能和外部通信。这种情况类似于vmware的虚拟通道。


KVM网络模型之路由模型:

解释:在隔离模型的基础上,在宿主机上虚拟出一个虚拟网卡vimnet1,并连接至交换机上。Guest1和Guest2等虚拟机的网关指向vimnet1的地址。打开宿主机的路由转发功能。如此一来,Guest1很Guest2就能发出报文,但是外部主机无法回应报文,非常不好使。


KVM网络模型之NAT模型:地址转换模型





NAT模型解释:在路由模型的基础上,从Guest1和Guest2发出的报文,做源地址转换(SNAT)。宿主机接收到数据的时候做目标地址转换(DNAT),把数据的目标地址转换为相应的Guest地址,才可以将数据转发到相应的Guest上。(SNAT和DNAT的功能就是添加iptables规则)。

这种模型就类似于vmware中的VMnet8,VMnet8就是vmware创建出来的虚拟桥设备。



KVM网络模型之桥接模型:


桥接模型解释:在宿主机上虚拟出一个桥设备br0,把宿主机上的物理网卡eth0连接到桥设备上。如此一来,通过Guest1的eth0发出的数据就可以通过桥设备上的宿主机的eth0出去。

具体做法是:把宿主机的物理网卡eth0的ip地址卸掉,该网卡添加到br0桥上,最后br0桥的ip地址设置为宿主机物理网卡eth0的ip地址

ifconfig eth0 0  up  卸掉宿主机的物理网卡eth0的ip地址,centos可能是eno****或者ens***

brctl addif br0 eth0  网卡添加到br0桥上

ifconfig br0 192.168.32.130 up  桥的ip地址设置为宿主机物理网卡eth0的ip地址




如何在linux上创建桥设备,使用桥设备:

内核提供了bridge模块:可以使用如下命令查看:

modinfo  bridge 

使用bridge-utils工具可以调用bridge模块创建桥设备:安装命令如下:

yum install bridge-utils  -y

安装完毕之后使用brctl --help 查看帮助信息


brctl addbr br0   虚拟出一个br0桥设备

brctl stp br0 off   关闭桥的生成树协议

brctl show 查看所有的桥设备,可以看到有多少设备关联上桥设备

ifconfig br0 up   激活桥设备 




下面的命令创建了一个名为rhel5.8的虚拟机,其RAM大小为512MB,有两颗CPU的SMP架构,默认引导设备为硬盘,有一个硬盘设备和一个光驱设备,网络接口类型为virtio,VGA模式为cirrus,并启用了balloon功能。


# qemu-kvm -name "rhel5.8" -m 512 \

-smp 2 -boot d \

-drive file=/VM/images/rhel5.8/hda,if=virtio,index=0,media=disk,format=qcow2 \

-drive file=/isos/rhel-5.8.iso,index=1,media=cdrom \

-net nic,model=virtio,macaddr=52:54:00:A5:41:1E \

-vga cirrus -balloon virtio

需要注意的是,上述命令中使用的硬盘映像文件/VM/images/rhel5.8/hda需要事先使用qemu-img命令创建。











qemu-kvm的半虚拟化:


磁盘,网络设备,pci设备,ballon设备,console等都可以实现半虚拟化。

IO半虚拟化分成两段:

前端驱动(也就是virtio前半段存在于虚拟机实例中):有:virtio-blk, virtio-net, virtio-pci, virtio-balloon, virtio-console,CentOS4.8+以上都支持,windows需要安装额外驱动程序

上图中的virtio表示队列

transport表示传输层

后端处理程序(virtio backed drivers)在qemu中实现


virtio-balloon:让vm运行中的GuestOS动态调整其内存大小

用法  qemu-kvm -balloon virtio 

手动查看GuestOS的内存用量:

info balloon

balloon N


virtio-net:其依赖于GuestOS中的前端,以及qemu中的后端驱动

GuestOS里有virtio_net.ko

QEMU用法  qemu-kvm -net nic,modle=virtio

vhost-net:用于取代工作于用户空间的qemu中为virtio-net实现的后端驱动来实现性能提升的另外一个驱动:-net tap[,vnet_hdr=on|off][,vhost=on|off]

用法  qemu-kvm -net tap,vnet_hdr=on,vhost=on



virtio-blk:其依赖于GuestOS中的驱动,以及qemu中的后端驱动

-drive file=/path/to/some_image_file, if=virtio



kvm_clock:半虚拟化的时钟

查看是否支持半虚拟化的时钟

cat /boot/config-4.18.0-408.el8.x86_64 | grep -i paravirt





虚拟机的迁移

迁移






    















评论

此博客中的热门博文

OAuth 2教程

网格策略

apt-get详细使用