KVM环境构建
硬件系统配置上,CPU要支持Intel VT-x/EPT或AMD-V/VRI
宿主机操作系统:CentOS7.9
KVM模块:modprobe kvm ,modprobe kvm-amd
安装qemu-kvm:yum install qemu-kvm
管理工具栈使用,包括了qemu-kvm和libvirt
qemu-kvm :创建一个链接到/usr/bin下,这样可以直接使用命令:
ln -sv /usr/libexec/qemu-kvm /usr/bin/qemu-kvm
语法:qemu-kvm options disk_image
命令选项:
标准选项-Standard options;
显示选项-Display options;
块设备选项-Block device options;
网络选项-Network options;
i386平台专用选项-i386 target only;
字符设备选项-Character device options;
USB设备选项;
Linux启动专用选项-Linux/Multiboot boot specific;
调试/专家模式选项-Debug/Expert options;
qemu-img:虚拟磁盘映像管理工具,一般产生的磁盘文件是稀疏类型,即创建100G的磁盘映像文件,最开始可能只是几兆或几十兆。
qemu-kvm 的具体使用:
启动第一个虚拟机,先使用已经做好的磁盘映像,这里下载cirros镜像文件。Cirros是一个超轻量级的Linux测试镜像,专门用来验证云平台(如OpenStack、KVM)是否正常工作。下载cirros-0.3.6-x86_64-disk.img。cirros最新版本是0.6.x。
使用qemu-img工具可以查看下载的磁盘镜像文件的信息:
qemu-img info /images/kvm/cirros-0.3.6-x86_64-disk.img
对CentOS6和7,因为qemu-img的版本不同,支持的格式也不同:
CentOS6中:

CentOS7中:

qcow2本身也有不同版本,不同的qemu-img对应着不同的qcow2。
qemu-kvm -m 128 -smp 2 -name testcirros -hda /images/kvm/cirros-0.3.6-x86_64-disk.img

参数说明:
-m:指定虚拟机的内存大小;
-smp:指定虚拟机的CPU数量;
-name:虚拟机的名称;
-hda:指定虚拟机使用的磁盘为IDE接口类型的硬盘,这是一个比较传统的用法,现在一般使用-drive指定,能够设置更丰富的特性;
虚拟机已经启动,但是是基于VNC的方式,想要查看虚拟机,需要使用vnc连接到vnc控制台上。
查看监控端口:

VNC只是监控在本地接口上,即localhost上,也就是只能从本地连接到VNC控制台上。
对于CentOS6,默认的qemu版本是QEMU PC emulator version 0.12.1,在CentOS7上,是QEMU emulator version 1.5.3 。在CentOS7.9上运行上述命令,启动虚拟机时,提示:

CentOS7.9中软件包qemu-kvm安装后,有两个bios文件,/usr/share/qemu-kvm/bios-256k.bin和/usr/share/qemu-kvm/bios.bin,试着加载bios.bin,成功。

qemu-kvm命令中使用-bios指定加载特定的bios。
bios-256k.bin是 QEMU/SeaBIOS 中特指256KB 容量截断版的 PC BIOS 镜像(仅含核心引导代码),而bios.bin通常是 SeaBIOS 编译生成的完整默认镜像(含完整硬件初始化与扩展支持);两者内容主体一致,但文件大小、包含模块及适用场景不同 。
那么,在本地安装一个VNC客户端:tigervnc
yum install tigervnc
CentOS6下,安装的是1.1.0版,CentOS7下,安装的是1.8.0,安装后,会安装一个/usr/bin/vncviewer,使用这个程序连接
vncviewer :5900
不幸的是,出现错误:vncviewer: unable to open display ""

CentOS6,安装:
yum groupinstall "X Window System"
yum groupinstall "Desktop"
重新启动后,运行虚拟机,然后vncviewer连接:

然后安装了XmanagerPowerSuite-7,使用这个版本的xshell

弹出窗口,显示登录信息,使用cirros用户,密码为cubswin:)
使用CTRL+ALT+1或2,可以在虚拟机界面和管理控制台界面切换,如CTRL+ALT+2,

可以使用Info命令查看虚拟机的各种信息:

CentOS7.9中,安装:yum groupinstall "X Window System",那么启动vncviewer是,就能弹出显示窗口。

在HostOS中,可以通过kill命令关系虚拟机。
启动虚拟机时,使用-drive指定磁盘映像文件:
qemu-kvm -m 128 -smp 2 -name test -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback,format=qcow2
这里使用了-drive指定磁盘,其有多个设置项:
file:指定磁盘对应的磁盘镜像文件;
if:网络接口类型,virtio是使用半虚拟化技术,能大大提升IO的性能,kvm一般使用virtio;
media:当前磁盘的类型,disk,就是硬盘,cdrom,是光盘,等等;
cache:缓存的设置,writeback是回写机制;
format:磁盘映像文件的格式;
通过cdrom启动windows的安装:
qemu-kvm -name win7 -m 512 -smp 2,,sockets=1,cores=2,threads=2 -drive file=/images/kvm/win7.img,if=ide,media=disk,cache=writeback,format=qcow2 -drive file=/root/win7_ghost.iso,media=cdrom
使用qemu-kvm管理kvm虚拟机。
标准选项参数说明 :
-cpu model:设定cpu模型,如core2duo,qemu64,可以使用qemu-kvm -cpu ?获取所支持的所有cpu模型,host指定cpu使用宿主机,即物理机的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、scsi、sd、mtd、floppy、pflash及virtio等;
index=index:设定同一种控制器类型中不同设备的索引号,即标识号;
media=media:定义介质类型为硬盘(disk)还是光盘(cdrom);
snapshot=snapshot:指定当前硬盘设备是否支持快照功能,on或off;
cache=cache:定义如何使用物理机缓存来访问块数据,其可用值有none、writeback、unsafe和writethrough;
format=format:定义映像文件的格式;
-boot order=drives,once=drives,menu=on\|off:定义启动设备的引导次序,每种设备使用一个字符表示:不同的架构所支持的设备及其表示字符不尽相同,在x86PC架构上,a、b表示软驱,c表示第一块硬盘,d表示第一个光驱设备,n-p表示网络适配器,默认为硬盘设备;once表示只有首次启动时,才有效。如下面配置,就是说首次启动时才使用光驱引导,此后将使用硬盘。
-boot order=dc,once=d
安装windows操作:
下载安装光盘镜像:win7_pro.iso
创建磁盘映像文件:qemu-img create -o size=80G,preallocation=metadata -f qcow2 /images/kvm/win7.img

启动虚拟机并引导安装:
qemu-kvm -name win7 -m 1024 -cpu host -smp 2 -drive file=/images/kvm/win7.img,media=disk -drive file=/root/WIN7_PRO.iso,media=cdrom -boot order=dc,once=d -bios /usr/share/qemu-kvm/bios.bin

vncviewer :5900


显示选项参数说明 :显示选项用于定义虚拟机启动后的显示接口相关类型及属性等
-nographic:默认情况下,qemu使用SDL来显示VGA输出,而此选项用于禁止图形接口,此时,qemu类似一个简单的命令行程序,其仿真串口设备将被重定向到控制台;
-sdl:启用SDL ------ Simple DirectMedia Layer,跨平台且开源的多媒体程序库文件;
-vga type:指定要仿真的VGA接口类型,常见类型有:
cirrus:Cirrus Logic GD5446显示卡;
std:带有Bochs VBI扩展的标准VGA显示卡;
vmware:VMWare SVGA-II兼容的显示适配器;
qxl:QXL半虚拟化显卡,与VGA兼容。
none:禁用VGA显卡;
-vnc display,option\[,option\[,...]]]:默认情况下,qemu使用SDL显示VGA输出(红帽给成了默认VNC),使用-vnc选项,可以让qemu监听在VNC上,并将VGA输出重定向至VNC会话,使用此选项时,必须使用-k选项指定键盘布局类型;
display:
1)host:N 如192.168.147.1:1,监听于192.168.147.1主机的5900+N的端口上;
2)unix:/path/to/socket_file
3)none
option:
password:连接时需要验证密码,设定密码通过monitor接口使用change命令修改获得
reverse:"反向"连接至某处于监听状态的vncview上;
-monitor stdio:表示在标准输入输出上显示monitor界面
-nographic:默认情况下,qemu使用SDL来显示
Ctrl - a,c:在console和monitor之间切换
Ctrl -a,h:显示帮助信息
测试使用-vnc:
qemu-kvm -name cirros -m 128 -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:0
此时,在本机查看网络监听:

使用vncviewer 192.168.147.140:5900,可以连接到虚拟机:

还可以在远程机器上连接,如在宿主机上,使用RealVNC链接:


点击Continue

使用vnc是需要密码,使用
qemu-kvm -name cirros -m 128 -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:0,password
本机上使用vncviewer 192.168.147.140:5900时,提示:

为了设置密码,启动虚拟机时,使用-monitor stdio选项:

此时,界面直接进入qemu的monitor,修改一个设备的密码:

再次使用vncviewer 192.168.147.140:5900
弹出密码窗口,输入密码后,进入虚拟机。
RealVNC链接时:

-nographic选项,直接在控制台界面上显示虚拟机:


在使用-nographic的同时,又设置了vnc,则可同时以各自方式连接虚拟机,即此时也可通过vncviewer 192.168.147.140:5900连接到虚拟机。
网络属性参数相关说明:网络属性相关选项用于定义网络设备接口类型及其相关的各属性等信息。
kvm是Type I型虚拟化,也就是半虚拟化技术,对于网络,也就是虚拟机的网卡,其是有前半段和后半段之分的,前半段在虚拟机中,以网卡形式,如eth0呈现,后半段在Hypervisor中,也表现为一个网卡。这些一般需要自己手动创建,还需要自己创建网桥设备,需要自己手动将后半段桥接到这个网桥设备。也就是网络基本是手动自己控制组建的。
Linux内核有bridge模块,实现虚拟网桥设备功能。
而管理虚拟网桥,需要用户空间需要使用brctl程序与bridge模块交互,完成桥设备的管理。这个程序要通过安装bridge-utils包获得,前面学习xen时有接触。

brctl的语法:

-net nic,vlan=n ,macaddr=mac ,model=type ,name=name ,addr=addr ,vectors=v:站在虚拟机的角度配置网络,即网络的前半段的配置。创建一个新的网卡设备并连接至vlan n中,PC结构上默认的NIC为e1000,macaddr用于为其指定MAC地址,name用于指定一个在监控时显示的网络设备名称。qemu可以模拟多个类型的网卡设备,如virtio、ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet等,不同平台可能有所不同,可以使用"qemu-kvm -net nic,model=? -bios /usr/shared/qemu-kvm/bios.bin"命令获取当前平台支持的类型;默认MAC地址都是52:54:00:12:34:56,所以对于启动第二个及以上虚拟机,需要设定MAC。

-net tap,vlan=n ,name=name ,fd=h ,ifname=name ,script=file,downscript=dfile:通过物理机的TAP网络接口连接至vlan n中,使用script=file指定的脚本(默认/etc/qemu-ifup)来配置当前网络接口,并使用downscript=dfile指定的脚本(默认/etc/qemu-ifdown)来撤销接口配置,使用script=no和downscript=no可分别来禁止执行脚本。ifname=name,指定在宿主机上的接口名称,name=name应该是tap设备的名称。这是站在物理机的角度(也就是宿主机或Hypervisor角度)配置网络,即网络的后半段的配置。
搭建各种网络模型 :
1、隔离模型
虚拟机之间在同一个网络中,且可以相互通信,与宿主机以及外部网络是隔离的,即不能访问宿主机及外部网络。其原理如下图:

guest1和guest2中的eth0,相当于半虚拟化的网络前半段,在虚拟机中,对应的后半段vif0.0和vif1.0在宿主机中,将宿主机中的这两个接口同时关联到br0网桥中,相当于同时接入同一个交换机中,此时虚拟机之间是相通的,但不能与宿主机及外部互通。Peth0和Peth1是宿主机的物理网卡。
宿主机上增加网桥设备:
添加前:

添加网桥br0:
brctl addbr br0
删除网桥br0:
brctl delbr br0

添加后的网桥不是启用状态,可以使用如下命令启动:
ifconfig br0 up


ip link set br0 up


通过nmtui也可以添加网桥。
启动第一个虚拟机,同时设置网络:
qemu-kvm -name cirros0.3.6 -m 128 -smp 2 -cpu host -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:0**-net nic -net tap,ifname=vif1.0,script=no**
此时查看宿主机上的网络设备情况:


后半段的vif1.0网卡出现在宿主机上。但是状态是没有启动,不是UP状态。
在虚拟机的monitor中,查看其网络情况:

这里可以清楚的看到前半段\e1000.0和后半段tap.0
测试一下nic和tap的name参数:
qemu-kvm -name cirros0.3.6 -m 128 -smp 2 -cpu host -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:0 -net nic,name=virteth0 -net tap,name=vif1,ifname=vif1.0,script=no

tap的name参数起作用了,nic的没起作用。
启动第二个虚拟机:
qemu-kvm -name cirros0.3.6-2 -m 128 -smp 2 -cpu host -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:1 -net nic**,macaddr=52:54:00:12:34:57** -net tap,name=vif2 ,ifname=vif2.0,script=no
此时宿主机上,已经有了两个后半段的网卡设备,只不过都是DOWN状态:

虚拟机中配置网络地址:

相互之间进行ping,是不通的,需要后半段同时加入相同的网桥中:

此时,在虚拟机中进行连通性测试:

两个虚拟机之间可以互通。但是与宿主机之间是隔离的。
这就实现了网络的隔离模型。
对于将后半段的网络接口加入到网桥,可以通过脚本来达到启动虚拟机,创建网络设备时自动加入指定网桥的功能,即 -net tap,script=来实现,script默认使用/etc/qemu-ifup脚本,downscript指定的脚本,默认/etc/qemu-ifdown,实现关闭虚拟机时自动从网桥中删除后半段接口。
/etc/qemu-ifup

检查是有有语法错误:bash -n /etc/qemu-ifup
添加执行权限: chmod +x /etc/qemu-ifup
再次启动两台虚拟机,此时script=no可以去掉,自动使用/etc/qemu-ifup脚本,查看网桥情况:
qemu-kvm -name cirros0.3.6 -m 128 -smp 2 -cpu host -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:0 -net nic -net tap,name=vif1,ifname=vif1.0,script=/etc/qemu-ifup
qemu-kvm -name cirros0.3.6-2 -m 128 -smp 2 -cpu host -drive file=/images/kvm/cirros-0.3.6-x86_64-disk.img,if=virtio,media=disk,cache=writeback -bios /usr/share/qemu-kvm/bios.bin -vnc 192.168.147.140:1 -net nic,macaddr=52:54:00:12:34:57 -net tap,name=vif2,ifname=vif2.0,script=/etc/qemu-ifup

2、路由模型
需要在宿主机上创建一对虚拟以太网设备veth,这个设备在前面xen中学习过,创建的一对veth一端相互连接,另一端都各自连接到网络栈,现在,要把其中的一个的一端从网络栈移到网桥上。
ip命令也可以实现虚拟网络设备添加的功能,如添加网桥,添加接口使用:
ip link add name br0 type bridge
ip link set vif1.0 master br0
添加veth设备:
ip link add veth0 type veth peer nameveth1

测试使用:ip link add pveth0.0 type veth peer namepveth0.1
p代表物理机中的虚拟以太网卡。
将pveth0.1添加到网桥br0中,同时给pveth0.0配置IP,与虚拟机在同一网段,虚拟机就可以与宿主机通信。
ip link set pveth0.1 master br0

配置pveth0.0的IP:ifconfig pveth0.0 192.168.6.12/24 up
测试连通性:

虚拟机要想与宿主机的物理地址通信,即与192.168.147.140通信,需要添加路由,将其网关设置为pveth0.0的地址192.168.6.12

ping另一台主机192.168.147.130,不通。

此时,在pveth0.0接口上抓包:

icmp包到达了pveth0.0接口,但是因为宿主机的内核没有打开路由转发功能,此包不能被转发到ens33接口:在ens33接口抓包

查看核心路由转发的设置:cat /proc/sys/net/ipv4/ip_forward

设置为1,打开转发功能,此时在ens33物理接口抓包:

在pveth0.0上抓包:

实际上,打开核心转发功能后,ping包能够到达130主机,响应包也回到了140接口,即物理接口,但是没有转发到pveth0.0上。

当前的问题好像是响应包到了物理接口后,物理接口没有转发到pveth0.0。
路由模型不是很适用,因为数据包的返回需要对端有相应的路由项,而我们一般无法控制对端的设备,也就无法控制对端路由。所以一般使用下面的模型
3、NAT模型

使用iptables添加NAT规则:
iptables -t nat -A POSTROUTING -s 192.168.6.0/24 -o ens33 -j SNAT --to-source 192.168.147.140

此时,在虚拟机上ping外部主机:

使用nat,也需要打开宿主机的核心转发功能,如果关闭,虚拟机上也是ping不同外部主机。
简化网络:
上面的操作在测试各模型的同时,也是对veth设备的熟悉过程,但从网络图中可以看到,增加了veth后,网络的链条明显增加了,实际中可以不使用veth,在网桥上配置地址即可,bridge在宿主机上也是一个网络设备,也是一个网卡。
删除veth,在bridge上配置IP地址。
先将pveth0.1从br0上删除,然后删除veth设备:
ip link set pveth0.1 nomaster
ip link delete pveth0.0

配置br0地址:
ifconfig br0 192.168.6.12/24
这样配置后,依然能够实现上面的效果。
4、桥接模式
将物理网卡的IP地址删除,将物理接口桥接到br0桥设备上,然后配置网桥地址为原来的物理网卡的地址。

ip addr del 192.168.6.12/24 dev br0
ip addr del 192.168.147.140/24 dev ens33
ip link set ens33 master br0
ip addr add 192.168.147.140/24 dev br0

可以看到关键的一点,物理网卡接口桥接到网桥后,网桥的MAC和物理网卡的MAC是一样的了。
启动两台虚拟机,配置其地址,与宿主机在同一个网段:
ifconfig eth0 192.168.147.10/24 up
然后添加路由:
route add default gw 192.168.147.2
此时,虚拟机就可以访问外部网络了,其与宿主机处于平等的网络位置。
宿主机上:

虚拟机上:

应该是dns的问题,但是IP地址是通的。
指定以网络接口启动虚拟机安装 :
qemu-kvm的-boot选项:-boot order=nc,once=n
在局域网中部署好pxe服务所需的dhcp,tftp等,或者使用cobbler环境等。
设置在后台运行虚拟机: -daemonize
图形界面时,鼠标轨迹不一致问题:设置-usb选项
KVM的virtio半虚拟化 :
HVM:虚拟化CPU
I/O半虚拟化分成两段:
前端驱动(virtio前半段):virtio-blk, virtio-net, virtio-pci, virtio-balloon, virtio-console
Linux:CentOS 4.8+, 5.3+, 6.0+, 7.0+
Windows:
virtio: 虚拟队列,virt-ring
transport:
后端处理程序(virt backend drivers):在QEMU中实现;
virtio-balloon:
ballooning: 让VM中运行的GuestOS中运行调整其内存大小;
qemu-kvm -balloon virtio
手动查看GuestOS的内存用量:
info balloon
balloon N
virtio-net:
其依赖于GuestOS中的驱动,及Qemu中的后端驱动
GuestOS: virtio_net.ko
qemu-kvm -net nic,model=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: 半虚拟化的时钟
grep -i "paravirt" /boot/config-2.6.32-504.el6.x86_64
CONFIG_PARAVIRT_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_PARAVIRT_CLOCK=y
VM Migration:虚拟机迁移
static migration:停机,迁移磁盘映像文件,启动
live migration :运行中迁移
整体迁移时间
服务器停机时间
对服务的性能的影响
在待迁入主机使用
qemu-kvm -vnc :N -incoming tcp:0:7777
vncviewer :590N
在源主机使用:
monitor接口:
migrate tcp:DEST_IP:DEST:PORT