KVM虚拟化基础与实操过程
作者:yuxb73
文章介绍了KVM虚拟化技术的基本概念、组成组件及常用命令,涵盖宿主机、虚拟机、镜像文件等术语,详解NFS配置与热迁移流程,并分享通过命令行和图形界面管理虚拟机的实践经验
KVM概念
KVM 核心概念
- KVM的定义:基于 Linux 内核的虚拟化技术,本质是一个内核模块,通过硬件虚拟化技术(如 Intel VT 或 AMD-V)实现对虚拟机的支持。
- KVM 的组成:包括 KVM 内核模块、QEMU(用户空间工具,负责模拟 I/O 设备等)、libvirt(管理虚拟机的 API 和工具)。
虚拟机相关术语
- 宿主机(Host):运行 KVM 的物理服务器。
- 虚拟机(Guest):在宿主机上创建的虚拟系统,如win7、vm2、vm3。
- 镜像文件(Image):虚拟机的磁盘文件,如 qcow2 格式文件,解释其特点(动态扩展、支持快照等)。
命令行工具解析
常用
virsh
命令补充说明:
virsh list --all:列出所有虚拟机(包括运行和关闭状态),帮助用户快速了解虚拟机整体情况。virsh start/shutdown/destroy:分别对应启动、正常关闭、强制关闭虚拟机,强调destroy的风险(类似拔电源,可能导致数据丢失)。virsh dumpxml:导出虚拟机的 XML 配置文件,该文件记录了虚拟机的硬件配置(CPU、内存、磁盘、网络等),可用于备份或修改配置。- 解释
qemu-img工具:用于管理虚拟机磁盘镜像,如创建(create)、查看信息(info)等操作,说明 qcow2 格式相比 raw 格式的优势(节省空间、支持压缩等)。
KVM使用
图形使用
图形调出

可以安装虚拟机

上传镜像才能安装虚拟机

上传镜像

安装虚拟机



后面直接前进就可以
这之前会弹出是否禁用快捷方式
下面按照正常安装win7就可以了



到这个界面用shift+f10





测试:安装硬盘网卡



命令行使用
[root@KVM1 ~]# virsh list --all Id 名称 状态 ---------------------- 5 win7 running [root@KVM1 ~]# virsh vcpuinfo win7 VCPU: 0 CPU: 3 状态: running CPU 时间: 49.1s CPU关系: yyyy VCPU: 1 CPU: 2 状态: running CPU 时间: 48.4s CPU关系: yyyy [root@KVM1 ~]# virsh list Id 名称 状态 ------------------- [root@KVM1 ~]# virsh list --all Id 名称 状态 ------------------- - win7 关闭
调出图形管理页面

[root@KVM1 ~]# virsh list Id 名称 状态 ------------------- [root@KVM1 ~]# virt-manager # [root@KVM1 ~]# virsh start win7 Domain 'win7' started [root@KVM1 ~]# virsh list Id 名称 状态 ---------------------- 6 win7 running #重启虚拟机win7 [root@KVM1 ~]# virsh reboot win7 Domain 'win7' is being rebooted #正常关机,一般都是正常关机 [root@KVM1 ~]# virsh shutdown win7 Domain 'win7' is being shutdown #强制关闭虚拟机(拔电源),系统无法响应,实在没办法再强制关机 [root@KVM1 ~]# virsh destroy win7 Domain 'win7' destroyed #设置虚拟机随着KVM一起开机 [root@KVM1 ~]# virsh autostart win7 Domain 'win7' marked as autostarted #列出随着宿主机一起开机的虚拟机有哪些 [root@KVM1 ~]# virsh list --autostart Id 名称 状态 ---------------------- 6 win7 running #关闭win7随KVM一起启动 [root@KVM1 ~]# virsh autostart --disable win7 Domain 'win7' unmarked as autostarted #观察现象,win7从自启动列表中移除 [root@KVM1 ~]# virsh list --autostart Id 名称 状态 -------------------
#查看虚拟机win7配置文件
[root@KVM1 ~]# virsh dumpxml win7
<domain type='kvm' id='1'>
<name>win7</name>
<uuid>e0d07415-c249-4d81-9e68-de33a55bc7d1</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/7"/>
</libosinfo:libosinfo>
</metadata>
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
<vcpu placement='static'>2</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-q35-rhel8.6.0'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<hyperv mode='custom'>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
</hyperv>
<vmport state='off'/>
</features>
<cpu mode='custom' match='exact' check='full'>
<model fallback='forbid'>EPYC-Milan</model>
<vendor>AMD</vendor>
<feature policy='require' name='x2apic'/>
<feature policy='require' name='tsc-deadline'/>
<feature policy='require' name='hypervisor'/>
<feature policy='require' name='tsc_adjust'/>
<feature policy='require' name='vaes'/>
<feature policy='require' name='vpclmulqdq'/>
<feature policy='require' name='spec-ctrl'/>
<feature policy='require' name='arch-capabilities'/>
<feature policy='require' name='ssbd'/>
<feature policy='require' name='virt-ssbd'/>
<feature policy='disable' name='vmcb-clean'/>
<feature policy='require' name='rdctl-no'/>
<feature policy='require' name='skip-l1dfl-vmentry'/>
<feature policy='require' name='mds-no'/>
<feature policy='require' name='pschange-mc-no'/>
<feature policy='disable' name='pcid'/>
<feature policy='disable' name='perfctr_core'/>
<feature policy='disable' name='xsaveerptr'/>
<feature policy='disable' name='amd-stibp'/>
<feature policy='disable' name='svm'/>
<feature policy='require' name='topoext'/>
<feature policy='disable' name='npt'/>
<feature policy='disable' name='nrip-save'/>
<feature policy='disable' name='svme-addr-chk'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='hypervclock' present='yes'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/win7.qcow2' index='3'/>
<backingStore/>
<target dev='sda' bus='sata'/>
<alias name='sata0-0-0'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/iso/cn_windows_7_enterprise_with_sp1_x64_dvd_u_677685.iso' index='2'/>
<backingStore/>
<target dev='sdb' bus='sata'/>
<readonly/>
<alias name='sata0-0-1'/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/win7-1.qcow2' index='1'/>
<backingStore/>
<target dev='sdc' bus='sata'/>
<alias name='sata0-0-2'/>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</disk>
<controller type='usb' index='0' model='ich9-ehci1'>
<alias name='usb'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<alias name='usb'/>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0' multifunction='on'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<alias name='usb'/>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<alias name='usb'/>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x2'/>
</controller>
<controller type='sata' index='0'>
<alias name='ide'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pcie-root'>
<alias name='pcie.0'/>
</controller>
<controller type='pci' index='1' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='1' port='0x10'/>
<alias name='pci.1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/>
</controller>
<controller type='pci' index='2' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='2' port='0x11'/>
<alias name='pci.2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/>
</controller>
<controller type='pci' index='3' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='3' port='0x12'/>
<alias name='pci.3'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/>
</controller>
<controller type='pci' index='4' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='4' port='0x13'/>
<alias name='pci.4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/>
</controller>
<controller type='virtio-serial' index='0'>
<alias name='virtio-serial0'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
</controller>
<interface type='network'>
<mac address='52:54:00:2a:d9:94'/>
<source network='default' portid='3f0a21b5-ffee-4b01-92f8-2c6d448c3fbc' bridge='virbr0'/>
<target dev='vnet0'/>
<model type='e1000e'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
<interface type='network'>
<mac address='52:54:00:9e:14:57'/>
<source network='default' portid='571c14eb-d753-4446-9746-d680769a286d' bridge='virbr0'/>
<target dev='vnet1'/>
<model type='e1000e'/>
<alias name='net1'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/0'/>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/0'>
<source path='/dev/pts/0'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0' state='disconnected'/>
<alias name='channel0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<input type='tablet' bus='usb'>
<alias name='input0'/>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'>
<alias name='input1'/>
</input>
<input type='keyboard' bus='ps2'>
<alias name='input2'/>
</input>
<graphics type='spice' port='5900' autoport='yes' listen='127.0.0.1'>
<listen type='address' address='127.0.0.1'/>
<image compression='off'/>
</graphics>
<sound model='ich9'>
<alias name='sound0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/>
</sound>
<audio id='1' type='spice'/>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</video>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir0'/>
<address type='usb' bus='0' port='2'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<alias name='redir1'/>
<address type='usb' bus='0' port='3'/>
</redirdev>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
</memballoon>
</devices>
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c619,c687</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c619,c687</imagelabel>
</seclabel>
<seclabel type='dynamic' model='dac' relabel='yes'>
<label>+107:+107</label>
<imagelabel>+107:+107</imagelabel>
</seclabel>
</domain>
#查看win7虚拟机配置的cpu数量
[root@KVM1 ~]# virsh vcpucount --active win7
2
#默认磁盘存放目录 [root@KVM1 ~]# cd /var/lib/libvirt/images/ [root@KVM1 images]# ls win7-1.qcow2 win7.qcow2 #win7虚拟机硬盘 #查看win7虚拟机磁盘长列表信息 [root@KVM1 images]# ll -h 总用量 8.7G -rw-------. 1 qemu qemu 21G 9月 2 11:21 win7-1.qcow2 -rw-------. 1 qemu qemu 42G 9月 2 11:34 win7.qcow2 #查看win7虚拟机硬盘简要信息,虚拟机关机状态下看 #可能要关闭win7后才能查看 [root@KVM1 images]# qemu-img info win7.qcow2 # 开机状态下可能不行 [root@KVM1 images]# qemu-img info win7.qcow2 qemu-img: Could not open 'win7.qcow2': Failed to get shared "write" lock Is another process using the image [win7.qcow2]?
命令行创建虚拟机
# 目前所在位置
[root@KVM1 images]# pwd
/var/lib/libvirt/images
#给虚拟机VM2创建硬盘vm2.qcow2
[root@KVM1 images]# qemu-img create -f qcow2 vm2.qcow2 20G
Formatting 'vm2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 lazy_refcounts=off refcount_bits=16
[root@KVM1 images]# ls
vm2.qcow2 win7-1.qcow2 win7.qcow2
#显示创建出来的新的虚拟机硬盘vm2.qcow2属性
[root@KVM1 images]# qemu-img info vm2.qcow2
image: vm2.qcow2
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
disk size: 196 KiB
cluster_size: 65536
Format specific information:
compat: 1.1
compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
[root@KVM1 images]# cd /iso/
#上传一个CentOS-7-x86_64-Minimal-1810.iso到/iso目录
[root@KVM1 iso]# mkdir /disk
[root@KVM1 iso]# qemu-img create -f qcow2 /disk/vm2.qcow2 20G
Formatting '/disk/vm2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 lazy_refcounts=off refcount_bits=16
[root@KVM1 iso]# virt-install --name vm2 --memory 4096 --vcpus 2 --disk path=/disk/vm2.qcow2 --location /iso/CentOS-7-x86_64-Minimal-1810.iso --network network=default --noautoconsole
开始安装......
搜索文件 vmlinuz...... | 6.3 MB 00:00
搜索文件 initrd.img...... | 50 MB 00:00
域仍在运行。安装可能正在进行中。
可以重新连接到控制台以完成安装过程。
#--name 指定虚拟机名字
#--memory 指定虚拟机内存
#--vcpus 指定虚拟机的CPU数量
#--disk path 指定虚拟机的磁盘位置
#--location 指定光盘镜像的位置
#--network 指定网络,KVM默认有个网络名为default的NAT网络
#查看创建的vm2
[root@KVM1 iso]# virsh list
Id 名称 状态
----------------------
1 win7 running
2 vm2 running

通过VNC连到虚拟机中去
# 创建个vm3虚拟机,通过VNC管理 [root@KVM1 ~]# qemu-img create -f qcow2 /disk/vm3.qcow2 20G Formatting '/disk/vm3.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 lazy_refcounts=off refcount_bits=16 [root@KVM1 ~]# virt-install --name vm3 --memory 2048 --vcpus 1 --disk path=/disk/vm3.qcow2 --location /iso/CentOS-7-x86_64-Minimal-1810.iso --network network=default --noautoconsole --vnclisten=0.0.0.0 --vncport=5903 --vnc 开始安装...... 搜索文件 vmlinuz...... | 6.3 MB 00:00 搜索文件 initrd.img...... | 50 MB 00:00 域仍在运行。安装可能正在进行中。 可以重新连接到控制台以完成安装过程。 #--vnclisten 设置VNC监听地址所有地址 #--vncport=5903 宿主机监听到5093的VNC请求,转到vm3虚拟机上 [root@KVM1 ~]# systemctl stop firewalld.service
vnc访问:

KVM热迁移实验
热迁移原理
- 说明 KVM 热迁移的概念:在虚拟机不中断服务的情况下,将其从一个宿主机迁移到另一个宿主机。
- 共享存储(如 NFS)在热迁移中的作用:虚拟机的磁盘文件存储在共享存储中,迁移时只需传输内存状态等数据,确保迁移前后虚拟机访问的磁盘一致。
- 热迁移的大致流程:暂停源虚拟机→传输内存数据→同步剩余数据→在目标宿主机恢复虚拟机运行→切换网络连接。
准备环境
克隆原有的KVM1到KVM2和NFS 修改克隆的主机名和ip地址 [root@KVM1 ~]# hostnamectl set-hostname KVM2 [root@KVM1 ~]# bash # 把uuid删掉另外把“IPADDR=”后的内容改了保存即可 [root@KVM2 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens160 [root@KVM2 ~]# nmcli connection reload ens160 [root@KVM2 ~]# ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 ens160 UP 192.168.108.102/24 fe80::20c:29ff:fe9f:e213/64 virbr0 DOWN 192.168.122.1/24 #kvm1配置完hosts后scp [root@KVM1 ~]# vim /etc/hosts [root@KVM1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.108.100 NFS 192.168.108.101 KVM1 192.168.108.102 KVM2 [root@KVM2 ~]# scp 192.168.108.101:/etc/hosts /etc/hosts The authenticity of host '192.168.108.101 (192.168.108.101)' can't be established. ECDSA key fingerprint is SHA256:MqzedPnQ99vEBryF/xQ5yZ1Crn6hD2rAnYXrp2n34kI. Are you sure you want to continue connecting (yes/no/[fingerprint])? y Please type 'yes', 'no' or the fingerprint: yes Warning: Permanently added '192.168.108.101' (ECDSA) to the list of known hosts. root@192.168.108.101's password: hosts 100% 221 106.2KB/s 00:00
创建共享存储NFS
NFS: [root@NFS ~]# mkdir /nfs [root@NFS ~]# vim /etc/exports [root@NFS ~]# vim /etc/exports [root@NFS ~]# cat /etc/exports /nfs *(rw,no_root_squash,no_subtree_check) #第一列:/nfs共享出去的目录 #第二列:*代表允许所有网段访问 #rw: 挂载此目录的客户端对该共享目录具有读写权限 #sync:资料同步写入内存和磁盘 #no_root_squash:客户机用root访问该共享文件夹时,不映射root用户,root_squash:客户机用root 访问该共享文件夹时,将root用户映射成匿名用户 #no_subtree_check:不检查父目录权限 # 重启NFS服务 [root@NFS ~]# systemctl restart nfs-server.service # 测试 [root@NFS ~]# showmount -e localhost Export list for localhost: /nfs * [root@KVM2 ~]# showmount -e 192.168.108.100 Export list for 192.168.108.100: /nfs * # 停止防火墙服务 [root@NFS ~]# systemctl stop firewalld.service
KVM1,KVM2分别创建/NFS目录用于挂载NFS的/nfs目录
[root@KVM1 ~]# mkdir /NFS [root@KVM2 ~]# mkdir /NFS
KVM1上操作
将KVM2添加进来

点击连接后,后面会显示框框,两个框框分别输入yes和密码123
右击Details两个KVM改名字

KVM1,KVM2添加共享存储NFS,先点KVM1操作

上传CentOS镜像,到KVM1,KVM1使用共享存储创建虚拟机

镜像上传好后,点击KVM1,创建虚拟机

选择刚才上传的镜像


选择安装到共享存储NFS



开始迁移
KVM1和KVM2关闭防火墙
KVM1: [root@KVM1 ~]# systemctl stop firewalld.service KVM2: [root@KVM2 ~]# systemctl stop firewalld.service # 迁移前 [root@KVM1 ~]# virsh list Id 名称 状态 --------------------------- 2 centos7.0 running [root@KVM2 ~]# virsh list Id 名称 状态 ------------------- # 迁移后 [root@KVM1 ~]# virsh list Id 名称 状态 ------------------- [root@KVM2 ~]# virsh list Id 名称 状态 --------------------------- 1 centos7.0 running


虚拟机从KVM1跑到KVM2

ping测试成功

总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
