在novaclient创建虚拟机的场景中,指定自定义镜像的核心参数是--image,后面直接跟镜像的ID或名称,例如nova boot --image 你的镜像ID --flavor 2 实例名。这个参数是整个创建命令里最容易踩坑的一环,因为很多人会把镜像名和镜像ID混用,或者压根不知道如何先确认自定义镜像已经上传成功,下面把配置路径、排查方法和常见错误一次讲清楚。
自定义镜像参数的完整配置流程
第一步:确认自定义镜像已经存在于环境中
不管是自己用openstack image create上传的qcow2镜像,还是从其他平台转换过来的镜像,在nova client里调用前,必须先让glance服务能看到它,使用glance image-list或者openstack image list来查看,如果列表里找不到你的自定义镜像,后面一切配置都无从谈起。
有个细节经常被忽略:镜像的可见性(visibility)必须是public或shared,如果你用普通项目上传的镜像默认是private,那么用另一个项目的账号去跑nova boot时,--image参数就会报找不到镜像,业内专家指出,这是多云管理环境下最常见的权限类故障源头。
第二步:在nova boot命令中正确书写--image参数
nova client(命令行工具)创建虚拟机的基础命令结构如下:
nova boot --flavor <规格ID> --image <镜像ID或名称> --nic net-id=<网络ID> 实例名称
其中--image参数的关键规则:
- 接受镜像ID(UUID),这是最稳妥的方式,因为UUID全局唯一。
- 也接受镜像名称,但如果环境里存在同名镜像,命令会直接报错
Multiple matches found for <名称>。 - 镜像ID或名称前后不要加引号或等号,
--image 9d8e0f2a-...就是标准写法。
举个例子,假设你上传了一个名为centos7-custom的镜像,想用2核4G的flavor创建一台名叫web-01的机器,完整的命令是:
nova boot --image centos7-custom --flavor 4 web-01
但更推荐先查到镜像ID再执行:

glance image-list | grep centos7-custom
拿到那串UUID后,换成:
nova boot --image 3f8e9d2a-6c1b-4e5d-9a0f-123456789abc --flavor 4 web-01
这样能彻底绕开同名镜像的干扰。
第三步:处理不支持--image参数的情况
如果执行命令时报错unrecognized arguments: --image,说明你用的不是nova client,而是openstack client,两者的参数风格完全不同,openstack client创建虚拟机的命令为:
openstack server create --image <镜像ID> --flavor <规格ID> 实例名
逻辑一样,但命令动词从boot换成了server create,如果是混合使用的环境,建议直接用openstack server create,因为它同时兼容计算、网络、镜像服务,能少装一个nova客户端。
自定义镜像参数配错的三大典型症状
报错"Image not found"或"Image cannot be found"
原因表面上是指定的镜像ID不存在,实际上多数是镜像还没上传完成,或者项目间权限隔离导致看不到,排查顺序:
- 用
openstack image show <镜像ID>确认镜像是否处于active状态。 - 检查镜像的
visibility字段是否为你当前项目可见。 - 如果镜像是从其他环境导出的,确认导入时没有遗漏
--disk-format和--container-format参数。
报错"Image has no disk"或"Image not active"
这类错误通常发生在镜像格式不对或镜像缓存未就绪时,nova计算节点需要把glance里的镜像下载到本地缓存,如果源镜像损坏或格式非raw/qcow2,就会中途失败,行业共识认为,绝大多数自定义镜像启动失败都源于qemu-img转换时未正确指定磁盘大小,比如从VMware的vmdk转换时,没有执行qemu-img convert -O qcow2,而是直接改了文件后缀名,那nova拿到后必然报错。
解决思路:重新用qemu-img工具转换,并确认镜像大小不为0,转换命令:
qemu-img convert -f vmdk -O qcow2 source.vmdk custom.qcow2

能用--image创建但无法启动
这种情况最让人头疼,虚拟机状态是ERROR,查控制台日志发现找不到引导设备,原因多是自定义镜像内部没有安装cloud-init或相关驱动,nova虽然把镜像注入到了虚拟机,但虚拟机无法自动配置网络和初始化密码,导致启动后没有IP,此时需要回头检查镜像内部是否安装了cloud-init包,以及是否开启了virtio驱动,如果镜像没做任何优化,第一次创建大概率会失败。
自定义镜像与密钥、安全组的搭配策略
指定了自定义镜像,并不代表其他创建参数可以随意,很多用户只关心--image,却忽略了与之强关联的--key-name和--security-groups。自定义镜像默认不会自动启用密码登录,如果想用密钥登录,必须在创建时就绑定好密钥对,具体命令:
nova boot --image <自定义镜像ID> --flavor 2 --key-name mykey --security-groups default my-instance
对于跨区域使用场景,比如在华东1、华北2等多个region同时创建虚拟机,镜像ID在每个region是不同的,不要指望同一个镜像ID能跨区域使用,你需要先在目标区域重新上传镜像,拿到新的UUID再配置,这属于镜像复制与同步的范畴。
如何验证自定义镜像参数是否配置成功
创建命令执行后,不能只盯着返回结果,推荐三步验证法:
- 查看虚拟机列表,确认状态由
BUILD变成ACTIVE。 - 使用
nova show <实例名>查看image字段,确认显示的镜像ID和你输入的一致。 - 通过VNC控制台或ping测试,确认系统真正启动。
如果状态卡在BUILD超过3分钟,直接看计算节点的日志,常见于镜像过大(超过10GB)导致下载超时,但nova client不会在客户端报错,只会让虚拟机状态一直处于BUILD,这种情况下,可以优化镜像大小,或调整计算节点上的nova.conf中的image_cache相关参数。
自定义镜像参数配置的进阶技巧
使用环境变量简化参数
经常在多个环境间切换的运维同学,可以先把默认值固化在环境变量里。

export OS_IMAGE_ID=3f8e9d2a-6c1b-4e5d-9a0f-123456789abc nova boot --flavor 2 --image $OS_IMAGE_ID test-instance
这样可以避免每次手抄一长串UUID,也减少拼错的风险。
通过脚本批量创建
当需要同时创建多台基于同一自定义镜像的虚拟机时,可以写个简单的for循环:
for i in 01 02 03; do
nova boot --image $IMAGE_ID --flavor 2 --availability-zone az1 web-$i
done
注意--availability-zone参数,如果自定义镜像需要被创建到特定物理节点,这比在镜像参数里折腾更直接。
镜像参数与其他参数的优先级
当你在命令里同时指定了--image和--block-device-mapping,nova会优先使用块设备映射的信息,块设备里的source_type=image、destination_type=volume等字段会替代--image的默认行为,如果不想用boot from volume,就别混着写,这是很多老版本的坑,最新版本虽然做了兼容,但建议保持单一来源。
常见疑问解答
nova client和openstack client配置自定义镜像的语法能互换吗?
不能直接互换。nova boot --image是python-novaclient的旧命令风格,而openstack server create --image是统一的OpenStackClient风格,在较新的OpenStack版本(Train及以后)中,nova client已被标记为维护模式,推荐使用openstack server create,如果你习惯了nova boot的写法,需要调整命令结构,但参数含义一致:--image后面跟镜像ID或名称。
自定义镜像创建后重新引导时总是找不到硬盘,和--image参数有关系吗?
有间接关系。--image参数只负责告诉nova使用哪个镜像作为根磁盘来源,但镜像内部是否包含正确的virtio驱动和磁盘分区表,由镜像本身决定,建议在镜像制作阶段执行virt-customize安装必要的驱动,并确保分区表为GPT且引导文件完整,创建时若出现no bootable device,优先检查镜像内部配置,而非修改nova命令参数。