- 虚拟化
- 开发工具
- 云原生
【免费下载链接】multipass
Multipass orchestrates virtual Ubuntu instances
本指南围绕 Multipass 提供的实例级设置键local.<instance-name>.cpus展开,讲解如何通过multipass set在运行时调整指定虚拟机实例的 CPU 核数、该设置键的合法取值与默认行为,并结合仓库源码揭示其在守护进程中的底层处理链路与各虚拟化后端的落地方式。读完本文,你将掌握查看、修改实例 CPU 配置的正确姿势,以及该设置键在 Multipass 内部如何被解析、校验和持久化。
关联说明:该设置键与
get、set、launch三个命令行接口配合使用;实例级设置的整体机制可参见 实例设置总览。
Key 的完整形式与含义
local.<instance-name>.cpus是 Multipass 的实例级设置键(instance-level setting key),其中:
local是 Multipass 守护进程设置(daemon settings)的根命名空间,源码中由mp::daemon_settings_root常量承载(见 src/daemon/instance_settings_handler.cpp);<instance-name>是目标 Multipass 实例的名称(例如handsome-ling、primary等);cpus是实例属性后缀,表示 CPU 核数。
该键所对应的值代表虚拟机模拟出的 CPU 数量,它从宿主机的角度规定了该实例「最多能同时使用多少个宿主机线程」。也就是说,这是一个上限约束:实例内可见的 vCPU 数量由该值决定,实例内的应用在任意时刻可并发执行的线程不会超过这一数值。
从源码结构看,Multipass 的实例设置处理器将实例属性划分为cpus、memory、disk、bridged四类(见 src/daemon/instance_settings_handler.cpp),并通过正则表达式%1\.%2\.%3(daemon_settings_root+ 实例名 + 属性名)解析用户传入的键(见 instance_settings_handler.cpp)。键格式不合法时会抛出UnrecognizedSettingException,而keys()方法则会为每个已注册实例动态生成形如local.<实例名>.cpus的完整键集合(见 instance_settings_handler.cpp)。
Description:该设置控制什么
local.<instance-name>.cpus决定虚拟机上模拟的 CPU 数量。这个值对运行中的实例建立了一个硬性上限:实例最多能同时使用多少个宿主机线程。
值得强调的是,这一设置与launch时通过--cpus指定的核数是同一套规格。在 Multipass 的守护进程内部,无论是launch命令的--cpus参数,还是set命令写入的cpus值,最终都收敛到同一个VMSpecs::num_cores字段(实例规格结构体)。例如在 src/daemon/daemon.cpp 中,launch创建实例时会校验vm_desc.num_cores是否小于mp::min_cpu_cores(其值为"1",见 include/multipass/constants.h),不满足则回退到默认值。
Possible values:合法取值与边界
文档规定该键的取值为正整数:
- Multipass 本身不设上限,数值上不限制最大值;
- 但底层虚拟化后端可能施加各自的限制(例如宿主机物理 CPU 核数、QEMU 后端可模拟的最大 vCPU 数、Hyper-V/Libvirt 的配额等),实际可设置的范围以所用后端为准。
在守护进程的实现中,set操作会对值做一次前置校验(见 instance_settings_handler.cpp 的update_cpus函数):
- 使用
QString::toInt将字符串转换为整数,转换失败(非十进制整数)即抛出InvalidSettingException; - 校验转换后的值是否小于
mp::min_cpu_cores(即1),小于 1 时抛出异常,错误信息为 "Need a positive integer (in decimal format) of minimum 1"; - 若新值与当前规格
spec.num_cores相同,则视为 NOOP,直接放行但不触发任何修改。
对应的单元测试覆盖了这些路径(见 tests/unit/test_instance_settings_handler.cpp):
setIncreasesInstanceCPUs:验证将 4 核提升到 6 核时,update_cpus(6)被精确调用一次,且规格同步更新;setMaintainsInstanceCPUsUntouchedIfSameButSucceeds:验证设置相同值(42 → 42)时不会调用update_cpus,但操作仍然成功(NOOP 语义);setAllowsDecreaseInstanceCPUs:验证将 3 核降为 2 核是被允许的(与memory只能扩容不同,CPU 核数可增可减)。
Examples:命令行使用示例
multipass set local.handsome-ling.cpus=4该命令将名为handsome-ling的实例的 CPU 核数设置为 4。其他典型用法:
# 读取某个实例当前的 CPU 核数 multipass get local.handsome-ling.cpus # 设置后确认结果 multipass get local.handsome-ling.cpus # 输出:4查看该设置键时,InstanceSettingsHandler::get直接返回spec.num_cores的十进制字符串形式(QString::number(spec.num_cores),见 instance_settings_handler.cpp),因此get的返回值总是纯整数格式。
修改的前提条件:实例必须处于停止状态
与memory、disk等运行时规格调整类似,修改cpus键有一个重要前置条件:目标实例必须处于stopped(已停止)或off(已关闭)状态。守护进程在InstanceSettingsHandler::set中会先调用check_state_for_update(见 instance_settings_handler.cpp),如果实例处于运行(running)或其他非停止状态,会抛出InstanceStateSettingsException,错误信息为 "Instance must be stopped for modification"。
因此正确的操作顺序是:
# 1. 停止实例 multipass stop handsome-ling # 2. 修改 CPU 核数 multipass set local.handsome-ling.cpus=4 # 3. 重新启动实例 multipass start handsome-ling此外,set还会拒绝以下场景(见 instance_settings_handler.cpp):
- 实例正在准备(preparing)过程中时抛出 "instance is being prepared";
- 实例已被删除(deleted)时抛出 "Instance is deleted" 错误。
修改成功后,守护进程会调用instance_persister()将新的规格(spec.num_cores)持久化,确保重启后设置依然生效。
Default value:默认值行为
该设置键的默认值是实例启动时(launch)所配置的 CPU 核数。也就是说:
- 创建实例时若未显式指定
--cpus,Multipass 会使用平台默认值。从源码看,mp::default_cpu_cores与mp::min_cpu_cores相同,均为"1"(见 include/multipass/constants.h),即默认单核; - 创建实例时若通过
multipass launch --cpus N指定了核数,则该值成为该实例的num_cores初始规格; - 之后对
local.<instance-name>.cpus的任何修改都会覆盖这一初始值,并持久化保存。
换句话说,get返回的值始终是「实例当前生效的核数」——它可能来自 launch 时的初始配置,也可能来自后续set的覆盖结果。
底层实现:从设置键到后端动作
为了让读者对该设置键有更立体的认知,下面梳理它在 Multipass 内部的完整链路。
1. 键解析与路由
InstanceSettingsHandler::set先通过parse_key把local.<instance-name>.cpus拆解为「实例名 + 属性名」,然后根据属性名分派到update_cpus(见 instance_settings_handler.cpp)。
2. 规格更新与实例通知
update_cpus在通过合法性校验后,会做两件事(见 instance_settings_handler.cpp):
- 调用
instance.update_cpus(cpus),通知对应的VirtualMachine实现更新其描述信息; - 同步更新
VMSpecs::num_cores = cpus,并随后触发持久化。
3. 各后端如何落地
update_cpus是VirtualMachine接口的虚函数,各平台后端均有实现:
- QEMU 后端:
QemuVirtualMachine::update_cpus仅将核数写入desc.num_cores(断言num_cores > 0),实际的 vCPU 拓扑在下次启动虚拟机时由 QEMU 参数生成逻辑读取(见 src/platform/backends/qemu/qemu_virtual_machine.cpp); - Hyper-V 后端:
update_cpus(int num_cores)在 hyperv_virtual_machine.h 中声明,由 Hyper-V 平台实现调用 PowerShell/WMI 接口调整虚拟机处理器数量; - Hyper-V API(HCS)后端:见 hcs_virtual_machine.h;
- Apple 虚拟化框架后端(applevz):见 applevz_virtual_machine.h;
- VirtualBox 后端:见 virtualbox_virtual_machine.h。
从源码结构可以推断:QEMU 等后端在实例停止期间修改描述信息、下次启动时重新生成虚拟机配置(--smp/-smp等参数会基于num_cores计算),因此 CPU 调整对运行中的实例不生效,这也从实现层面印证了「必须停止实例才能修改」的约束。
注意事项与最佳实践
- 先停后改:修改
local.<instance-name>.cpus前必须停止实例,否则守护进程直接拒绝操作。 - 值必须为正整数:
0、负数、小数或非数字字符串都会被拒绝,报错信息为 "Need a positive integer (in decimal format) of minimum 1"。 - Multipass 不设上限,但后端有限制:取值过大会导致后端报错或启动失败,建议按宿主机物理核数合理规划;例如在 QEMU 后端下,模拟核数不应超过宿主机可用 CPU 资源。
- 设置是持久的:修改后的核数会写入实例规格并持久化,重启宿主机或 Multipass 守护进程后依然生效;
multipass get local.<instance-name>.cpus可随时确认当前生效值。 - 与
launch --cpus的关系:launch指定的是初始值,set是在实例生命周期内做二次调整,两者作用于同一个num_cores规格字段。 - 同值设置是安全的 NOOP:即使实例已停止,设置与当前值相同的核数也不会产生任何副作用,操作直接成功。
延伸阅读
- 设置键的读取与写入命令:get、set
- 创建实例并指定初始 CPU:launch
- 实例级设置的其他键:
local.<instance-name>.memory(内存)、local.<instance-name>.disk(磁盘)、local.<instance-name>.bridged(桥接网络),总览见 实例设置文档 - 设置键语法与取值规则汇总:settings-keys-values
- 核心实现:instance_settings_handler.cpp、instance_settings_handler.h、constants.h
- 测试用例:test_instance_settings_handler.cpp
- 虚拟化
- 开发工具
- 云原生
【免费下载链接】multipass
Multipass orchestrates virtual Ubuntu instances
相关推荐
如何在 macOS 上从源码构建 Lynx Explorer 并打包 LynxSDK
如何在 macOS 上从源码构建 Lynx Explorer 并打包 LynxSDK 在 macOS 上从 Lynx 源码构建可运行的 LynxExplorer
虚拟化开发工具云原生Dagster+ GraphQL API 调用返回 UnauthorizedError 怎么排查?
Dagster+ GraphQL API 调用返回 UnauthorizedError 怎么排查? 调用 Dagster+ 的 GraphQL API 时,即使
虚拟化开发工具云原生FastMCP MCPMixin 组件化指南:用类方法与装饰器批量注册 Tool / Resource / Prompt
FastMCP MCPMixin 组件化指南:用类方法与装饰器批量注册 Tool / Resource / Prompt 本文以 fastmcp_slim/fa
虚拟化开发工具云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考