环境搭建和准备

 # 查看cpu是否支持硬件虚拟化
 grep -E -c "vmx|svm" /proc/cpuinfo
 
 sudo apt install -y qemu qemu-kvm libvirt-daemon bridge-utils virt-manager virtinst

# if centos
# yum install -y kvm virt-manager libvirt libvirt-python python-virtinst virt-install qemu-kvm

 lsmod | grep -i kvm
 
 sudo systemctl status libvirtd.service
 
 # 如果服务未启动
 sudo systemctl enable libvirtd --now
 
 # 配置网桥使得libvirt可以从外部访问
 cat /etc/netplan/00-installer-config.yaml
 
 
 # 可选,GUI管理工具
 sudo apt-get install virt-manager python-spice-client-gtk
 

下载调试镜像: 从官方地址下载cirros镜像,用来调试虚拟机,用户名和密码如下

user:cirros
pass:cubswin:)   # 不同版本密码不同

通常将cirros镜像放置到/var/lib/libvirt/boot路径下

可以查看镜像信息

qemu-img info cirros-0.5.0-x86_64-disk.img

至此,vrish学习的基本环境就搭建完成

Libvirt基本概念

virsh命令大概分组

  • Domain Management(域管理)
  • Domain Monitoring(域监控)
  • Host and Hypervisor(主机及虚拟化)
  • Interface(网卡接口)
  • Network Filter(网络防火墙)
  • Networking(网络)
  • Node Device(节点设备驱动)存在
  • Secret
  • Snapshot(快照)
  • Storage Pool(存储池或存储策略)
  • Storage Volume(存储卷)
  • Virsh itself(virsh shell自身相关)

定义过的或者能够被libvirt感知到的虚机的配置文件都在/etc/libvirt目录下

虚拟机文件和其它的相关文件都保存在 /var/lib/libvirt/

镜像的默认路径是 /var/lib/libvirt/boot/

Vm lifecycle graph.png

上图时一个libvirt虚拟机的生命周期图,虚拟机分为两种:

  • 持久性的
  • 短暂性的

持久性虚拟机会一直存在,直到被删除;

短暂性的虚拟机只有在虚拟机被关机或重启前存在

虚拟机常用命令

virsh和qemu的命令非常多,下面罗列一些常用的命令

virsh help									# 查看帮助信息
virsh version								# 查看qemu版本
virsh help <特定命令>						# 查看特定命令帮助信息
virsh <特定命令> --help						# 查看特定命令帮助信息
virsh nodeinfo								# 查看宿主机信息
virsh uri                                  # 查看当前主机hyperviso的连接路径;
virsh connect <hypervisor uri>			   # 连接到特定hypervisor,默认qemu:///system
virsh sysinfo								# 查看hypervisro信息

virsh start <虚拟机名称>             		# 启动一个之前已经定义define过的虚拟机(domain)
virsh shutdown <虚拟机名称>					# 关闭虚拟机,类似虚拟机内执行关机
virsh reboot <虚拟机名称>					# 重启虚拟机
virsh destroy <虚拟机名称>					# 强制关闭虚拟机,类似于断电
virsh suspend <虚拟机名称>   				# 挂起虚拟机,将当前状态保存在内存中
virsh resume <虚拟机名称>					# 恢复虚拟机挂起状态,从内存中恢复虚拟机状态
virsh save <虚拟机名称> <img镜像文件名>	 	 # 暂停虚拟机,将虚拟机状态保存在磁盘镜像文件中
virsh restore <img镜像文件名>			   #重新载入暂停的虚拟机
virsh autostart <虚拟机名称>					# 虚拟机随着物理机启动自动启动
virsh autostart <虚拟机名称> --disable		# 禁止开机启动
virsh dominfo <虚拟机名称>					# 查看虚拟机domain信息
virsh domblklist <虚拟机名称>				# 列出虚拟机所有块存储设备
virsh console <虚拟机名称>					# 控制台连接虚拟机
virsh dumpxml <虚拟机名称>					# 查看虚拟机xml文件
virsh edit <虚拟机名称>						# 编辑虚拟机xml文件
virsh managedsave <虚拟机名称>				# 保存状态save并关闭虚拟机,下次启动会恢复到之前保存的状态
virsh start <虚拟机名称>						# 启动并恢复managedsave保存的状态
virsh reset <虚拟机名称>						# 对虚拟机执行强制重启,类似重置电源按钮
virsh create <虚拟机xml文件>                 # 从xml文件中创建domain,创建完成后会自动启动;
											# 一个xml对应一个domain虚拟机
virsh define <虚拟机xml文件>					# 从xml文件定义define新的domain,不会自动启动
virsh undefine <虚拟机名称>					# 对于运行中的持久性虚拟机,将状态转换为暂时的,关机后virsh无法感知其存在
											# 对于非活动的虚拟机,undefine后virsh将无法感知其存在
											# undefine后磁盘依然存在,只是删除虚拟机的配置文件/etc/libvirt/qemu

virsh undefine <虚拟机名称> --remove-all-storage		# 删除虚拟机并删除所有磁盘文件


virsh snapshot-create-as <虚拟机名称> --name <快照名称>  # 从命令行创建快照
virsh snapshot-create <虚拟机名称>					# 从xml文件创建快照
virsh snapshot-list <虚拟机名称>						# 查看虚拟机快照列表
virsh snapshot-parent <虚拟机名称> --current			# 查看当前快照的上一级快照
virsh snapshot-edit <虚拟机名称> --snapshotname <快照名>	# 编辑快照
virsh snapshot-revert <虚拟机名称> --snapshotname <快照名>	# 恢复快照
virsh snapshot-delete <虚拟机名称> --snapshotname <快照名>	# 删除快照



virsh list									# 查看活动虚拟机状态
virsh list --all							# 查看所有虚拟机状态

virsh setvcpus <虚拟机名称> 4 --maximum --config # 设置最大vcpu数(只能用--config,下次运行生效)
virsh setvcpus <虚拟机名称> 4 --config   		# 下次启动使用vcpu数
virsh vcpuinfo <虚拟机名称>    					# 查看vcpu信息
virsh vcpupin <虚拟机名称>						# 查询域 vcpu亲和性,即vcpu和物理cpu之间关系
virsh maxvcpus								   # 显示本机vcpu最大值

virsh setmaxmem <虚拟机名称> [--size] 2G --current  # 设置最大内存限制值
virsh setmem <虚拟机名称> [--size] 2G --current     # 设置内存分配


virsh domblklist cirros							# 查看虚拟机的存储块设备

创建磁盘文件
#qcow2是文件类型,test1-add1.qcow2是磁盘文件,5G是大小
qemu-img create -f qcow2 /var/lib/libvirt/images/test1-add1.qcow2 5G
qemu-img info <虚拟机镜像>			# 查看镜像信息


virt-install <命令行> 	# 通过命令行指定来创建虚拟机

virsh attach-disk <虚拟机名称> 
virsh attach-device <虚拟机名称> /etc/libvirt/qemu/test2-add.xml --persistent		# 从XML文件附加设备
virsh detach-device <虚拟机名称> /etc/libvirt/qemu/test2-add.xml --persistent		# 卸载设备

虚拟机操作实践

实验1:修改虚拟机vcpu

修改虚拟机的最大vcpu数量,可以修改maximum config 和current config的值

# 查看vcpu配置
➜  ~ virsh vcpucount cirros
maximum      config         2			# 指定下次重启虚拟机后可用的最大vcpu数量
maximum      live           2			# 指定运行/暂停状态下虚拟机可用的最大vcpu数量,重启后和maximum config一致
current      config         2			# 下次重启时虚拟机使用的vcpu数量
current      live           2			# 正在运行的虚拟机vcpu实际数量

通过修改xml文件修改vcpu数量

virsh edit cirros
#  <vcpu placement='static'>2</vcpu>
# 修改为
 <vcpu placement='static'>3</vcpu>

关闭并重新启动虚拟机

virsh shutdown cirros
virsh list --all   # 确认已经是shut off状态
virsh start cirros

再次查看vcpu数量,发现已经改变

➜  ~ virsh vcpucount cirros
maximum      config         3
maximum      live           3
current      config         3
current      live           3

同样方式,修改xml文件,恢复为2个vcpu,执行virsh reboot 后并没释放vcpu

➜  ~ virsh vcpucount cirros
maximum      config         2
maximum      live           3
current      config         2
current      live           3

必须执行shutdown或者destory,然后重新start才能改变运行时的vcpu

➜  ~ virsh vcpucount cirros
maximum      config         2
maximum      live           2
current      config         2
current      live           2

还可以通过命令行修改vcpu的各个配置值

➜  ~ virsh setvcpus cirros 3 --maximum --config 

➜  ~ virsh vcpucount cirros                    
maximum      config         3
maximum      live           2
current      config         2
current      live           2

➜  ~ virsh setvcpus cirros 3 --config  # 修改current config

➜  ~ virsh vcpucount cirros          
maximum      config         3
maximum      live           2
current      config         3
current      live           2

# 重启虚拟机使其生效
➜  ~ virsh shutdown cirros
➜  ~ virsh start cirros
➜  ~ virsh vcpucount cirros
maximum      config         3
maximum      live           3
current      config         3
current      live           3

在宿主机上无法设置vcpu的current live小于current config,只能在虚拟机内部执行chcpu指令来修改,使得vcpu离线

也可以将最大可用vcpu设置较大,方便后续在虚拟机运行时可以动态调整vcpu的数量

➜  ~ virsh setvcpus cirros 5 --maximum --config 
➜  ~  virsh setvcpus cirros 2 --config 

➜  ~ virsh shutdown cirros
➜  ~ virsh start cirros

➜  ~ virsh vcpucount cirros
maximum      config         5
maximum      live           5
current      config         2
current      live           2

➜  ~ virsh setvcpus cirros 3			# 动态调整vcpu数量,调整范围[current config,比maximum config]
➜  ~ virsh vcpucount cirros 
maximum      config         5
maximum      live           5
current      config         2
current      live           3
➜  ~ virsh setvcpus cirros 2			
➜  ~ virsh vcpucount cirros 
maximum      config         5
maximum      live           5
current      config         2
current      live           2
➜  ~ virsh vcpuinfo cirros				# 查看vcpu运行状态

实验2:修改虚拟机的内存

通过修改xml配置文件并重新启动虚拟机

# 修改项,修改完成后
<memory unit='KiB'>462144</memory>				# 启动后最大允许可用内存
<currentMemory unit='KiB'>262144</currentMemory># 启动时使用的内存大小

在最大可用内存范围内,可以在虚拟机运行时调整内存使用

虚拟机最大内存只能在虚拟机关闭状态更改,重启后生效

使用virsh setmaxmem命令,和直接修改xml文件等效

➜  ~ virsh dominfo cirros | grep memory    # 虚拟机启动时显示的used memory不准确
Max memory:     462144 KiB
Used memory:    262144 KiB

➜  ~ virsh setmem cirros 300000        

➜  ~ virsh dominfo cirros | grep memory
Max memory:     462144 KiB
Used memory:    300000 KiB

➜  ~ virsh shutdown cirros
➜  ~ virsh setmaxmem cirros 700000

实验3:调整虚拟机的磁盘

虚拟机支持在虚拟机开机时动态挂载新的磁盘

➜  ~ qemu-img create -f qcow2 -o size=20M,preallocation=metadata /var/lib/libvirt/boot/second.qcow2
Formatting '/var/lib/libvirt/boot/second.qcow2', fmt=qcow2 size=20971520 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16

➜  ~ qemu-img info /var/lib/libvirt/boot/second.qcow2

image: /var/lib/libvirt/boot/second.qcow2
file format: qcow2
virtual size: 20 MiB (20971520 bytes)
disk size: 260 KiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false


virsh attach-disk cirros /images/cirros/second.qcow2 vda --targetbus virtio 

# 卸载磁盘(前提时没有分区或者挂载
virsh detach-disk 26 vda

也可以手动修改xml文件,然后重启虚拟机

# 首先创建一个qcow2磁盘或者raw磁盘
# dd命令创建一个非稀疏的磁盘
dd if=/dev/zero of=/vm-images/vm1-add.img bs=1M count=1024

# 在xml文件中加入一个新的xml段
<disk type='file' device='disk'>
     <driver name='qemu' type='raw' cache='none' io='threads'/>
     <source file='/vm-images/vm1-add.img'/>
     <target dev='vdb' bus='virtio'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
 </disk>

实验4:创建虚拟机

virt-install  --name=cirros --ram=256 --vcpus=1 --disk path=/var/lib/libvirt/boot/cirros-0.5.0-x86_64-disk.img,format=qcow2 --import --network network:default --vnc --vncport=5920
# 也可以通过xml文件来创建

实验5:复制虚拟机

可以通过命令行复制一个虚拟机,也可以通过拷贝并修改配置文件和存储卷文件进行复制

# 通过virt-clone命令复制
# virt-clone -o <虚拟机名称> -n <新虚拟机名称> -f /var/lib/libvirt/images/test4.qcow2
# qcow2磁盘不需要预先创建,创建完成后需要进虚拟机手动改变ip地址和用户名
➜  ~ virt-clone -o cirros -n cirros1 -f /var/lib/libvirt/boot/cirros1.qcow2
# 自动生产不一样的mac地址和uuid
➜  ~ diff cirros.xml cirros1.xml
        <   <name>cirros</name>
        <   <uuid>874fe199-47ea-45d1-a25d-98d0535dddb3</uuid>
        ---
        >   <name>cirros1</name>
        >   <uuid>fba2f776-432d-4870-a7ec-bbf73fa1b086</uuid>
        39c39
        <       <source file='/var/lib/libvirt/boot/cirros-0.5.0-x86_64-disk.img'/>
        ---
        >       <source file='/var/lib/libvirt/boot/cirros1.qcow2'/>
        63c63
        <       <mac address='52:54:00:fa:5c:d3'/>
        ---
        >       <mac address='52:54:00:29:8d:06'/>
        81c81
        <     <graphics type='vnc' port='5921' autoport='no'>
        ---
        >     <graphics type='vnc' port='-1' autoport='yes'>


#virt-clone -f指定的文件不要事先创建,如果有多个磁盘文件就用多个-f选项 如
virt-clone -o <虚拟机名称> -n <新虚拟机名称> -f /home/lib/libvirt/images/test4.qcow2 -f /mnt/images/test4-add1.qcow2

可以手动复制xml文件和磁盘镜像来复制

➜  qemu cp cirros.xml cirros3.xml
# 修改xml文件中的domain name和mac地址等信息
➜  qemu vim cirros3.xml 
➜  qemu cd /var/lib/libvirt/boot 
# 在define新的克隆虚拟机之前准备好所需的磁盘
➜  boot cp cirros-0.5.0-x86_64-disk.img cirros3.img
➜  boot qemu-img info cirros3.img 
        image: cirros3.img
        file format: qcow2
        virtual size: 112 MiB (117440512 bytes)
        disk size: 198 MiB
        cluster_size: 65536
        Snapshot list:
        ID        TAG                     VM SIZE                DATE       VM CLOCK
        1         1603292226              101 MiB 2020-10-21 22:57:06   94:39:31.435
        Format specific information:
            compat: 1.1
            lazy refcounts: false
            refcount bits: 16
            corrupt: false
➜  ~ virsh define /etc/libvirt/qemu/cirros3.xml 
	Domain cirros3 defined from /etc/libvirt/qemu/cirros3.xml

➜  ~ virsh list --all
     Id   Name      State
    --------------------------
     2    cirros    running
     -    cirros3   shut off
 
➜  ~ virsh start cirros3 
	Domain cirros3 started

# 此时,一个新的克隆虚拟机就创建完成
# 需要手动修改IP和hostname

实验6:误删虚拟机恢复

# 误删除虚拟机
➜  ~ virsh undefine cirros1
Domain cirros1 has been undefined

➜  ~ virsh dominfo cirros1
Id:             1
Name:           cirros1
UUID:           fba2f776-432d-4870-a7ec-bbf73fa1b086
OS Type:        hvm
State:          running
CPU(s):         2
CPU time:       41.7s
Max memory:     700416 KiB
Used memory:    262144 KiB
Persistent:     no								# 已经变为非持久化的,无法重新启动
Autostart:      disable
Managed save:   no
Security model: apparmor
Security DOI:   0
Security label: libvirt-fba2f776-432d-4870-a7ec-bbf73fa1b086 (enforcing)

➜  ~ virsh shutdown cirros1    # 关机后再也启动不了了

➜  ~ ls /etc/libvirt/qemu      # cirros1的xml文件已经不存在
➜  ~ ls /var/lib/libvirt/boot  # cirros1的qcow2镜像仍然存在

# 需要在关闭虚拟机之前,重新定义define一个配置文件即可恢复
virsh  dumpxml   centos-C  > /etc/libvirt/qemu/centos-C.xml       
virsh define /etc/libvirt/qemu/centos-C.xml 
# 如果是在关闭着的服务器上执行的virsh undefine  centos-C 删除命令,则会把对应的配置文件清空,虚拟机再也启动不了,重新定义也不行
对于

参考

在 Ubuntu 的 KVM 中安装 Windows 系统

virsh使用总结

kvm管理和基础命令

kvm命令总结和虚机器备份迁移

How to Install KVM on Ubuntu 20.04 LTS Server (Focal Fossa)

Libvirt虚拟机生命周期

Modify cpu number