1 - 下载
下载
github 下载地址:
https://github.com/cloud-hypervisor/cloud-hypervisor/releases/

x86
x86平台下载:
mkdir -p ~/work/soft/cloudhypervisor/bin
cd ~/work/soft/cloudhypervisor/bin
wget https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v50.0/ch-remote
wget https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v50.0/cloud-hypervisor
wget https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v50.0/ch-remote-static
wget https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v50.0/cloud-hypervisor-static
chmod +x ./ch-remote
chmod +x ./cloud-hypervisor
chmod +x ./ch-remote-static
chmod +x ./cloud-hypervisor-static
# 验证一下版本
./cloud-hypervisor --version
./cloud-hypervisor-static --version
./ch-remote --version
./ch-remote-static --version
版本输出为:
$ ./cloud-hypervisor-static --version
cloud-hypervisor v50.0.0
$ ./cloud-hypervisor --version
[1] 10062 segmentation fault ./cloud-hypervisor --version
$ ./ch-remote --version
ch-remote v50.0.0
$ ./ch-remote-static --version
ch-remote v50.0.0
cloud-hypervisor 不能用.这是因为带 static 的二进制文件是静态编译版本,所有依赖库都已经打包在可执行文件里;不带 static 的则是动态链接版本,运行时需要系统上存在相应的共享库。如果系统缺少或版本不匹配,就可能出现 segmentation fault。
方便起见,还是直接用 static 版本比较好.
mkdir -p ~/work/soft/cloudhypervisor/bin
cd ~/work/soft/cloudhypervisor/bin
wget https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v50.0/ch-remote-static -O ch-remote
wget https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v50.0/cloud-hypervisor-static -O cloud-hypervisor
chmod +x ./ch-remote
chmod +x ./cloud-hypervisor
# 验证一下版本
./cloud-hypervisor --version
./ch-remote --version
arm64
类似,下载 cloud-hypervisor-static-aarch64 和 ch-remote-static-aarch64.
安装
将二进制文件所在的目录加入到 path 就可以了,这样用起来比较方便.
vi ~/.zshrc
加入内容:
# cloud hypervisor
export PATH="$PATH:$HOME/work/soft/cloudhypervisor/bin"
生效并检验:
source ~/.zshrc
ch-remote --version
cloud-hypervisor --version
升级
貌似只要直接覆盖原来版本的文件即可.
2 - 构建
也可以不下载,自己从源码开始构建.
参考: https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/building.md
准备
机器信息:
- 操作系统: debian13
- 内核: 6.12
准备工作:
mkdir -p $HOME/work/soft/cloudhypervisor
export CLOUDH=$HOME/work/soft/cloudhypervisor
cd $CLOUDH
安装依赖包:
sudo apt-get update
sudo apt install git build-essential m4 bison flex uuid-dev qemu-utils musl-tools
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add x86_64-unknown-linux-musl
构建
clone 代码并开始构建:
mkdir -p ~/work/code/cloud-hypervisor
cd ~/work/code/cloud-hypervisor
git clone https://github.com/cloud-hypervisor/cloud-hypervisor.git
cd cloud-hypervisor
# 最新的 release tag
git checkout v50.0
# 采用静态链接
cargo build --release --target=x86_64-unknown-linux-musl --all
sudo setcap cap_net_admin+ep ./target/x86_64-unknown-linux-musl/release/cloud-hypervisor
检查构建之后的版本:
./target/x86_64-unknown-linux-musl/release/cloud-hypervisor --version
cloud-hypervisor v50.0
ls -lh ./target/x86_64-unknown-linux-musl/release/cloud-hypervisor
-rwxrwxr-x 2 sky sky 4.0M Nov 18 15:23 ./target/x86_64-unknown-linux-musl/release/cloud-hypervisor
静态链接也才4M,没大多少.
3 - 启动
参考:
https://www.cloudhypervisor.org/docs/prologue/quick-start/#booting-linux
在 linux 上启动.
Cloud Hypervisor 支持直接内核启动(x86-64内核需使用支持PVH构建的内核)或通过固件/firmware启动(可选Rust Hypervisor固件或名为 CLOUDHV/CLOUDHV_EFI 的edk2 UEFI固件)。
最新版本的Rust Hypervisor固件及edk2存储库中均提供固件文件的二进制构建版本。
固件的选择取决于您的客户操作系统选项,可能需要进行一些实验性测试。
固件启动
Cloud Hypervisor 支持引导包含运行云工作负载所需全部组件的磁盘镜像,即云镜像。
准备工作
首先安装 qemu-utils,稍后要用到其中的 qemu-img 和 mkdosfs :
sudo apt install qemu-utils
sudo apt install dosfstools
sudo apt install mtools
以下示例命令将下载Ubuntu云镜像,将其转换为 Cloud Hypervisor 可用的格式,并生成引导该镜像所需的固件。
mkdir -p ~/work/soft/cloudhypervisor/fireware
cd ~/work/soft/cloudhypervisor/fireware
wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
wget https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/download/0.5.0/hypervisor-fw
处理完成后的文件列表:
$ ls -lh
total 2.1G
-rw-rw-r-- 1 sky sky 618M Jun 25 09:39 focal-server-cloudimg-amd64.img
-rw-r--r-- 1 sky sky 2.2G Oct 16 16:54 focal-server-cloudimg-amd64.raw
-rw-rw-r-- 1 sky sky 133K Nov 30 2024 hypervisor-fw
Ubuntu云镜像默认不提供密码,因此首次启动时必须使用 cloud-init 磁盘镜像进行镜像定制。本脚本可生成基础 cloud-init 镜像,为镜像预设默认用户名/密码为 cloud/cloud123 。仅需在首次启动时添加此磁盘镜像即可。脚本同时通过 --net “mac=12:34:56:78:90:ab,tap=” 选项,基于 test_data/cloud-init/ubuntu/local/network-config 配置信息分配默认IP地址。随后系统将根据 network-config 详情启用匹配MAC地址的网络接口。
准备需要的脚本, 在代码仓库根目录下的 scripts 中:
https://github.com/cloud-hypervisor/cloud-hypervisor/tree/v48.0/scripts
后面还要使用到 test_data/cloud-init/ubuntu/ 目录下的文件, 因此最好是把整个代码仓库下载下来,方便后面使用
mkdir -p ~/work/code/cloud-hypervisor/
cd ~/work/code/cloud-hypervisor/
git clone https://github.com/cloud-hypervisor/cloud-hypervisor.git
cd cloud-hypervisor
git checkout v50.0
执行:
~/work/code/cloud-hypervisor/cloud-hypervisor/scripts/create-cloud-init.sh
输出如下:
+ rm -f /tmp/ubuntu-cloudinit.img
+ mkdosfs -n CIDATA -C /tmp/ubuntu-cloudinit.img 8192
mkfs.fat 4.2 (2021-01-31)
+ mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/local/user-data ::
+ mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/local/meta-data ::
+ mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/local/network-config ::
这会生成一个 ubuntu-cloudinit.img 文件,大小为 8M:
$ ls -lh /tmp/ubuntu-cloudinit.img
-rw-rw-r-- 1 sky sky 8.0M Oct 16 17:12 /tmp/ubuntu-cloudinit.img
注意这个目录是 /tmp,重启之后文件很可能就不在了,方便起见, 还是复制到
mkdir -p ~/work/soft/cloudhypervisor/images
mv /tmp/ubuntu-cloudinit.img /home/sky/work/soft/cloudhypervisor/images
启动
注意: 从 v49 版本开始需要设置 cloud-hypervisor 二进制的特权, 执行命令:
sudo setcap cap_net_admin+ep /home/sky/work/code/cloud-hypervisor/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor
否则后面启动时会报错:
cloud-hypervisor: 0.016376s: <main> ERROR:/home/sky/work/code/cloud-hypervisor/cloud-hypervisor/src/lib.rs:23 -- Fatal error: VmBoot(VmBoot(DeviceManager(CreateVirtioNet(OpenTap(TapOpen(ConfigureTap(Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" })))))))
Error: Cloud Hypervisor exited with the following chain of errors:
0: Error booting VM
1: The VM could not boot
2: Error from device manager
3: Cannot create virtio-net device
4: Failed to open taps
5: Open tap device failed
6: Unable to configure tap interface
7: Operation not permitted (os error 1)
注意启动命令中的路径要用绝对路径,不能用 ‘~/’ 之类,否则会报错无法找到文件.
/home/sky/work/code/cloud-hypervisor/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor \
--kernel /home/sky/work/soft/cloudhypervisor/fireware/hypervisor-fw \
--disk path=/home/sky/work/soft/cloudhypervisor/fireware/focal-server-cloudimg-amd64.raw path=/home/sky/work/soft/cloudhypervisor/images/ubuntu-cloudinit.img \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask="
输出为:
cloud-hypervisor: 481.142000µs: <main> WARN:vmm/src/vm_config.rs:356 -- Deprecation warning: No IP address provided. A default IP address is assigned. This behavior will be deprecated soon.
cloud-hypervisor: 506.863000µs: <main> WARN:vmm/src/vm_config.rs:363 -- Deprecation warning: No network mask provided. A default network mask is assigned. This behavior will be deprecated soon.
Ubuntu 20.04.6 LTS cloud hvc0
cloud login:
输入前面设置的用户/密码 (cloud / cloud123), 登录进去, 如果要退出,执行 sudo shutdown now 命令关闭启动的 microVM 即可.
此时因为没有配置好网络, 所以登录进去 microVM 后会发现没有网络可用.
配置microVM的网络
没成功,等下继续.
首先要在主机上创建并配置 TAP 接口:
sudo ip tuntap add name vm-tap0 mode tap user $(whoami)
sudo ip link set vm-tap0 up
sudo ip addr add 192.168.1.127/24 dev vm-tap0
此时在主机上看到的 vm-tap0 设备为:
$ ip addr
......
10: vm-tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 3e:7b:2e:ca:9a:3e brd ff:ff:ff:ff:ff:ff
inet 192.168.1.127/24 scope global vm-tap0
valid_lft forever preferred_lft forever
注意:上面的 ip 命令在重启后会失效。若需持久化配置,可将其写入主机的网络配置文件(如 /etc/network/interfaces 或使用 systemd-networkd/NetworkManager)。
注意2: 如果配置有问题,可以先删除,再重新配置. sudo ip link delete vm-tap0
/home/sky/work/code/cloud-hypervisor/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor \
--kernel /home/sky/work/soft/cloudhypervisor/fireware/hypervisor-fw \
--disk path=/home/sky/work/soft/cloudhypervisor/fireware/focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--cpus boot=4 \
--memory size=1024M \
--net "tap=vm-tap0,mac=12:34:56:78:90:22,ip=192.168.1.129,mask=255.255.255.0"
/home/sky/work/code/cloud-hypervisor/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor \
--kernel /home/sky/work/soft/cloudhypervisor/fireware/hypervisor-fw \
--disk path=/home/sky/work/soft/cloudhypervisor/fireware/focal-server-cloudimg-amd64.raw path=/home/sky/work/soft/cloudhypervisor/images/ubuntu-cloudinit.img \
--cpus boot=4 \
--memory size=1024M \
--net "tap=tap0,mac=12:34:56:78:90:22,ip=192.168.1.10,mask=255.255.255.0"
镜像启动
Cloud Hypervisor 也支持直接内核启动。对于 x86-64 架构,需要一个 vmlinux ELF 内核(编译时包含 PVH 支持)。为了支持开发,有一个自定义分支;不过只要所需选项已启用,任何近期的内核都可以使用。
构建 linux 内核
要构建内核:
cd ~/work/code/cloud-hypervisor/
git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.12.8 linux-cloud-hypervisor
cd linux-cloud-hypervisor
make ch_defconfig
sudo apt install libelf-dev
sudo apt install bc
注意要执行 sudo apt install libelf-dev 命令安装 libelf,否则会报错:
<stdin>:1:10: fatal error: libelf.h: No such file or directory
构建 x86-64 kernel:
KCFLAGS="-Wa,-mx86-used-note=no" make bzImage -j `nproc`
构建完成后,linux 内核保存在 ./arch/x86/boot/compressed/vmlinux.bin,大小为 45M:
$ ls -lh ./arch/x86/boot/compressed/vmlinux.bin
-rwxrwxr-x 1 sky sky 45M Nov 18 15:50 ./arch/x86/boot/compressed/vmlinux.bin
rootfs 磁盘镜像可以用之前下载的 ubuntu 镜像, 之前存放在目录 ~/work/soft/cloudhypervisor/fireware 下
也可以再次下载和转换:
cd ~/work/soft/cloudhypervisor/fireware
wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img # x86-64
wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-arm64.img # AArch64
qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw # x86-64
qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-arm64.img focal-server-cloudimg-arm64.raw # AArch64
启动 vm:
/home/sky/work/code/cloud-hypervisor/cloud-hypervisor/target/x86_64-unknown-linux-musl/release/cloud-hypervisor \
--kernel /home/sky/work/code/cloud-hypervisor/linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
--console off \
--serial tty \
--disk path=/home/sky/work/soft/cloudhypervisor/fireware/focal-server-cloudimg-amd64.raw \
--cmdline "console=ttyS0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask="
4 - 命令
参考:
https://www.cloudhypervisor.org/docs/prologue/commands/
cloud-hypervisor
通过 help 命令可以得到参数和参数说明:
cloud-hypervisor --help
-
--api-socket <api-socket>HTTP API socket (UNIX domain socket): path=
</path/to/a/file> or fd=<fd> -
-
-balloon <balloon>Balloon parameters
“size=<balloon_size>,deflate_on_oom=on|off”
-
--cmdline <cmdline>Kernel command line
-
--console <console>Control (virtio) console: “off|null|pty|tty|file=</path/to/a/file>,iommu=on|off”
[default: tty]
-
--cpus <cpus>boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on[default: boot=1,max_phys_bits=46]
-
--debug-console <debug-console>off|pty|tty|file=</path/to/a/file>,iobase=
<port in hex>[default:off,iobase=0xe9]
-
--device <device>...Direct device assignment parameters
“path=<device_path>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>”
-
--disk <disk>...Disk parameters
“path=<disk_image_path>,readonly=on|off,direct=on|off,iommu=on|off,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,vhost_user=on|off,socket=<vhost_user_socket_path>,bw_size=
,bw_one_time_burst= ,bw_refill_time= ,ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time= ,id=<device_id>,pci_segment=<segment_id>,rate_limit_group=<group_id>,queue_affinity=<list_of_queue_indices_with_their_associated_cpuset>,serial=<serial_number>” -
--event-monitor <event-monitor>File to report events on:
path=</path/to/a/file> or fd=<fd> -
--firmware <firmware>File to report events on:
path=</path/to/a/file> or fd=<fd> -
--fs <fs>...virtio-fs parameters “tag=<tag_name>,socket=<socket_path>,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,pci_segment=<segment_id>”
-
--initramfs <initramfs>Path to initramfs image
-
--kernel <kernel>Path to kernel to load. This may be a kernel or firmware that supports a PVH entry point (e.g. vmlinux) or architecture equivalent
-
--landlockenable/disable Landlock.
-
--landlock-rules <landlock-rules>...Landlock parameters “path=<path/to/{file/dir}>,access=[rw]”
-
--log-file <log-file>Log file. Standard error is used if not specified
-
--memory <memory>“size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,hugepage_size=<hugepage_size>,hotplug_method=acpi|virtio-mem,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>,prefault=on|off,thp=on|off”
[default: size=512M]
-
--memory-zone <memory-zone>...User defined memory zone parameters
“size=<guest_memory_region_size>, file=<backing_file>, shared=on|off, hugepages=on|off, hugepage_size=<hugepage_size>, host_numa_node=<node_id>, id=<zone_identifier>, hotplug_size=<hotpluggable_memory_size>, hotplugged_size=<hotplugged_memory_size>, prefault=on|off”
-
--net <net>...Network parameters
“tap=<if_name>,ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>,fd=<fd1,fd2…>,iommu=on|off,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>, vhost_user=<vhost_user_enable>, socket=<vhost_user_socket_path>, vhost_mode=client|server, bw_size=
,bw_one_time_burst= , bw_refill_time= , ops_size=<io_ops>, ops_one_time_burst=<io_ops>, ops_refill_time= , pci_segment=<segment_id>offload_tso=on|off, offload_ufo=on|off, offload_csum=on|off” -
--numa <numa>...Settings related to a given NUMA node
“guest_numa_id=<node_id>, cpus=<cpus_id>, distances=<list_of_distances_to_destination_nodes>, memory_zones=<list_of_memory_zones>, pci_segments=<list_of_pci_segments>”
-
--pci-segment <pci-segment>...PCI Segment parameters
“pci_segment=<segment_id>, mmio32_aperture_weight=
, mmio64_aperture_weight= ” -
--platform <platform>num_pci_segments=<num_pci_segments>, iommu_segments=<list_of_segments>, iommu_address_width=<bits>, serial_number=<dmi_device_serial_number>, uuid=<dmi_device_uuid>, oem_strings=<list_of_strings> -
--pmem <pmem>...Persistent memory parameters
“file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,discard_writes=on|off,id=<device_id>,pci_segment=<segment_id>”
-
--pvpanicEnable pvpanic device
-
--rate-limit-group <rate-limit-group>...Rate Limit Group parameters
"bw_size=<bytes>, bw_one_time_burst=<bytes>, bw_refill_time=<ms>, ops_size=<io_ops>, ops_one_time_burst=<io_ops>, ops_refill_time=<ms>, id=<device_id>" -
--restore <restore>Restore from a VM snapshot.
Restore parameters
"source_url=<source_url>, prefault=on|off, net_fds=<list_of_net_ids_with_their_associated_fds>"source_urlshould be a valid URL (e.g file:///foo/bar or tcp://192.168.1.10/foo)prefaultbrings memory pages in when enabled (disabled by default)net_fdsis a list of net ids with new file descriptors. Only net devices backed by FDs directly are needed as input. -
--rng <rng>Random number generator parameters “src=<entropy_source_path>,iommu=on|off”
[default: src=/dev/urandom]
-
--seccomp <seccomp>[default: true] [possible values: true, false, log]
-
--serial <serial>Control serial port:
off|null|pty|tty|file=</path/to/a/file>|socket=</path/to/a/file>[default: null]
-
--tpm <tpm>TPM device “(UNIX Domain Socket from swtpm) socket=
</path/to/a/socket>” -
--user-device <user-device>...Userspace device socket=
<socket_path>,id=<device_id>,pci_segment=<segment_id> -
-v...Sets the level of debugging output
-
--vdpa <vdpa>...vDPA device
“path=<device_path>,num_queues=<number_of_queues>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>”
-
-V, --versionPrint version
-
--vsock <vsock>Virtio VSOCK parameters
“cid=<context_id>, socket=<socket_path>, iommu=on|off, id=<device_id>, pci_segment=<segment_id>”
-
--watchdogEnable virtio-watchdog
-
-h, --helpPrint help
ch-remote
通过 help 命令可以得到参数和参数说明:
ch-remote --help
| 命令 | 命令描述 |
|---|---|
| add-device | Add VFIO device |
| add-disk | Add block device |
| add-fs | Add virtio-fs backed fs device |
| add-net | Add network device |
| add-pmem | Add persistent memory device |
| add-user-device | Add userspace device |
| add-vdpa | Add vDPA device |
| add-vsock | Add vsock device |
| boot | Boot a created VM |
| coredump | Create a coredump from VM |
| counters | Counters from the VM |
| create | Create VM from a JSON configuration |
| delete | Delete a VM |
| info | Info on the VM |
| nmi | Trigger NMI |
| pause | Pause the VM |
| ping | Ping the VMM to check for API server availability |
| power-button | Trigger a power button in the VM |
| reboot | Reboot the VM |
| receive-migration | Receive a VM migration |
| remove-device | Remove VFIO and PCI device |
| resize | Resize the VM |
| resize-zone | Resize a memory zone |
| restore | Restore VM from a snapshot |
| resume | Resume the VM |
| send-migration | Initiate a VM migration |
| shutdown | Shutdown the VM |
| shutdown-vmm | Shutdown the VMM |
| snapshot | Create a snapshot from VM |
| help | Print this message or the help of the given subcommand(s) |
命令行选项:
| 选项 | 选项描述 |
|---|---|
--api-socket <api-socket> |
HTTP API socket path (UNIX domain socket) |
| -h, –help | Print help |
| -V, –version | Print version |