老早以前我就想写一篇这样的文章,因为每次向人推荐 OpenStack 入门方案,最后都会被复杂安装劝退。直到我折腾出一套组合,才觉得这事终于能坐下来好好聊聊了。这套组合就是 DevStack + Multipass:用 Multipass 快速拉起来一台 Ubuntu 虚拟机,再在虚拟机里跑 DevStack 的 stack.sh 脚本,把 OpenStack 的核心服务一次性部署好。整个流程下来,不用准备几台物理机,不用折腾复杂的自动化运维工具,一个普通的笔记本就能跑起来。
为什么要写这个主题?因为很多人搞 OpenStack 学习,第一步就卡在“装不上”。官方生产部署一般推荐 kolla-ansible 或者 TripleO,但这些东西为了生产环境考虑了太多因素,参数多、依赖重、对机器要求高,用来学习完全是杀鸡用牛刀。DevStack 是 OpenStack 社区官方维护的开发测试脚本,它的定位就是在单一节点上快速拉起一个可用的 OpenStack 环境,非常适合学习、试验和 CI 验证。而 Multipass 负责提供一个干净、可销毁的宿主机环境,让整个流程可复现。
这篇文章适合三类人:一是刚开始学 OpenStack、想先跑起来看看它长什么样的开发者;二是需要在本地方便地做二次开发测试的工程人员;三是准备给学生或同事做培训、希望有一套“照着敲就能成功”的教学环境的人。我会从装 Multipass 开始,一步步走到创建第一台云主机,并把我踩过的坑和一些排查思路都整理出来。
1. 项目概述与方案选型
1.1 为什么本地学习 OpenStack 首选 DevStack
DevStack 本质是一组 Bash 脚本,核心文件是 stack.sh。运行它时,脚本会去拉取 OpenStack 各个服务项目的代码,然后自动完成依赖安装、数据库初始化、Keystone 服务注册、Nova/Neutron/Glance 等服务的配置和启动。整个过程像是一个“自动化安装向导”,把生产环境需要手工做的步骤全部封装起来了。
这里要敲个重点:DevStack 不是生产环境方案,这一点从名字就看得出来,“Dev”是 Development。它默认会开很多调试开关,日志也打得非常详细,所有服务都跑在同一个节点上,网络、存储、认证全部是简化模式。但恰恰是这种“简化”,让它成为理解 OpenStack 组件协作关系的最好教材。通过它跑起来的 OpenStack,服务清单、配置文件、数据库都可以清晰地查到,想深入看哪个组件都可以直接去看代码。相比那些容器化部署,DevStack 让你能直接看到每个服务的真实进程,这对学习非常友好。
另外,DevStack 还带了一堆方便调试的功能,比如./unstack.sh可以快速停掉所有服务,./clean.sh可以清空安装数据,改完代码后重新跑一遍 stack.sh 就能让环境回到最新状态。做开发测试时,这种“随时推倒重来”的能力非常宝贵。实际工程项目里,我也用 DevStack 做 CI 环境的临时节点,跑完就销毁,成本极低。
1.2 为什么用 Multipass 而不是传统虚拟机
有人会问,为什么不直接在电脑上装一台 VirtualBox 虚拟机,再用它来跑 DevStack?其实完全可以,我以前也这么干过,但体验差不少。Multipass 是 Canonical 官方出的轻量级虚拟机管理工具,它直接调用宿主机底层的虚拟化能力,比如 macOS 的 HyperKit、Windows 的 Hyper-V,以及 Linux 的 KVM,命令式管理虚拟机,比手动点 VirtualBox 的图形界面利索得多。
Multipass 最大的好处有两个:启动快、占用低。它使用的是精简过的 Ubuntu Cloud 镜像,通常十几秒就能把一台配置好的 Ubuntu 虚拟机拉起来;而且支持在命令行直接指定 CPU、内存、磁盘大小,对硬件资源的使用非常可控。配合multipass launch一条命令,就能创建出一台干净的 Ubuntu 环境。
对比更重的 Vagrant,Multipass 的命令集更简单,和系统集成更自然。尤其当你想给多个同学或同事出一份统一的实验环境时,只要把几条multipass命令和一份local.conf发出去,大家克隆下来就能跑,不会出现“我这边三步五步好了,你那边莫名其妙起不来”的尴尬。可复现性是我在标题里特意强调“可复现指南”的原因。
1.3 这套组合的完整工作链路
用一张图来理解整个安装链路(脑补文字版):宿主机(你的笔记本/台式机)通过 Multipass 启动一台 Ubuntu VM;在 VM 内部下载 DevStack 代码并配置 local.conf;执行 stack.sh 后,VM 就变成一个 all-in-one 的 OpenStack 节点,里面同时跑着 Keystone、Glance、Nova、Neutron、Horizon 等核心服务;宿主机通过浏览器访问 VM 的 IP 加/dashboard路径打开 Horizon 控制台,也可以通过 SSH 进入 VM 使用命令行工具。
这个链路里的每一步都可以抽出来单独复现。Multipass 的 VM 规格、local.conf 的配置、后续安装命令,都是声明式的。也就是说,只要你在同一套硬件环境和网络条件下,按这同一份指南操作,大概率能拿到相同的结果。这也是我想强调“可复现”的价值——不是玄学,而是可以照着抄的作业。
2. 环境准备:从安装 Multipass 到初始化虚拟机
2.1 Windows/macOS/Linux 安装 Multipass 的几种方式
Multipass 的安装并没有太多坑,但不同平台还是有点区别。Windows 上安装 Multipass 之前,要先确认系统已经开启了 Hyper-V 或 WSL2 底层。安装包可以从官网下载,也可以用winget install Canonical.Multipass来装。装好以后打开 PowerShell 或者 CMD,输入multipass version能看到版本号就算成功。
macOS 上最简单的方式是brew install --cask multipass,或者直接从官网下载 pkg 安装包。如果机器比较老,可能要注意 Multipass 对虚拟化框架的要求,不过 M 系列芯片和 Intel 芯片都能跑,只是底层驱动不同。Linux 上推荐用 snap:sudo snap install multipass,它会自动处理依赖。
安装完以后,不管哪个平台,都可以先跑multipass list看看当前有哪些虚拟机,刚装好时应该是空的。如果你在 Windows 上碰见“不支持的虚拟化”报错,多半是 Hyper-V 没开或者和别的虚拟化软件冲突,需要在“启用或关闭 Windows 功能”里把 Hyper-V 勾选上,然后重启。这块我会在后面的坑位里细说。
2.2 创建一台足够跑 OpenStack 的 Ubuntu 虚拟机
DevStack 是个资源大户,虽然 OpenStack 各个服务都压缩在一台机器上,但它内部还是有消息队列、数据库、镜像服务、网络代理等一堆进程。所以给虚拟机的配置不要太抠,我的建议是最低给 4 核 CPU、8GB 内存、50GB 磁盘。如果你的宿主机内存只有 16GB,给虚拟机 8GB 后还剩 8GB 给本机,基本够用;如果只有 8GB 内存,建议把 swap 加上再试,否则很容易中途 OOM。
创建虚拟机只需要一条命令:
multipass launch -n devstack -c 4 -m 8G -d 50G 22.04这里-n是虚拟机名字,-c指定 CPU 核数,-m指定内存,-d指定磁盘大小,最后的22.04是 Ubuntu 版本代号。我推荐用 22.04 LTS,后续的 OpenStack 版本兼容性比较好。命令执行后,Multipass 会自动下载对应镜像并启动,第一次会慢一些,之后再用同样镜像就是秒级启动。
创建完成后,先用multipass list查看 VM 状态和 IP 地址,再用multipass shell devstack进入虚拟机。这里提醒一下,VM 的默认用户名就是ubuntu,密码不是重点,因为 Multipass 会配置好 SSH 密钥,所以你也可以直接用multipass exec devstack -- bash -c 'uname -a'这种宿主机直调方式在 VM 里执行命令。
2.3 进入 VM 后的基础环境整理
进入虚拟机后,第一件事是更新软件包索引和升级已有软件:
sudo apt update && sudo apt upgrade -y这一步最好做完,因为 DevStack 在安装时会安装很多依赖,如果基础系统本身不干净,很容易出现装到一半因为某个旧包报错。
接下来要确认几个基础工具是否就位:
sudo apt install -y git python3 python3-pip另外,如果你的网络环境访问 GitHub 和 PyPI 比较慢,可以在 VM 里配置好国内的 pip 镜像源和 git 镜像再往下走。这里不展开太多,但是我可以给一个 pip 加速的简单做法:创建或修改~/.pip/pip.conf,写入[global]和指向你习惯的镜像源的index-url。这样后面stack.sh下载 Python 依赖会快很多,省得反复超时。
DevStack 建议用一个非 root 且有 sudo 权限的用户来安装。Multipass 默认的ubuntu用户正好满足要求。注意不要在 root 下直接跑 stack.sh,脚本里会有检查,建议用普通用户跑。接下来我们就以ubuntu用户身份,把 DevStack 目录 clone 到主目录下。
3. DevStack 核心配置与安装过程
3.1 拉取 DevStack 代码并选择 OpenStack 版本
先回到ubuntu用户主目录,执行:
git clone https://opendev.org/openstack/devstack cd devstack这里拉的是默认分支,通常是 master。对于学习环境,我更推荐签出到稳定的发布分支,比如stable/2024.1或stable/2023.2。稳定分支和默认分支的区别在于,前者经过了发布测试,组件之间的版本匹配更可靠,踩到兼容性坑的概率低很多。
签出分支的命令:
git checkout stable/2024.1如果你想安装特定组件的最新代码,也可以不签出分支,直接在 master 上跑,但那样就要接受“不确定性”。我在实际使用中发现,跟着稳定的 OpenStack 版本走是最省心的,因为社区文档、各组件依赖关系都围绕着发布版本做过验证。另外,devstack目录里除了 stack.sh,还有samples/local.conf示例文件,我们可以拿它作为配置模板。
3.2 local.conf 里的密码、IP 与服务裁剪
local.conf 是 DevStack 的灵魂,它决定了这个 OpenStack 环境长什么样。在 devstack 目录下新建一个文件,名字就叫local.conf。我的最小配置是这样:
[[local|localrc]] ADMIN_PASSWORD=admin123 DATABASE_PASSWORD=$ADMIN_PASSWORD RABBIT_PASSWORD=$ADMIN_PASSWORD SERVICE_PASSWORD=$ADMIN_PASSWORD HOST_IP=192.168.64.10这里我把所有密码都指向ADMIN_PASSWORD,方便记忆。密码不要包含$、#、&这类会被 shell 解释的字符,否则脚本会凌乱。HOST_IP就是虚拟机的 IP,可以通过multipass info devstack查到,最好手动写死,避免 DevStack 自动检测的时候选错网卡。
默认配置会启用很多服务,包括 Cinder、Swift、Tempest 等。对于只想体验核心 OpenStack 功能的人来说,这些服务不仅拖慢安装,还占用大量内存和磁盘。所以我习惯把它们关掉:
[[local|localrc]] ... disable_service tempest disable_service cinder c-sch c-api c-vol disable_service swift这样保留 Keystone、Glance、Nova、Placement、Neutron、Horizon,足够用来学习和创建云主机了。
如果后续想单独开启哪个服务,比如想试用对象存储 Swift,直接把disable_service swift这行删掉,然后重新跑./stack.sh就行。DevStack 这种“按需裁剪服务”的能力,是我一直推荐它做学习环境的重要原因。改配置就像搭积木,每次重装都能按需组装。
3.3 执行 stack.sh 并实时监控日志
配置写好后,直接运行:
./stack.sh如果一切顺利,脚本会经过依赖安装、源码拉取、数据库初始化、服务注册等阶段,整个过程大概 15 到 30 分钟,具体时间取决于你的网络速度和宿主机性能。第一次跑的时候,建议另开一个终端,用下面的命令实时看日志:
tail -f /home/ubuntu/devstack/logs/stack.sh.log或者直接观察当前终端输出。DevStack 的日志很啰嗦,但也很诚实,哪一步失败会直接报红色错误信息。
安装成功的标志是最后一段提示,通常会告诉你This is your host IP address和Horizon is now available at http://<IP>/dashboard。就算看到这个提示,也别急着关终端,先在 VM 里等几秒,让服务完成健康检查。我之前就有过刚显示成功就去做其他操作,结果 Nova 服务还没来得及注册完的情况。多等十秒,后面的操作会更顺。
4. 安装后的功能验证与第一台云主机
4.1 用 openstack CLI 确认核心服务全部在线
安装完成后,进入 devstack 目录,先加载环境变量:
cd ~/devstack source openrc admin adminopenrc脚本会设置好OS_*系列环境变量,让openstack命令知道该往哪个数据中心、哪个租户发请求。执行完以后,先查一下认证服务:
openstack service list正常情况下能看到 keystone、nova、neutron、glance、placement 等服务的条目,每一条对应一个服务类型。
再顺手查一下组件状态:
openstack endpoint list openstack compute service list openstack network agent list openstack image list前两个确认认证端点和 Nova 服务状态,网络代理列表能让你看到 DHCP、L3、metadata 等 agent 是否都处于 up 状态。如果某个 agent 是 down 的,创建出来的云主机大概率没有网络,所以这一步最好仔细看。日志在/home/ubuntu/devstack/logs下,具体到n-*和q-*这些服务都有单独日志文件。
4.2 通过浏览器访问 Horizon 仪表板
命令行验证通过后,可以再看看 Web 界面。在宿主机浏览器里访问http://<虚拟机IP>/dashboard,会出现一个登录页,输入admin和 local.conf 里设置的ADMIN_PASSWORD就能登录。Horizon 是 OpenStack 的官方 Web 面板,项目、镜像、网络、实例这些资源都能在界面里看到。
第一次登录可能会遇到页面样式加载不全的情况,大多数时候是静态文件缓存的问题,刷新几遍或者换个无痕窗口就好了。还有个小提醒:因为 DevStack 默认是 HTTP,浏览器可能提示不安全,这是正常的,直接继续访问就好。登录后可以先去“项目 → 计算 → 实例”页面看一眼前提环境,再继续下一步命令行操作。
4.3 从创建网络到拉起第一台实例的完整操作
现在开始干正事:创建第一台云主机。我们需要分四步:创建网络、创建路由、准备镜像和密钥、创建实例。这一步是比较经典的用户链,走通了,你对 OpenStack 的“租户网络”模型就有体感了。
先建一个隔离的专用网络,命令如下:
openstack network create demo-net openstack subnet create --subnet-range 192.168.100.0/24 --network demo-net --dns-nameserver 8.8.8.8 demo-subnet openstack router create demo-router openstack router add subnet demo-router demo-subnet这里我建了一个 24 位掩码的子网,用的网段跟 DevStack 默认的public网段不冲突。路由的作用是让这个子网里的实例能和外部通信,后面我们还要给路由绑定外部网关。
接着准备镜像和密钥。Cirros 是一个专门用来做云主机测试的最小 Linux 镜像,只有几十 MB,非常适合首次练习:
openstack image create --disk-format qcow2 --container-format bare --public cirros \ --file /path/to/cirros-0.6.2-x86_64-disk.img如果没有现成镜像文件,可以先用wget下载到 VM 里,路径替换一下即可。密钥方式我习惯用openstack keypair create mykey > mykey.pem,然后chmod 600 mykey.pem。这样后面 SSH 登录才能用上。
最后创建实例:
openstack server create --flavor m1.tiny --image cirros --network demo-net \ --key-name mykey demo-instancem1.tiny是 DevStack 默认自带的“微型”规格,内存只有 512MB,跑 Cirros 完全够用。创建后可以openstack server list查看状态,从BUILD变成ACTIVE就表示成功。为了能够从外部访问这台实例,还需要给它绑定一个浮动 IP,并放行安全组规则:
openstack floating ip create public openstack server add floating ip demo-instance <浮动IP> openstack security group rule create --protocol icmp --ingress default openstack security group rule create --protocol tcp --dst-port 22 --ingress default之后就可以用ping <浮动IP>测试连通性了。如果 ping 不通,优先检查路由外网网关和安全组规则。
5. 常见问题与避坑速查表
5.1 内存不足导致的安装中断
这是我在本地和远程服务器上跑 DevStack 时遇到最多的失败原因。VM 内存给得太小,或者宿主机内存不够,stack.sh经常会在编译或者服务启动阶段被系统 OOM Killer 杀掉,表现就是日志里直接出现Killed字样,后面没有任何明确报错。
排查思路很简单,先在 VM 里执行dmesg | tail看有没有 out of memory 的记录;如果有,官方建议是加大内存,我实践经验是 8GB 起步才舒服。如果宿主机物理内存确实紧张,退而求其次的办法是增加 swap。在 Multipass 创建的 VM 里加 swap 有点绕,可以进入 VM 后用 fallocate 创建一块 swap 文件,然后挂载启用。另外,也可以按上文那样裁剪服务,把 Cinder、Swift、Tempest 都禁掉,能省下不少常驻内存。
5.2 下载超时和依赖拉取失败
DevStack 安装过程会从 Git 仓库拉取 OpenStack 各组件的源码,也会用 pip 安装大量 Python 依赖。这两个环节最容易因为网络问题导致失败,尤其在某些网络环境下,默认源可能会很慢。如果你碰到git clone卡住或者pip install超时,多半是源访问慢,不是脚本问题。
应对办法有两个方向。一是配置国内镜像源。git 方面可以用git config --global url."<镜像地址>".insteadOf "https://opendev.org/openstack"这样的重写规则;pip 方面就是前面提过的pip.conf。DevStack 里很多GIT_BASE变量也可以自定义,具体可以看官方文档。二是善用 DevStack 的断点续跑能力——如果安装在中途失败,修复网络后直接重新跑./stack.sh,它不会重复执行已经完成的步骤,会接着往下走。我经常“多跑几次就过去了”。
5.3 版本兼容性带来的各种怪问题
DevStack 对 Ubuntu 版本、Python 版本和 OpenStack 版本之间的组合是有讲究的。比如 Ubuntu 24.04 用的 Python 3.12,如果你硬要跑老的 stable/2023.1 分支,可能会碰到 Python 包不兼容的问题。反过来,用 Ubuntu 20.04 跑最新的 master 也可能因为 Python 版本太老而报错。所以我的建议是尽量使用官方持续集成中常见的组合,例如 Ubuntu 22.04 + stable/2024.1,这套我用下来很稳。
如果你在不太新也不太旧的版本组合上遇到了莫名的 RuntimeError,不要急着改代码,先在本地看看 DevStack 仓库里有没有相应的 issue 或 patch。很多时候某个版本刚发布,社区会有一批兼容性修复,只要切换到最新的稳定补丁分支就能解决。另外,./clean.sh之后重跑 stack.sh 也是一个万能的“重置键”,很多半新不旧的状态都可以通过它恢复。
5.4 如何干净地卸载与重建环境
本地学习最不缺的就是折腾,环境搞坏了怎么办?不用慌。在 DevStack 里可以执行./unstack.sh停掉所有服务,再执行./clean.sh清理掉安装的数据和编译产物;如果还想更彻底,直接销毁整个 Multipass 虚拟机就行:
multipass delete devstack multipass purge之后再创建一台全新的 VM,整个过程不过几分钟。这种“大不了重来”的底气,正是 Multipass 带来的最大优势。
补充一个细节:Multipass 的delete只是把 VM 标记为删除,需要再执行purge才会真正清掉磁盘上的数据。如果你只是暂时不用,可以先multipass stop devstack保留环境,下次multipass start devstack继续用。这个习惯能帮你省下很多重复安装的时间。
5.5 故障速查表(含经验值)
除了上面的逐条分析,我习惯把踩过的坑整理成一张表贴在笔记里,遇到问题先对号入座。
| 故障现象 | 可能原因 | 处理办法 |
|---|---|---|
| 安装中断,日志出现 Killed | 内存不足触发 OOM | 增加 VM 内存,或关闭 Cinder/Swift/Tempest 服务 |
| git clone 阶段卡住 | 网络访问慢 | 配置 git 镜像或本地源,重跑 stack.sh 续跑 |
| pip install 超时 | PyPI 速度慢 | 配置 pip 镜像源,使用 pip.conf |
| 创建实例一直 BUILD | Nova/Neutron 服务状态异常 | 查看 compute service list 和对应服务日志 |
| Horizon 样式加载不全 | 静态文件缓存 | 强制刷新或换无痕窗口 |
| 端口无法访问 | 安全组未放行 | 添加 ICMP/TCP 安全组规则 |
这张表我后来在团队内部分享时也经常用,配合日志定位,基本能解决九成以上的安装问题。
6. 我实践后的经验与后续玩法
6.1 几个让我省时间的操作习惯
实践几次之后,我摸索出几个提高效率的小习惯。第一,每次创建 VM 后,我会把 DevStack 的local.conf放到宿主机的一个目录里管理起来,然后用multipass mount挂载进 VM。这样重装 VM 时不用重新手写配置,直接复制过来就行,版本管理也方便。
第二,不要一直盯着安装日志发呆。stack.sh跑的时候,我会同时打开一个终端,用top看 VM 的 CPU 和内存变化,另一个终端随时准备tail日志。一旦发现内存快满了,趁早决定要不要停掉重来,不要等 OOM。第三,网络相关的参数,比如HOST_IP、子网网段,首次写好之后不要随意改动,否则很容易出现“服务都起来了但网络不通”的玄学问题。
6.2 在 DevStack 基础上还能做哪些试验
环境跑通之后,玩法就多了。你可以试试用 Heat 编排一组多层应用,体验一下基础设施即代码;也可以把 Cinder 重新启用来练习块存储挂载;还可以接入 Octavia 体验负载均衡服务。这些在本地 DevStack 上都能跑,只是资源要再宽裕点。
如果想把环境分享给团队成员,可以写一个简单的启动脚本,把multipass launch、git clone、local.conf生成、./stack.sh封装成一条命令,大家克隆脚本后一键执行。我在内部培训里就干过这件事,效果很好,极大降低了新人上手 OpenStack 的门槛。最后再分享一个真实感受:别怕环境搞坏,本地环境的优势就是可以随意破坏和重建,折腾得越多,理解得越深。