1. Nova 是什么为什么还要手动安装Nova 不是某个具体软件的代号而是 OpenStack 云平台中负责计算服务Compute Service的核心组件。它管理着虚拟机实例的整个生命周期——从创建、调度、启动、暂停、迁移到最终销毁。你可以把它理解为云数据中心里的“虚拟机总调度室”当用户在 Web 控制台点下“新建实例”按钮或者通过命令行执行openstack server create背后真正干活、跟物理服务器打交道、调用 KVM/QEMU/LXC 的就是 Nova。但问题来了既然 OpenStack 官方提供了 DevStack一键脚本、PackstackRHEL/CentOS 专用部署器、甚至 TripleO企业级裸金属部署方案为什么还有人执着于“手动安装与配置”这绝不是为了炫技或返祖而是源于三个无法被自动化工具绕开的现实刚性需求第一教学与深度理解场景。DevStack 脚本跑完你看到的是一个能用的云界面但 Nova 的nova-api、nova-scheduler、nova-conductor、nova-compute四个核心服务如何通信它们各自监听哪个端口数据库表结构里instances表和compute_nodes表如何关联配置文件中scheduler_driver和compute_driver的取值逻辑是什么这些底层脉络只有亲手把每个服务的 systemd unit 文件写出来、把/etc/nova/nova.conf里每一行参数的意义抠明白才能真正建立认知地图。我带过三届 OpenStack 认证培训凡是跳过手动安装直接上 DevStack 的学员在后续排错时面对NoValidHost错误90% 会卡在“不知道该查 scheduler 日志还是 compute 日志”。第二生产环境定制化硬约束。某金融客户要求 Nova 必须使用 Oracle 数据库而非默认 MySQL并且所有 API 请求必须经由自研的 RBAC 网关做二次鉴权。DevStack 默认只支持 SQLitePackstack 的数据库选项列表里压根没有 Oracle。此时唯一路径就是手动下载 Nova 源码包或 PyPI wheel修改setup.cfg中的数据库驱动依赖重编译后再逐项配置connection、connection_recycle_time、max_retries等 Oracle 特有参数。这个过程没有捷径自动化脚本在这里不是帮手而是障碍。第三故障隔离与最小化验证。当一个已运行半年的 OpenStack 集群突然出现“实例创建超时”而日志里只显示Scheduler returned no hosts你无法确定是nova-scheduler进程挂了还是nova-conductor与数据库连接池耗尽抑或是nova-compute主机上的 libvirt 服务异常。此时最高效的排查方式是临时在一台干净的测试机上用最简配置仅启用nova-apinova-scheduler SQLite 后端启动 Nova验证基础调度逻辑是否正常。这个“最小可运行单元”的构建恰恰依赖对手动安装流程的肌肉记忆——你知道哪些配置项是绝对必需的如[DEFAULT] transport_url、[api_database] connection哪些是可后期追加的如[cinder]块存储集成。所以“手动安装”从来不是目的而是抵达深度掌控的必经之路。它像学游泳时拆掉浮板像木工学徒亲手刨平第一块木料——过程笨拙但每一道划痕都刻进经验里。接下来的内容不会教你复制粘贴几行命令就完成部署而是带你一砖一瓦垒起属于你自己的 Nova 计算服务基石。2. 手动安装前的环境准备那些被忽略的“地基细节”很多人卡在第一步不是因为不会敲命令而是败在环境准备的“隐性门槛”上。手动安装 Nova 不是装一个普通应用它是一组强耦合服务的协同体对操作系统、内核、网络、安全模块都有明确要求。我见过太多人反复重装系统只因忽略了以下三点关键细节。2.1 操作系统与内核版本不是“能跑就行”而是“必须匹配”OpenStack 的每个大版本如 Yoga、Zed、Antelope都严格限定支持的操作系统及内核范围。以当前主流的 Antelope 版本为例官方文档明确要求操作系统Ubuntu 22.04 LTSJammy或 CentOS Stream 9内核版本最低 5.15.0Ubuntu或 5.14.0CentOS Stream 9为什么如此苛刻因为 Nova 的nova-compute服务深度依赖内核特性。例如当启用libvirt的virtio-fs共享文件系统时需要内核 5.16 的fs/virtio_fs模块若使用kvm_intel模块的ept1扩展页表优化则要求内核 5.10 对 Intel VT-x 的完整支持。我在某次部署中客户坚持使用 Ubuntu 20.04内核 5.4结果nova-compute启动后持续报错libvirtError: internal error: process exited while connecting to monitor排查三天才发现是qemu-system-x86_64进程因内核缺少kvm_hv模块而崩溃。提示执行uname -r查看内核版本后务必对照 OpenStack Release Matrix 文档确认兼容性。不要相信“别人在 20.04 上装成功了”——他们的 Nova 版本可能比你低两个小版本。2.2 网络规划不止是 IP 地址更是服务通信拓扑手动安装 Nova 时网络配置远超“给网卡配个 IP”这么简单。你需要预先规划四类网络平面网络平面用途典型 IP 段关键配置项Management NetworkNova 服务间通信API、RPC192.168.10.0/24bind_host在nova.conf中设为管理网 IPProvider Network虚拟机直连物理网络Flat/VLAN10.0.100.0/24physical_interface_mappings映射物理网卡Instance Tunnel Network虚拟机跨主机通信VXLAN/GRE172.16.0.0/16local_ip设为隧道网 IPenable_tunnelingTrueStorage Network (Optional)Ceph RBD 存储访问172.16.10.0/24rbd_cluster_name,rbd_user等 Ceph 参数最容易出错的是 Management Network 的bind_host配置。很多教程直接写bind_host 0.0.0.0这在单机测试可行但在多节点生产环境会引发严重安全风险——nova-api将监听所有网卡包括面向公网的接口。正确做法是在控制节点bind_host 192.168.10.10管理网 IP在计算节点bind_host 192.168.10.20。同时防火墙必须放行对应端口nova-api8774、nova-scheduler无独立端口走 RPC、nova-conductor同上、nova-compute无 HTTP 端口但需开放 libvirt 的 16509 端口。2.3 Python 环境与依赖管理避开系统包与虚拟环境的“双重陷阱”Nova 是 Python 应用但它的依赖管理极其特殊。它既不能完全依赖系统包如 Ubuntu 的python3-nova也不能简单用pip install nova—— 因为 Nova 服务需要与oslo.config、oslo.db、keystoneauth等 OpenStack 公共库精确版本对齐。Antelope 版本要求oslo.config 8.7.0, 9.0.0而系统仓库里的python3-oslo.config可能是 6.x 版本直接冲突。我的标准做法是放弃系统 Python 包但也不用全局 pip。而是为每个 Nova 服务创建独立的 Python 虚拟环境并使用pip-tools锁定依赖# 创建 nova-api 专用虚拟环境 python3 -m venv /opt/venvs/nova-api source /opt/venvs/nova-api/bin/activate # 安装 pip-tools 并生成依赖文件 pip install pip-tools echo nova[mysql]26.0.0,27.0.0 requirements.in pip-compile requirements.in # 生成 requirements.txt含精确版本 pip install -r requirements.txt这样做的好处是当需要升级 Nova 时只需更新requirements.in中的版本号重新pip-compile就能确保所有依赖包括间接依赖版本兼容。我曾因未锁定sqlalchemy版本导致nova-manage db sync报错AttributeError: Table object has no attribute columns根源是sqlalchemy 2.0移除了table.columns属性而 Nova 25.x 代码尚未适配。3. 核心服务配置详解从nova.conf到 systemd Unit 文件手动安装的精髓不在“装”而在“配”。nova.conf这个配置文件表面看是文本实则是 Nova 的神经中枢。它决定了服务如何启动、与谁通信、数据存哪里、权限怎么控。下面我将逐段拆解一个生产可用的nova.conf骨架并解释每一处为何如此设置。3.1[DEFAULT]段全局行为的“宪法条款”这是整个配置文件的基石错误配置会导致服务根本无法启动。[DEFAULT] # 服务标识与日志 my_ip 192.168.10.10 # 必须控制节点管理网 IP用于 RPC 绑定 use_neutron True # 强制启用 Neutron 网络禁用旧版 nova-network firewall_driver nova.virt.firewall.NoopFirewallDriver # 生产环境禁用 Nova 自带防火墙交由 Neutron 处理 # RPC 与消息队列核心 transport_url rabbit://openstack:RABBIT_PASS192.168.10.10:5672/ # RabbitMQ 连接串密码需提前在 RabbitMQ 创建用户 rpc_response_timeout 180 # RPC 调用超时避免 scheduler 等待过久 # 数据库连接注意此处是 API 数据库非主业务库 api_database_connection mysqlpymysql://nova:NOVA_DBPASS192.168.10.10/nova_api?charsetutf8mb4 # 认证与授权 auth_strategy keystone # 必须为 keystone禁用 noauth仅测试用关键点解析my_ip不是localhost或127.0.0.1nova-scheduler通过此 IP 向nova-compute发送 RPC 指令若设为127.0.0.1计算节点将收不到调度请求。firewall_driver设为NoopFirewallDriverNova 自带的 iptables 防火墙规则与 Neutron 的安全组规则存在严重冲突会导致实例无法访问外网。这是生产环境铁律。transport_url中的RABBIT_PASS必须是 RabbitMQ 中为openstack用户设置的密码且该用户需有/vhost 的全部权限configure,write,read。我曾因权限不足nova-scheduler日志持续报错AMQPConnectionException: Connection refused却误以为是网络不通。3.2[database]段主业务数据库的“生命线”Nova 有两个数据库nova_api存 API 相关元数据和nova存实例、主机等核心数据。[database]段配置后者。[database] connection mysqlpymysql://nova:NOVA_DBPASS192.168.10.10/nova?charsetutf8mb4 max_retries -1 # 永久重试避免数据库短暂抖动导致服务退出 connection_recycle_time 3600 # 连接池连接存活时间秒防止 MySQL 的 wait_timeout 断连为什么max_retries -1因为在金融级生产环境数据库连接中断是常见事件如主从切换、网络抖动。若设为默认10nova-conductor服务会在第 11 次失败后直接退出导致整个集群实例创建停滞。设为-1后它会无限重试配合connection_recycle_time定期刷新连接保障服务韧性。3.3[keystone_authtoken]段身份认证的“数字护照”此段配置 Nova 如何向 Keystone 验证自身及用户身份。[keystone_authtoken] www_authenticate_uri https://192.168.10.10:5000 # Keystone Public API 端点 auth_url https://192.168.10.10:35357 # Keystone Admin API 端点注意端口不同 memcached_servers 192.168.10.10:11211 # Memcached 用于 token 缓存提升性能 auth_type password project_domain_name Default user_domain_name Default project_name service username nova password NOVA_PASS致命陷阱www_authenticate_uri和auth_url的端口必须区分Keystone 的 Public API5000 端口供外部用户调用Admin API35357 端口供内部服务如 Nova进行管理操作如创建 endpoint。若两者都指向 5000nova-manage api_db sync会报错Forbidden: You are not authorized to perform the requested action: identity:create_endpoint。3.4 systemd Unit 文件让服务“活”起来的启动脚本配置文件写完服务不会自动运行。你需要为每个 Nova 服务编写 systemd Unit 文件。以nova-api为例/etc/systemd/system/nova-api.service[Unit] DescriptionOpenStack Compute API Server Afternetwork.target Aftermysqld.service Aftermemcached.service Afterrabbitmq-server.service [Service] Typesimple Usernova Groupnova WorkingDirectory/var/lib/nova ExecStart/opt/venvs/nova-api/bin/nova-api Restarton-failure RestartSec10 KillModeprocess LimitNOFILE65536 [Install] WantedBymulti-user.target关键细节After行定义了严格的启动顺序必须等 MySQL、Memcached、RabbitMQ 全部就绪后nova-api才能启动。否则会因数据库不可达而反复崩溃。Usernova和Groupnova必须创建nova系统用户useradd -r -s /bin/false nova禁止以 root 运行服务。LimitNOFILE65536提高文件描述符上限。Nova 在高并发时如批量创建 1000 实例会打开大量 socket 和日志文件系统默认 1024 远远不够会导致Too many open files错误。4. 初始化与验证从db sync到第一个实例诞生配置文件和 Unit 文件就位后真正的考验才开始。初始化不是一条命令的事而是一个有严格顺序、环环相扣的链条。任何一步出错后续步骤必然失败。4.1 数据库同步nova-manage的“奠基仪式”Nova 提供nova-manage工具进行数据库初始化。顺序绝对不可颠倒# 1. 同步 API 数据库nova_api sudo -u nova /opt/venvs/nova-api/bin/nova-manage api_db sync # 2. 同步主业务数据库nova sudo -u nova /opt/venvs/nova-api/bin/nova-manage db sync # 3. 注册计算节点关键 sudo -u nova /opt/venvs/nova-api/bin/nova-manage cell_v2 create_cell --namecell1 --verbose为什么cell_v2创建必须在db sync之后因为create_cell会向nova数据库的cell_mappings表插入记录。若先执行db sync会因表结构不存在而报错。--verbose参数会输出新创建 cell 的 UUID这个 UUID 后续要填入nova.conf的[placement]段。注意nova-manage db sync命令本身不报错不代表成功。必须检查 MySQL 中nova数据库的表数量SELECT COUNT(*) FROM information_schema.tables WHERE table_schemanova;正常应返回 50 张表。若只有 10 张说明同步未完成大概率是nova.conf中的connectionURL 有语法错误如漏了?charsetutf8mb4。4.2 服务启动与状态诊断systemctl不是万能钥匙启动服务后不能只看systemctl status nova-api显示active (running)就认为成功。必须逐层验证# 1. 检查进程是否真在运行 ps aux | grep nova-api | grep -v grep # 2. 检查监听端口 ss -tlnp | grep :8774 # 3. 检查日志是否有致命错误重点关注 ERROR 和 CRITICAL sudo journalctl -u nova-api -f | grep -E (ERROR|CRITICAL)最常见的日志错误是No module named keystoneauth1。这表明nova-api虚拟环境里缺少keystoneauth1包。解决方案不是pip install keystoneauth1而是回到requirements.in添加keystoneauth14.4.0,5.0.0然后重新pip-compile和pip install。因为手动pip install会破坏依赖锁导致版本冲突。4.3 创建第一个实例用openstackCLI 验证全链路当所有服务nova-api,nova-scheduler,nova-conductor,nova-compute都稳定运行后用最简命令创建实例是终极验证# 1. 创建密钥对跳过 ssh 密钥则实例无法登录 openstack keypair create mykey mykey.pem chmod 600 mykey.pem # 2. 启动实例指定最小规格、镜像、网络 openstack server create \ --flavor m1.tiny \ --image cirros-0.6.2-x86_64-disk \ --nic net-idNETWORK_UUID \ --key-name mykey \ --security-group default \ test-instance如果命令卡住或报错按此顺序排查openstack server list是否能看到test-instance状态为BUILD若看不到nova-api接收请求失败查nova-api.log。若状态为BUILD但长时间不变成ACTIVE查nova-scheduler.log是否有NoValidHost若有查nova-compute.log是否报libvirtError或Unable to connect to libvirt若nova-compute.log显示Connection refused检查libvirtd服务是否运行systemctl status libvirtd以及nova.conf中[libvirt]段的uri qemu:///system是否正确。我曾在一个案例中test-instance卡在BUILD15 分钟。最终发现是nova-compute主机的 SELinux 处于enforcing模式阻止了nova-compute进程访问/var/lib/libvirt/images/目录。执行setsebool -P virt_use_nfs on后立即解决。这再次证明手动安装的价值在于你能精准定位到 SELinux 这个层级的问题而自动化脚本只会告诉你“部署失败”。5. 常见故障与避坑指南那些只在深夜调试时才浮现的真相手动安装 Nova 的过程本质上是一场与各种“幽灵错误”的搏斗。这些错误往往不报明确异常而是表现为服务看似运行、功能却部分失效。以下是我在上百次部署中总结的五大高频“暗坑”附带真实排查路径。5.1 “实例创建成功但无法 ping 通”Neutron Agent 状态迷雾现象openstack server create返回ACTIVEnova list显示实例运行但ping实例 IP 失败ssh也超时。排查路径openstack network agent list检查neutron-openvswitch-agent和neutron-l3-agent是否alive且admin_state_upTrue。若neutron-l3-agent状态为down登录其所在主机执行sudo systemctl status neutron-l3-agent。查看日志sudo journalctl -u neutron-l3-agent -n 100。常见错误是Failed to bind port根源是ovs-vsctl show显示br-int与br-ex未正确连接或br-ex未绑定到物理网卡。经验neutron-l3-agent的配置文件/etc/neutron/l3_agent.ini中external_network_bridge br-ex必须与ovs-vsctl show输出的网桥名完全一致包括大小写。我曾因配置为br-EX导致 L3 agent 启动后立即退出日志只显示Exiting毫无线索。5.2 “Scheduler 返回 no valid host”计算节点资源报告失真现象nova-scheduler.log明确记录Filter ImagePropertiesFilter returned 0 hosts或RamFilter returned 0 hosts。根本原因nova-compute服务未能正确向nova-conductor上报计算节点资源。这通常由两个原因导致原因一nova-compute服务未真正运行。systemctl status nova-compute显示active但ps aux | grep nova-compute无进程。这是因为nova-compute启动后若检测到libvirtd未运行或qemu-kvm不可用会静默退出。解决方案sudo systemctl start libvirtd并确认lsmod | grep kvm输出kvm_intel或kvm_amd。原因二nova.conf中[libvirt]段配置错误。关键参数[libvirt] virt_type qemu # 若 CPU 不支持硬件虚拟化必须设为 qemu慢不能设为 kvm cpu_mode none # 避免 CPU 特性不匹配导致实例启动失败 images_type rbd # 若使用 Ceph此项必须存在且正确实操技巧执行nova hypervisor-stats。若返回{count: 0, memory_mb: 0}说明nova-compute未上报若返回{count: 1, memory_mb: 16384}则上报成功。这是判断计算节点注册状态的黄金命令。5.3 “API 返回 500 Internal Server Error”Placement API 的隐形依赖现象openstack server list或openstack hypervisor list报错HTTP 500nova-api.log显示Placement API communication failed。Placement 是 OpenStack Rocky 版本引入的独立服务用于跟踪计算资源CPU、内存、磁盘的使用情况。Nova 所有资源查询都依赖它。但 Placement 不是 Nova 的子服务它有自己的配置和数据库。避坑要点Placement 服务必须单独安装pip install python-placement并配置placement.conf。nova.conf中[placement]段必须正确指向 Placement API[placement] os_region_name RegionOne auth_url https://192.168.10.10:5000 auth_type password project_domain_name Default user_domain_name Default project_name service username placement password PLACEMENT_PASSPlacement 数据库需单独同步sudo -u placement placement-manage db sync。我曾因忘记启动placement-api服务nova-api日志里满屏500却花了两天时间在 Nova 配置里大海捞针。记住nova-api的 500 错误80% 源头在 Placement。5.4 “实例 Console 无法访问”Serial Console 的证书迷局现象openstack console url show instance返回的 VNC URL 无法连接浏览器提示SSL_ERROR_UNKNOWN_PROTOCOL。根源Nova 的nova-novncproxy服务需要有效的 TLS 证书。若使用自签名证书浏览器会拦截。但更隐蔽的坑是nova.conf中[vnc]段的novncproxy_base_url必须与实际 Nginx/Apache 反向代理的域名完全一致。[vnc] enabled true server_listen 0.0.0.0 server_proxyclient_address 192.168.10.10 novncproxy_base_url https://controller.example.com:6080/vnc_auto.html若你的反向代理配置在https://cloud.example.com但novncproxy_base_url写成https://controller.example.comVNC 连接会因 CORS跨域被浏览器拒绝且错误日志里没有任何提示。解决方案在反向代理如 Nginx中强制将controller.example.com的请求重定向到cloud.example.com或直接在nova.conf中统一使用cloud.example.com。同时确保nova-novncproxy服务的ssl_cert和ssl_key指向正确的证书路径。5.5 “服务启动缓慢日志刷屏 WARNING”Python 日志级别的无声消耗现象nova-api启动耗时超过 2 分钟journalctl -u nova-api持续滚动WARNING oslo_config.cfg: Option xxx from group yyy is deprecated。这不是功能错误但会严重拖慢启动速度并掩盖真正错误。原因是 Nova 启动时会扫描所有已加载的配置项对每个废弃deprecated选项发出警告。Antelope 版本中[DEFAULT] log_dir已被弃用应改用[DEFAULT] log_file。根治方法在nova.conf顶部添加[DEFAULT] # 禁用废弃选项警告提升启动速度 deprecated_opts_warning false彻底清理配置文件删除所有log_dir、use_syslog等废弃参数改用新参数log_file /var/log/nova/nova-api.log、use_syslog_rfc_format true。这个细节看似微小但在大规模集群中每个服务节省 30 秒启动时间10 个节点就是 5 分钟的部署窗口缩短。手动安装的价值正在于你能掌控这些影响系统毛细血管的微观参数。6. 手动安装后的进阶实践从“能用”到“好用”的跃迁当 Nova 成功运行第一个实例顺利启动手动安装的使命并未结束。真正的价值始于配置完成之后。以下是三个立竿见影的进阶实践它们不增加复杂度却能显著提升稳定性、可观测性和运维效率。6.1 为nova-compute添加健康检查探针Kubernetes 有 liveness/readiness probe传统服务同样需要。nova-compute作为最关键的计算节点服务一旦僵死进程存在但不响应 RPCnova-scheduler仍会向其派发任务导致实例创建失败。为此我为nova-compute编写了一个轻量级健康检查脚本/usr/local/bin/nova-compute-healthcheck.sh#!/bin/bash # 检查 nova-compute 进程是否存在 if ! pgrep -f nova-compute /dev/null; then echo nova-compute process not found exit 1 fi # 检查 libvirtd 是否运行 if ! systemctl is-active --quiet libvirtd; then echo libvirtd is not active exit 1 fi # 检查能否列出虚拟机最简单的功能验证 if ! sudo -u nova /opt/venvs/nova-compute/bin/nova-compute --config-file /etc/nova/nova.conf --list-hosts 2/dev/null | grep -q compute; then echo nova-compute cannot list hosts exit 1 fi echo nova-compute is healthy exit 0然后将其集成到 systemd 中在nova-compute.service的[Service]段添加ExecStartPre/usr/local/bin/nova-compute-healthcheck.sh HealthCheckStartSec30 HealthCheckIntervalSec60这样systemd 会每 60 秒执行一次健康检查若连续两次失败自动重启nova-compute。无需额外监控系统原生 systemd 就提供了可靠的自我修复能力。6.2 使用nova-manage进行数据库维护不只是syncnova-manage不仅用于初始化更是日常运维的瑞士军刀。两个高频命令清理僵尸实例当实例被强制删除virsh destroy但 Nova 数据库未同步时会产生DELETED状态的僵尸记录占用数据库空间并干扰统计。执行# 清理 7 天前的 DELETED 实例 sudo -u nova /opt/venvs/nova-api/bin/nova-manage db archive_deleted_rows --max_rows 1000 --age_in_days 7修复 Cell 映射当新增计算节点后nova-manage cell_v2 discover_hosts可能遗漏。手动触发全量发现# 强制扫描所有计算节点并注册到 cell1 sudo -u nova /opt/venvs/nova-api/bin/nova-manage cell_v2 discover_hosts --verbose提示archive_deleted_rows命令会移动数据不是删除。它将instances表中deleted_at早于指定天数的记录迁移到shadow_instances表。这比直接DELETE更安全保留了审计线索。6.3 构建可复现的部署流水线从手动到半自动手动安装的终极目标不是永远手动而是为自动化铺平道路。我将手动安装过程沉淀为一个 Ansible Playbook但它与通用 Playbook 有本质区别所有变量都来自真实的nova.conf文件而非凭空定义。Playbook 的核心思想是ansible-pull拉取 Playbook然后template模块根据本地nova.conf.j2模板生成配置。模板中关键变量如transport_url rabbit://{{ lookup(file, /root/rabbit_pass.txt) }}{{ management_ip }}:5672/ connection mysqlpymysql://nova:{{ lookup(file, /root/nova_db_pass.txt) }}{{ management_ip }}/nova?charsetutf8mb4/root/rabbit_pass.txt和/root/nova_db_pass.txt是在部署前由运维人员手动创建的密码文件。这样Playbook 本身不包含任何敏感信息密码通过文件注入符合安全审计要求。每次部署只需ansible-pullcp两个命令即可在新节点上复现完全一致的手动安装效果。这个实践让我深刻体会到所谓“手动”不是原始而是可控所谓“自动化”不是黑盒而是对手动过程的精确编码。二者并非对立而是同一枚硬币的两面——手动是理解的起点自动化是规模的终点。