热拔插
https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/hotplug.md
目前 cloud hypervisor 支持 CPU 设备(仅限 x86)、PCI 设备和内存调整的热插拔。
内核支持
在 cloud hypervisor 上进行热插拔需要 ACPI GED 支持。这可以通过开启 CONFIG_ACPI_REDUCED_HARDWARE_ONLY 或使用此内核补丁(在 5.5-rc1 及更高版本中可用):https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/drivers/acpi/Makefile?id=ac36d37e943635fc072e9d4f47e40a48fbcdb3f0
CPU 热插拔
额外的 vCPU 可以在运行的 cloud-hypervisor 实例中添加和移除。这由两种机制控制:
-
指定一个大于默认(boot)vCPU 数量的最大潜在 vCPU 数。
-
向 VMM 发出 HTTP API 请求,要求添加额外的 vCPU。
要使用 CPU 热插拔功能,请以大于启动 vCPU 数量的最大 vCPU 数启动虚拟机,例如。
$ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--cpus boot=4,max=8 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--rng \
--api-socket=/tmp/ch-socket
$ popd
注意 –api-socket=/tmp/ch-socket 和 max 参数在 –cpus boot=4,max=8 中的添加。
若要请求 VMM 添加额外的 vCPU,请使用 resize API:
./ch-remote --api-socket=/tmp/ch-socket resize --cpus 8
额外的 vCPU 线程将被创建并向运行中的内核进行通告。内核不会立即启动 CPU,相反,用户必须从虚拟机内部将它们 “online” 化:
root@ch-guest ~ # lscpu | grep list:
On-line CPU(s) list: 0-3
Off-line CPU(s) list: 4-7
root@ch-guest ~ # echo 1 | tee /sys/devices/system/cpu/cpu[4,5,6,7]/online
1
root@ch-guest ~ # lscpu | grep list:
On-line CPU(s) list: 0-7
重启后,添加的 CPU 将保持在线状态。
移除 CPU 的操作与减少 resize API 中"desired_vcpus"字段的数值类似。CPU 将在虚拟机内部自动下线,因此无需在虚拟机内部运行任何命令:
./ch-remote --api-socket=/tmp/ch-socket resize --cpus 2
关于向虚拟机添加 CPU,重启后虚拟机将以减少的 vCPU 数量运行。
内存热插拔
ACPI 方法
可以从正在运行的 cloud-hypervisor 实例中添加额外内存。这由两种机制控制:
-
为热插拔内存分配部分 guest 物理地址空间。
-
向 VMM 发起 HTTP API 请求,要求为虚拟机分配新的内存量。在为虚拟机扩展内存的情况下,新内存将被热插拔到正在运行的虚拟机中;如果减少内存大小,则更改将在下次重启后生效。
要使用内存热插拔,启动虚拟机时在内存配置的 hotplug_size 参数中指定一些 RAM 大小。这个参数中指定的所有内存并不都会用于热插拔,因为存在间隔和对齐要求,所以建议使其大于所需的热插拔 RAM 大小。
由于 ACPI 方法为默认选项,因此无需添加额外的选项 hotplug_method=acpi 。
$ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--cpus boot=4,max=8 \
--memory size=1024M,hotplug_size=8192M \
--net "tap=,mac=,ip=,mask=" \
--rng \
--api-socket=/tmp/ch-socket
$ popd
在发出 API 请求之前,需要在虚拟机内部运行以下命令,以使其自动上线添加的内存:
root@ch-guest ~ # echo online | sudo tee /sys/devices/system/memory/auto_online_blocks
要求 VMM 扩展虚拟机的 RAM:
./ch-remote --api-socket=/tmp/ch-socket resize --memory 3G
新内存现在可以在虚拟机内部使用:
free -h
total used free shared buff/cache available
Mem: 3.0Gi 71Mi 2.8Gi 0.0Ki 47Mi 2.8Gi
Swap: 32Mi 0B 32Mi
由于 guest 操作系统限制,必须确保添加的内存量(当前分配的 RAM 与所需 RAM 之间的差值)是 128MiB 的倍数。
相同的 API 也可以用来减少虚拟机的所需 RAM,但更改不会在虚拟机重新启动后生效。
内存和 CPU 调整可以组合在同一个 HTTP API 请求中。
virtio-mem 方法
额外的内存可以从正在运行的 Cloud Hypervisor 实例中添加和移除。这由两种机制控制:
-
为热插拔内存分配部分客户物理地址空间。
-
向 VMM 发起 HTTP API 请求,请求为虚拟机分配新的内存量。
要使用内存热插拔功能,启动虚拟机时需要在 hotplug_size 参数中指定一些内存大小,并在内存配置中使用 hotplug_method=virtio-mem 。
$ pushd $CLOUDH
$ sudo setcap cap_net_admin+ep ./cloud-hypervisor/target/release/cloud-hypervisor
$ ./cloud-hypervisor/target/release/cloud-hypervisor \
--kernel custom-vmlinux.bin \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--memory size=1024M,hotplug_size=8192M,hotplug_method=virtio-mem \
--net "tap=,mac=,ip=,mask=" \
--api-socket=/tmp/ch-socket
$ popd
要求 VMM 为虚拟机扩展 RAM(请求单位为字节):
./ch-remote --api-socket=/tmp/ch-socket resize --memory 3G
新内存现在可以在虚拟机内部使用:
相同的 API 也可以用来减少虚拟机的所需 RAM。需要注意的是,减少 RAM 大小可能只能部分生效,因为 guest 可能正在使用其中的一部分。
PCI 设备热插拔
添加 VFIO 设备
稍后看,目前没需要.
添加磁盘设备
要让 VMM 添加额外的磁盘设备,请使用 add-disk API。
./ch-remote --api-socket=/tmp/ch-socket add-disk path=/foo/bar/cloud.img
添加文件系统设备
要请求 VMM 添加额外的文件系统设备,请使用 add-fs API。
./ch-remote --api-socket=/tmp/ch-socket add-fs tag=myfs,socket=/foo/bar/virtiofs.sock
添加网络设备
要求 VMM 添加额外的网络设备,请使用 add-net API。
./ch-remote --api-socket=/tmp/ch-socket add-net tap=chtap0
添加 Pmem 设备
稍后看,目前没需要.
添加 Vsock 设备
若要请求 VMM 添加额外的 vsock 设备,请使用 add-vsock API。
./ch-remote --api-socket=/tmp/ch-socket add-vsock cid=3,socket=/foo/bar/vsock.sock
所有 PCI 设备的通用特性
额外的 PCI 设备将被创建并向正在运行的内核进行通告。新设备可以通过检查 PCI 设备列表来找到。
root@ch-guest ~ # lspci
00:00.0 Host bridge: Intel Corporation Device 0d57
00:01.0 Unassigned class [ffff]: Red Hat, Inc. Virtio console (rev 01)
00:02.0 Mass storage controller: Red Hat, Inc. Virtio block device (rev 01)
00:03.0 Unassigned class [ffff]: Red Hat, Inc. Virtio RNG (rev 01)
重启后,添加的 PCI 设备将保持存在。
移除 PCI 设备
移除 PCI 设备对所有类型的 PCI 设备都采用相同的方式。必须提供与设备相关的唯一标识符。此标识符可以在添加新设备时由用户提供,或者默认情况下由 Cloud Hypervisor 分配。
./ch-remote --api-socket=/tmp/ch-socket remove-device _disk0
在为虚拟机添加 PCI 设备后,重启后虚拟机将不再运行已移除的 PCI 设备。