1 热插拔卷
热插拔卷¶
KubeVirt 支持热插拔卷到正在运行的虚拟机实例(VMI)中。卷必须是块存储卷(block volume)或包含磁盘映像(虚拟机镜像或虚拟机磁盘)的卷。 当热插拔卷的虚拟机被重新启动时,热插拔的卷将被挂载到重新启动的虚拟机上。如果卷被持久化,它们将成为VM规范的一部分,而不会被视为热插拔。 如果它们没有被持久保存,卷将作为热插拔卷重新连接。
热插拔卷使用场景:将故障的虚拟机系统卷热插拔到正常运行的虚拟机中进行修复。
使用热插拔卷的前置条件是先在kubevirt中启用HotplugVolumes特性
为虚拟机添加热插拔卷步骤¶
-
要使用热插拔卷,需要先准备一个能被VM使用的卷,可以是DV(DataVolume),此处创建了一个空的DV
apiVersion: cdi.kubevirt.io/v1beta1 kind: DataVolume metadata: name: hotplug-vol01 spec: source: blank: {} pvc: storageClassName: "ceph-hdd-block" accessModes: - ReadWriteOnce resources: requests: storage: 5Gi上述yaml示例使用的accessMode模式是ReadWriteOnce,volumeMode是Filesystem,可通过pvc信息进行查看。 如果存储支持,卷热插拔支持块存储卷模式为ReadWriteMany/ReadWriteOnce/ReadOnlyMany的所有组合。
-
使用virtctl命令为VM添加热插拔卷,并可以使用
注意 这条命令会将卷热插拔到正在运行的--persist来持久化卷vm-ubuntu01中,并将磁盘的序列号设置为卷名称,也就是hotplug-vol01;——persist表示永久添加该卷,这意味着该卷已经定义在VM中,即使重新启动VM,卷仍然存在。 即例使用virtctl removevolume移除热插拔卷,也会在虚拟机下次重启时又插回到虚拟机中,这是因为--persist参数已经将该卷的定义添到了VM中,所以删除时也要加上virtctl removevolume xx --persist同时删除定义。 -
进入到虚拟机,查看到多了一块sda的磁盘
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS loop0 7:0 0 63.9M 1 loop /snap/core20/2105 loop1 7:1 0 114.4M 1 loop /snap/lxd/26741 loop2 7:2 0 40.4M 1 loop /snap/snapd/20671 sda 8:0 0 4.7G 0 disk vda 252:0 0 10G 0 disk ├─vda1 252:1 0 9.9G 0 part / ├─vda14 252:14 0 4M 0 part └─vda15 252:15 0 106M 0 part /boot/efi vdb 252:16 0 1M 0 disk # ls -l /dev/disk/by-id/ scsi-0QEMU_QEMU_HARDDISK_hotplug-vol01 scsi-SQEMU_QEMU_HARDDISK_hotplug-vol01新增了一个热插拔卷的pod,这个pod的名字可以在相应VMI的
status.volumeStatus中查看到为什么磁盘是sda而不是vdc(这里的vdb是cloudinit挂载的卷)? 因为热插拔卷使用的是# kubectl get pods NAME READY STATUS RESTARTS AGE hp-volume-2jbmz 1/1 Running 0 23m virt-launcher-vm-ubuntu01-tmck4 2/2 Running 0 35mvirtio-scsi。总线类型是scsi磁盘,而非常规的virtio磁盘。原因在于virtio磁盘存在一个限制,即每个磁盘在虚拟机中都会占用一个PCIe插槽,而PCIe插槽数量最多为32个。 这就意味着可以热插拔磁盘的数量上限较低,特别是考虑到其他硬件设备也需要占用PCIe插槽的情况下。另一个问题是这些插槽需要预先预留。因此,如果无法提前知道热插拔磁盘的确切数量,就无法正确预留所需的插槽数目。
为了解决这个问题,每个虚拟机都配置了一个virtio-scsi控制器,该控制器允许使用scsi总线来挂载热插拔磁盘。
通过这种方式,virtio-scsi控制器能够支持超过400万块磁盘的热插拔操作。而且,根据相关性能测试显示,virtio-scsi与virtio在性能上非常接近,具体可参考github
- 可以指定热插拔卷的序列号
在添加热插拔卷时,是可以加上
--serial参数,来指定热插拔卷的序列号## 先移除,再重新添加 # virtctl removevolume vm-ubuntu01 --volume-name=hotplug-vol01 Successfully submitted remove volume request to VM vm-ubuntu01 for volume hotplug-vol01 ## 添加热插拔卷,并指定序列号 # virtctl addvolume vm-ubuntu01 --volume-name=hotplug-vol01 --serial=012345678910 ## 查看 # ls -l /dev/disk/by-id/ total 0 lrwxrwxrwx 1 root root 9 Feb 20 06:04 scsi-0QEMU_QEMU_HARDDISK_012345678910 -> ../../sda lrwxrwxrwx 1 root root 9 Feb 20 06:04 scsi-SQEMU_QEMU_HARDDISK_012345678910 -> ../../sda
查看热插拔卷状态信息¶
当执行了添加卷的热插拔操作后(例如,在addvolume示例中),VMI对象的status部分将会包含关于新热插拔卷的详细状态信息。 这意味着通过查看VMI的status.VolumeStatus字段,我们可以清晰地了解到所有磁盘的当前状态,这对于监控、管理和排查虚拟机实例的存储问题非常有用。
- vda通常代表包含操作系统(vm-ubuntu01)的磁盘; - vdb则是cloudinit磁盘。 - 每个卷都有一个# kubectl get vmi vm-ubuntu01 -o yaml ... status: ... volumeStatus: - name: cloudinitdisk size: 1048576 target: vdb - hotplugVolume: attachPodName: hp-volume-2jbmz attachPodUID: 5f608032-a09e-4f61-b88a-d154eb0d3088 message: Successfully attach hotplugged volume hotplug-vol01 to VM name: hotplug-vol01 persistentVolumeClaimInfo: accessModes: - ReadWriteOnce capacity: storage: 5Gi filesystemOverhead: "0.055" requests: storage: 5Gi volumeMode: Filesystem phase: Ready reason: VolumeReady target: sda - name: root-disk persistentVolumeClaimInfo: accessModes: - ReadWriteMany capacity: storage: 10Gi filesystemOverhead: "0" requests: storage: 10Gi volumeMode: Block target: vdatarget,这个target是指向QEMU虚拟机监控程序的唯一标识符,在将磁盘分配给虚拟机时使用,target的值对于每个VM来说都是唯一的。 -attachPodName记录了用于将该卷挂载到运行VMI节点上的Pod名称。如果这个Pod被删除,那么VMI也将停止运行,因为无法确保卷会继续保留在节点上。 - 当卷的phase为ready时,就表示可以被虚拟机使用了。
删除热插拔卷¶
# virtctl removevolume vm-ubuntu01 --volume-name=hotplug-vol01
Successfully submitted remove volume request to VM vm-ubuntu01 for volume hotplug-vol01
## 永久删除,包括删除了VM中热插拔卷的定义
# virtctl removevolume vm-ubuntu01 --volume-name=hotplug-vol01 --persist
有热插拔卷的VM也支持实时迁移¶
目前,允许任何带有热插拔卷的VMI进行实时迁移。但是,有一个已知问题,就是目标节点使用了CPU管理器,并且其策略设置为静态(static policy),同时使用的runc版本早于v1.0.0, 那么对于带有热插拔块存储卷(block volumes)的VMI,在迁移过程中可能会失败。