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测试成功
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。