1. 从ISO镜像到可用实例:整体设计思路拆解
在私有云运维的日常里,用ISO镜像装虚拟机这件事,说简单也简单,说坑多也是真多。很多刚接触OpenStack的朋友习惯了在虚拟化平台里点几下就装完系统,结果到了OpenStack这边,上传ISO、配卷、挂载、引导、装系统、再卸载ISO,一套流程走下来,中间任何一步没配对,虚拟机就卡在BIOS界面或者直接进不了安装程序。我前后在几个不同规模的环境里做过这件事,踩过的坑足够写一篇避雷指南,所以这篇就把从ISO创建虚拟机的完整链路拆开讲清楚。
先明确一下这个操作到底在做什么。OpenStack本身是一个云操作系统,它管理的是计算、存储、网络这些资源池。默认情况下,它最擅长的是用现成的镜像(qcow2、raw这类)快速批量创建虚拟机,因为这种镜像里已经装好了系统,开机即用。但现实场景里,你经常需要从ISO开始装系统,比如要装一个特定版本的操作系统、要做自定义分区、要装一些镜像里没有的驱动,或者干脆就是想模拟一台物理机的完整安装过程。这时候就需要走ISO引导安装这条路。
这个内容适合谁看?如果你已经能登录OpenStack的Dashboard或者会用命令行,知道什么是flavor、什么是volume、什么是network,那这篇就是给你准备的实操手册。如果你连项目、用户、配额这些概念都还没搞明白,建议先把基础操作过一遍再回来,不然中间很多步骤你会不知道为什么这么做。
核心思路其实一句话就能概括:把ISO当成一张光盘,把虚拟机的系统盘当成一块空白硬盘,让虚拟机先从光盘启动装系统,装完之后再把光盘拔掉,从硬盘启动。听起来跟给物理机装系统一模一样,对吧?OpenStack里也是这个逻辑,只不过“光盘”和“硬盘”都是虚拟的,需要通过卷(Volume)和镜像(Image)来模拟。
这里有个关键的设计选择需要提前想清楚:系统盘到底用本地盘还是云硬盘(Cinder卷)?这个选择会直接影响你后续的操作路径。用本地盘的话,虚拟机实例的根盘是临时的,实例删了系统就没了,而且没法做快照和迁移;用Cinder卷的话,系统盘是持久化的,可以快照、可以迁移、可以随时挂载到别的实例上排查问题。从ISO安装这个场景,我强烈建议用Cinder卷,原因后面会详细说,因为ISO安装过程中需要多次挂载和卸载,用卷操作起来灵活得多。
还有一个前置条件容易被忽略:你的OpenStack环境得支持从卷引导。有些老版本或者配置不完整的环境,Cinder卷只能作为数据盘挂载,不能作为启动盘。这个在创建实例的时候就能看出来,如果“从卷启动”那个选项是灰的,或者创建完直接报错,那就是后端存储或者Glance跟Cinder的集成没配好。遇到这种情况,要么找管理员确认配置,要么就只能退而求其次用本地盘方案。
2. 核心细节解析与实操要点
2.1 ISO镜像的上传与格式要求
第一步是把ISO文件弄进OpenStack。这里有个常见的误解:很多人以为ISO要像qcow2镜像那样上传到Glance,然后直接拿它创建实例。实际上,ISO在Glance里就是一个普通镜像,但它的用途是作为“光盘”挂载,而不是作为启动盘直接引导。上传的时候有几个参数必须配对,否则后面挂载会失败。
上传ISO到Glance,命令行大概是这样:
openstack image create "ubuntu-22.04-iso" \ --file ./ubuntu-22.04.3-live-server-amd64.iso \ --disk-format iso \ --container-format bare \ --public注意--disk-format iso这个参数,一定要写对。如果你手滑写成qcow2或者raw,Glance虽然能存进去,但后面挂载给虚拟机的时候,底层驱动会按qcow2去解析这个文件,结果就是虚拟机根本认不出这是一张光盘,引导直接失败。我见过有人图省事直接写--disk-format raw,结果排查了半天才发现是格式标错了。
--container-format bare也是必须的,ISO文件本身就是裸的,不需要额外的容器封装。至于--public还是--private,看你的使用范围,如果只是自己项目里用,private就够了,省得污染公共镜像列表。
上传完之后,用openstack image list确认一下状态是active,大小跟你本地文件一致。如果状态一直是queued或者saving,那可能是Glance后端存储出问题了,得找存储管理员看看。
提示:ISO文件通常比较大,几个GB是常态。上传之前先确认Glance后端的存储空间够不够,别传一半空间满了,镜像卡在saving状态,清理起来很麻烦。
2.2 系统盘的创建与参数计算
接下来要创建一块空白卷作为虚拟机的系统盘。这块盘的大小怎么定?我的经验是:ISO里官方推荐的最小磁盘空间,再往上加20%到30%的余量。比如Ubuntu Server 22.04官方建议最小25GB,那你至少给30GB,最好给40GB。因为安装过程中会解压大量文件,还要留出swap分区和后续更新的空间,给得太紧巴巴的,装到一半提示空间不足,前功尽弃。
创建卷的命令:
openstack volume create --size 40 --image ubuntu-22.04-iso \ --bootable system-disk-for-vm01这里有个细节:--image参数指定ISO镜像,--bootable标记这块卷是可引导的。有些版本的OpenStack里,--image和--bootable要配合使用,意思是“这块卷从指定的镜像引导”。但注意,这里指定的镜像其实是ISO,所以这块卷在创建的时候会被写入ISO的内容吗?不是的,它只是把卷标记为“可以从这个镜像引导”,实际引导的时候,ISO是作为光盘挂载的,卷本身还是空的。这个逻辑有点绕,但理解这一点很重要,因为它决定了你后面挂载和卸载ISO的操作方式。
如果你用的是Dashboard,操作路径是:卷 -> 创建卷 -> 在“卷来源”里选择“镜像”,然后选中你上传的ISO,勾选“可引导”。大小填40GB。创建完之后等状态变成available。
2.3 实例的创建与引导顺序设置
卷创建好之后,就可以创建实例了。这里的关键是引导顺序。在OpenStack里,创建实例的时候可以指定从哪个设备引导。如果你用命令行,大概是这样:
openstack server create --flavor m1.medium \ --volume system-disk-for-vm01 \ --network private-net \ --key-name mykey \ vm01注意--volume参数,它把刚才创建的卷作为启动盘挂给实例。但这时候有个问题:卷里是空的,ISO虽然标记在卷上,但实际引导的时候,虚拟机需要先从ISO启动。OpenStack的默认行为是,如果卷是从ISO创建的,它会自动把ISO作为光盘挂载,并且引导顺序会优先从光盘启动。但这个行为在不同版本里表现不一样,有的版本需要你手动指定。
更稳妥的做法是,创建实例的时候先不挂ISO,而是创建一个带空卷的实例,然后手动把ISO挂载上去,再重启实例,在启动过程中进入BIOS或者引导菜单选择从光盘启动。但这样操作太繁琐,而且很多OpenStack环境不允许你直接访问虚拟机的BIOS界面。
所以实际生产里,我推荐的做法是:创建卷的时候就把ISO关联上,创建实例的时候直接用这块卷,OpenStack会自动处理引导顺序。如果创建完实例发现直接进了BIOS或者提示“no bootable device”,那说明引导顺序不对,需要检查一下卷的bootable标记和镜像关联是否正确。
2.4 网络与安全组的配置要点
网络这块,ISO安装过程中通常需要联网下载一些额外的包,所以实例得能访问外网。如果你用的是私有网络,记得把路由和NAT配好,让实例能通过路由器访问外部网络。安全组方面,安装过程中可能需要SSH或者HTTP访问,但默认的安全组通常只开了SSH。如果你在安装过程中需要从外部访问虚拟机的Web控制台,那还得开对应的端口。
不过说实话,ISO安装阶段最方便的还是通过VNC或者SPICE直接看虚拟机的控制台,这样不需要额外开端口,直接在Dashboard里就能操作。OpenStack的Dashboard里,实例详情页有个“控制台”标签,点进去就能看到虚拟机的屏幕,跟坐在物理机前面一样。安装系统的时候用这个最省事。
注意:VNC控制台在安装过程中可能会因为网络延迟或者浏览器兼容性问题卡顿,建议用Chrome或者Firefox,别用那些小众浏览器。如果控制台一直黑屏,先检查实例状态是不是ACTIVE,再看VNC代理服务是不是正常。
3. 实操过程与核心环节实现
3.1 完整操作流程拆解
下面我把整个流程按顺序走一遍,你可以直接照着做。假设你已经有了OpenStack的访问权限,命令行工具也配好了。
第一步:上传ISO到Glance。
openstack image create "centos-7-iso" \ --file ./CentOS-7-x86_64-Minimal-2009.iso \ --disk-format iso \ --container-format bare \ --private上传完成后确认状态:
openstack image show centos-7-iso -c status -c size状态应该是active,size跟你本地文件大小一致。
第二步:创建可引导的空白卷。
openstack volume create --size 50 --image centos-7-iso \ --bootable centos7-system-disk等卷状态变成available:
openstack volume show centos7-system-disk -c status第三步:创建实例并挂载卷。
openstack server create --flavor m1.large \ --volume centos7-system-disk \ --network private-net \ --security-group default \ --key-name mykey \ centos7-vm创建完之后,用openstack server list看实例状态,应该是ACTIVE。如果状态是ERROR,用openstack server show centos7-vm看fault信息,通常是卷挂载失败或者flavor资源不足。
第四步:通过控制台安装系统。
在Dashboard里找到这个实例,点“控制台”,应该能看到CentOS的安装界面。如果看到的是“no bootable device”或者直接进了BIOS,说明引导顺序不对。这时候需要检查卷的bootable标记,或者手动把ISO挂载为光盘。
手动挂载ISO的命令:
openstack server add volume centos7-vm centos-7-iso --device /dev/sr0然后重启实例:
openstack server reboot --hard centos7-vm重启的时候盯着控制台,应该能看到从光盘引导的提示。如果还是不行,可能需要在创建实例的时候指定引导顺序,但这个操作在不同OpenStack版本里差异很大,有的版本支持--boot-from-volume参数,有的版本需要在Nova的配置里改。
第五步:安装完成后卸载ISO。
系统装完之后,虚拟机会自动从硬盘重启。这时候ISO还挂载着,虽然不影响使用,但最好卸载掉,免得下次重启又从光盘引导。
openstack server remove volume centos7-vm centos-7-iso卸载完之后,再重启一次实例,确认能从硬盘正常引导。
3.2 参数计算与选择依据
整个流程里,有几个参数需要你根据实际情况算一下。
卷的大小:前面说了,官方最小要求加20%到30%。但如果你要装图形界面或者大量开发工具,那得再加。比如CentOS 7 Minimal官方建议最小10GB,但你如果要装GNOME桌面,至少得20GB起步。我的经验是,开发测试环境给40GB,生产环境给60GB到100GB,具体看你的应用需求。
flavor的选择:ISO安装过程中对CPU和内存的要求比正常运行时要高,因为安装程序本身要解压大量文件。建议至少2核4GB起步,如果ISO比较大或者要装图形界面,4核8GB更稳妥。安装完之后,你可以再调整flavor,但注意OpenStack默认不支持在线调整flavor,需要关机再改。
网络带宽:如果你是从外部上传ISO到Glance,那上传速度取决于你的网络带宽。一个4GB的ISO,在100Mbps的网络上大概要传5到6分钟。如果Glance后端是分布式存储,上传过程中可能会有额外的网络开销,时间会更长。
3.3 实操现场记录与关键截图说明
由于这里没法贴图,我用文字描述一下关键界面的样子,你操作的时候可以对照。
Glance镜像列表:上传成功后,镜像名称旁边会显示“active”,大小显示为ISO的实际大小,比如“4.2 GB”。如果显示“queued”,说明还在上传中;如果显示“error”,点进去看错误信息,通常是存储后端的问题。
卷列表:创建完卷之后,卷的状态是“available”,大小显示为你指定的大小,比如“50 GB”。如果状态是“creating”,等一会儿刷新;如果状态是“error”,看错误信息,可能是Cinder后端存储空间不足。
实例控制台:安装界面出现后,你会看到ISO的引导菜单,比如CentOS的“Install CentOS 7”或者Ubuntu的“Try or Install Ubuntu Server”。用键盘方向键选择,回车进入安装程序。安装过程中,分区那一步建议选“自动分区”,除非你有特殊需求。如果选手动分区,记得给/boot至少1GB,/至少20GB,swap根据内存大小定,一般内存的1到2倍。
安装完成后的重启:安装程序会提示你重启,重启的时候注意看屏幕,如果又出现了“Press any key to boot from CD”,千万别按键,等它自己跳过,从硬盘引导。如果按了键,又会进安装程序,那就白装了。
4. 常见问题与排查技巧实录
4.1 引导失败类问题排查
问题一:创建完实例,控制台显示“no bootable device”。
这是最常见的问题。原因通常是卷没有正确标记为可引导,或者ISO没有正确挂载为光盘。排查步骤:
- 检查卷的
bootable属性:openstack volume show <volume-id> -c bootable,应该是True。 - 检查卷关联的镜像:
openstack volume show <volume-id> -c image_id,应该是ISO的镜像ID。 - 检查实例挂载的卷:
openstack server show <server-id> -c volumes,确认系统盘挂载在/dev/vda或者/dev/sda。 - 如果以上都正常,尝试手动挂载ISO为光盘:
openstack server add volume <server-id> <iso-image-id> --device /dev/sr0,然后硬重启。
问题二:控制台显示“Booting from Hard Disk”,但硬盘是空的。
这说明引导顺序错了,虚拟机直接从硬盘引导,但硬盘里没系统。解决办法是进入BIOS调整引导顺序,但OpenStack里通常没法直接进BIOS。替代方案是,在创建实例的时候指定引导顺序,或者用--boot-from-volume参数强制从卷引导。如果这些都不行,那就只能删掉实例重新创建,创建的时候确保ISO已经正确关联到卷上。
问题三:安装过程中提示“Unable to find a medium containing a live file system”。
这是Ubuntu ISO常见的问题,通常是因为ISO挂载的设备不对。Ubuntu的安装程序会去找包含casper目录的设备,如果ISO挂载在/dev/sr0但安装程序没认出来,就会报这个错。解决办法是,在引导菜单里按e编辑引导参数,把cdrom相关的路径改对,或者干脆换一个ISO版本试试。我遇到过几次,换成Server版而不是Live版就好了。
4.2 性能与资源类问题
问题四:安装过程特别慢,进度条半天不动。
可能的原因有几个:一是Cinder后端存储性能差,读写速度跟不上;二是网络带宽不够,安装程序在下载额外的包;三是flavor给的资源太少,CPU跑满了解压速度慢。排查的时候,先在Dashboard里看实例的CPU和内存使用率,如果CPU一直100%,那就是资源不够,关机改flavor。如果CPU不高但磁盘IO很高,那就是存储性能问题,找存储管理员确认后端是不是机械盘或者网络存储延迟大。
问题五:安装完成后,实例启动特别慢,或者卡在某个服务上。
这通常是系统盘的问题。用Cinder卷做系统盘,IO性能取决于后端存储。如果后端是机械盘或者低端网络存储,系统启动会比本地盘慢很多。我的经验是,生产环境尽量用SSD或者高性能分布式存储做Cinder后端,不然装完系统用起来也难受。如果实在没法改存储,那就只能忍,或者在创建实例的时候用本地盘做系统盘,但那样就失去了持久化和迁移的能力。
4.3 常见问题速查表
| 问题现象 | 可能原因 | 排查命令 | 解决办法 |
|---|---|---|---|
| 控制台显示“no bootable device” | 卷未标记可引导或ISO未挂载 | openstack volume show <id> -c bootable | 重新创建卷并确保--bootable和--image参数正确 |
| 直接从硬盘引导但硬盘为空 | 引导顺序错误 | openstack server show <id> -c volumes | 手动挂载ISO为光盘并硬重启 |
| 安装程序找不到ISO介质 | ISO挂载设备不对 | 在控制台查看挂载点 | 编辑引导参数或更换ISO版本 |
| 安装过程极慢 | 存储性能差或资源不足 | 查看实例CPU和磁盘IO | 改flavor或更换存储后端 |
| 安装完成后无法从硬盘引导 | ISO未卸载或引导顺序未恢复 | openstack server show <id> -c volumes | 卸载ISO并重启实例 |
| 卷创建失败 | Cinder后端空间不足 | openstack volume show <id> -c status | 清理无用卷或扩容后端存储 |
4.4 独家避坑技巧
技巧一:先用小ISO测试流程。如果你第一次做这个操作,别上来就拿几十GB的ISO试。找一个几百MB的轻量级Linux发行版,比如Alpine或者Tiny Core,先把整个流程跑通,确认引导、挂载、安装、卸载都没问题,再换正式ISO。这样能省很多时间,因为大ISO上传和安装都慢,出错了排查也费劲。
技巧二:安装过程中别关控制台。有些人习惯开着控制台然后去干别的,结果回来发现控制台断开了,安装卡在某个交互界面等输入。OpenStack的VNC控制台在长时间无操作后可能会断开,虽然虚拟机本身还在跑,但你没法看到界面也没法输入。所以安装过程中最好保持控制台窗口活跃,或者用openstack console log show看日志确认进度。
技巧三:装完系统先别急着卸载ISO。系统装完第一次重启后,确认能正常登录了,再卸载ISO。因为有时候系统装完但引导记录没写对,卸载ISO后直接起不来,还得重新挂载ISO进救援模式修复。多挂一会儿不碍事,确认没问题了再卸。
技巧四:用卷快照做备份。系统装好之后,第一时间给卷做个快照。这样以后装坏了或者要批量部署,直接从这个快照创建新卷就行,不用每次都从头装。快照命令:openstack volume snapshot create --volume <volume-id> <snapshot-name>。恢复的时候用openstack volume create --snapshot <snapshot-id> <new-volume-name>。
技巧五:注意时区和键盘布局。安装过程中,时区和键盘布局这两个选项很容易被忽略,但装完之后再改就麻烦了。特别是键盘布局,如果你选错了,后面输密码的时候会发现打出来的字符跟预期不一样,登录都登不进去。安装的时候花几秒钟确认一下,省得后面折腾。
5. 批量部署与自动化扩展思路
单台从ISO装系统搞定了,接下来自然会想能不能批量做。答案是能,但需要一些额外的工具和脚本。OpenStack本身提供了Heat编排服务,你可以写一个Heat模板,把上传ISO、创建卷、创建实例、挂载ISO这一系列操作串起来,一键部署多台。但Heat模板写起来比较繁琐,而且调试麻烦,对于偶尔用一次的场景有点杀鸡用牛刀。
更轻量的做法是用命令行脚本。把前面那些命令写成一个bash脚本,用循环创建多台实例。但注意,ISO安装过程中需要人工交互,脚本没法自动完成分区、设置密码这些步骤。所以批量部署的场景,通常不是从ISO装,而是先手工装好一台,做成镜像,然后用这个镜像批量创建实例。这才是OpenStack的正确用法。
如果你确实需要批量从ISO装,那可以考虑用Kickstart或者Preseed做自动化安装。CentOS系用Kickstart,Ubuntu系用Preseed,把安装配置写成一个文件,放在HTTP服务器上,ISO引导的时候指定这个文件的URL,安装程序就会自动完成所有步骤,不需要人工干预。这样配合脚本就能实现批量部署。但配置Kickstart文件本身也需要不少时间,适合有长期批量需求的场景。
提示:Kickstart和Preseed的配置文件里可以指定分区方案、软件包列表、网络配置、用户密码等。写的时候注意密码要用加密后的哈希值,别直接写明文。生成哈希可以用
openssl passwd -6命令。
6. 个人实操体会与后续扩展
这套流程我在不同环境里跑过很多次,最大的体会是:OpenStack从ISO装虚拟机的难点不在命令本身,而在环境配置和引导顺序。命令就那么几条,背都背下来了,但环境里任何一个环节没配好,比如Cinder后端不支持可引导卷、Glance镜像格式不对、Nova引导顺序配置有问题,都会让你卡住。所以遇到问题的时候,别急着怀疑自己的操作,先确认环境是不是支持这个用法。
另一个体会是,能不用ISO就不用ISO。如果你的需求只是装一个标准系统,那直接找一个现成的qcow2镜像上传到Glance,创建实例的时候选这个镜像,几十秒就能起来,比ISO安装快得多也稳得多。ISO安装适合那些确实需要自定义分区、需要特定驱动、或者需要模拟完整安装过程的场景。日常运维里,大部分情况用现成镜像就够了。
后续如果要把这个流程产品化,可以考虑做成一个自服务门户,让用户填几个参数(ISO选择、卷大小、flavor、网络),后台自动完成剩下的步骤。这样不懂OpenStack命令的人也能用。但要注意,ISO安装过程中还是需要人工交互,所以门户里得集成VNC控制台,让用户能直接操作安装界面。这个集成工作量不小,但做一次能省很多重复劳动。
最后分享一个小技巧:如果你经常需要从ISO装系统,可以准备一个“万能”ISO,里面集成常用的驱动和工具,然后把这个ISO做成Glance里的公共镜像,所有人共享。这样不用每个人都上传一遍ISO,省存储空间也省时间。ISO的定制可以用mkisofs或者genisoimage工具,把额外的文件追加进去,具体方法这里就不展开了,有需要的可以自己查一下。