Nova是OpenStack最核心的组件,负责管理和调度虚拟机实例的生命周期。
以下分析将结合架构图,分为总体架构、核心组件交互、以及关键流程三个维度。
1. Nova 总体架构图
Nova采用了分布式、无状态的架构。其核心设计思想是“通过消息总线(RabbitMQ)进行通信,通过数据库进行状态存储”。
graph TB
subgraph External[外部访问层]
User([用户/客户端])
CLI[CLI / SDK]
API_Endpoint[RESTful API]
end
subgraph Core[核心服务层]
Nova_API[Nova-API<br/>接收请求/协调/鉴权]
Nova_Scheduler[Nova-Scheduler<br/>调度器/资源筛选]
Nova_Conductor[Nova-Conductor<br/>数据库代理/安全]
Nova_Placement[Placement API<br/>资源库存管理]
end
subgraph Compute[计算节点层]
Nova_Compute[Nova-Compute<br/>Hypervisor Driver]
Libvirt[Libvirt/KVM<br/>Xen/ESXi等]
end
subgraph Backend[支撑后端]
DB[(SQL Database<br/>MySQL/PostgreSQL)]
MQ[Message Queue<br/>RabbitMQ]
end
User --> CLI
CLI --> API_Endpoint
API_Endpoint --> Nova_API
Nova_API <--> MQ
Nova_Scheduler <--> MQ
Nova_Conductor <--> MQ
Nova_Compute <--> MQ
Nova_API --> DB
Nova_Conductor --> DB
Nova_Placement --> DB
Nova_Compute --> Libvirt
Nova_Compute -.->|状态上报| Nova_Conductor
style External fill:#e1f5fe,stroke:#01579b,stroke-width:2px
style Core fill:#fff3e0,stroke:#e65100,stroke-width:2px
style Compute fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
style Backend fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
style Nova_API fill:#ffb74d,stroke:#f57c00
style Nova_Scheduler fill:#ffb74d,stroke:#f57c00
style Nova_Conductor fill:#ffb74d,stroke:#f57c00
style Nova_Compute fill:#66bb6a,stroke:#2e7d32
组件职责说明:
- Nova-API:全局入口,处理REST请求(OS API/EC2 API),负责权限校验(Keystone)、请求合法性验证。
- Nova-Scheduler:决定虚拟机跑在哪台物理机上。通过过滤器(Filters)和权重(Weighers)算法选择最优宿主机。
- Nova-Conductor:关键的安全层。为了避免计算节点直接访问数据库(安全风险),所有数据库操作均由Conductor代理。它负责数据库的读写、对象模型的转换。
- Nova-Compute:运行在每台物理机上的“工人”。它通过轮询消息队列接收指令,调用底层的Hypervisor API(Libvirt、VMware等)执行生命周期操作(创建、销毁、重启)。
- Placement:从Newton版本开始独立的核心服务。管理资源类(CPU、RAM、Disk、GPU、NUMA)的库存和消费记录,提供资源供应决策依据。
2. 核心组件交互流程(创建虚拟机为例)
下图展示了在创建一台虚拟机的典型过程中,各个组件是如何通过消息队列和数据库进行异步协作的。
sequenceDiagram
autonumber
participant User
participant API as Nova-API
participant MQ as RabbitMQ
participant Scheduler as Nova-Scheduler
participant Cond as Nova-Conductor
participant DB as Database
participant Placement as Placement API
participant Compute as Nova-Compute
participant Hypervisor as KVM/QEMU
User->>API: POST /servers (Boot Request)
API->>API: 鉴权 (Keystone)
API->>DB: 创建虚拟机记录 (vm_state=BUILDING)
API->>MQ: 发送 'boot' 消息 (RPC cast)
MQ-->>Scheduler: 获取 'boot' 任务
Scheduler->>Placement: 查询可用资源 (GET /allocation_candidates)
Placement-->>Scheduler: 返回候选宿主机列表
Scheduler->>DB: 过滤并选定宿主机 (Host)
Scheduler->>MQ: 发送 'build_and_run_instance' (RPC cast to selected host)
MQ-->>Compute: 获取构建任务
Compute->>Cond: 请求虚拟机完整信息 (RPC call)
Cond->>DB: 读取实例数据
DB-->>Cond: 返回数据
Cond-->>Compute: 返回实例对象
Compute->>Placement: 申请资源 (PUT /allocations)
Compute->>Hypervisor: spawn() 创建虚拟机磁盘 & 启动
Hypervisor-->>Compute: 返回成功 & Guest IP
Compute->>DB: 更新虚拟机状态 (vm_state=ACTIVE)
3. 高级架构特性图解:Cells v2 架构
在生产环境中(大规模部署),为了解决单点数据库瓶颈和消息队列压力,Nova引入了 Cells v2 架构。它将环境划分为多个“细胞”(Cell),实现了水平扩展。
graph TD
subgraph Top[控制平面 - 全局]
API_Cell[API Cell<br/>Nova-API + Placement API]
Global_DB[(Global Database<br/>API DB: 记录 Cell 映射)]
MQ_Global[Global Message Queue]
end
subgraph Cell1[Cell 1 - 机房A]
Cell1_DB[(Cell DB<br/>实例元数据)]
Cell1_MQ[Cell Message Queue]
Cell1_Sched[Nova-Scheduler]
Cell1_Cond[Nova-Conductor]
Cell1_Compute[Nova-Compute]
end
subgraph Cell2[Cell 2 - 机房B]
Cell2_DB[(Cell DB)]
Cell2_MQ[Cell Message Queue]
Cell2_Sched[Nova-Scheduler]
Cell2_Cond[Nova-Conductor]
Cell2_Compute[Nova-Compute]
end
API_Cell --> Global_DB
API_Cell --> MQ_Global
MQ_Global -->|跨Cell路由| Cell1_MQ
MQ_Global -->|跨Cell路由| Cell2_MQ
Cell1_Sched --> Cell1_MQ
Cell1_Cond --> Cell1_DB
Cell1_Compute --> Cell1_MQ
Cell1_Compute --> Cell1_DB
style Top fill:#fce4ec,stroke:#880e4f
style Cell1 fill:#e0f2f1,stroke:#004d40
style Cell2 fill:#e0f2f1,stroke:#004d40
架构特点:
- API Cell:负责路由,用户请求进来后,根据
host或uuid映射判断请求属于哪个 Cell。 - Cell 隔离:每个 Cell 拥有独立的 消息队列 和 数据库。这防止了单一 RabbitMQ 集群或 MySQL 集群成为整个云平台的瓶颈。
- Cell0:特殊的 Cell,用于记录所有失败的实例或尚未被调度的实例,避免污染主数据库。
4. 架构设计哲学总结
- 无状态与水平扩展:
nova-api和nova-scheduler是无状态的。你可以通过负载均衡轻松扩展它们的数量。- 状态数据全部存储在
MySQL或Redis(用于缓存的Tooz)中。
- 异步通信与最终一致性:
- Nova 大量使用 RPC Cast(单向调用) 而非 Call(双向调用)。创建虚拟机时,API 收到请求写入数据库后立即返回
202 Accepted,后续的构建是异步的。 - 这种设计使得系统在高并发下具有极高的吞吐量,但牺牲了即时反馈,运维需要依赖
ceilometer或nova instance-action-list来追踪进度。
- Nova 大量使用 RPC Cast(单向调用) 而非 Call(双向调用)。创建虚拟机时,API 收到请求写入数据库后立即返回
- 驱动化架构(Driver Framework):
Nova-Compute完全依赖 Driver 模式。无论是 KVM、vSphere、Hyper-V 还是容器化(如通过 virtlet),底层异构硬件的差异被 Driver 层完全屏蔽。
- 资源供应分离:
- 自 Newton 版本后,Placement 服务从 Scheduler 中剥离出来。这使得资源计算(Resource Management)与调度逻辑(Scheduling Logic)解耦,不仅服务于 Nova,也可供 Cyborg(加速器管理)、Magnum(容器编排)等其他项目使用。
5. 关键技术难点与运维建议
- 数据库锁与竞争:在高并发创建/删除场景下,
nova-conductor对数据库的更新可能导致行锁等待。建议使用 Galera Cluster 多主模式,并严格配置[conductor]下的workers数量。 - 消息队列积压:如果
nova-compute处理能力跟不上,RabbitMQ 会积压。需要监控rabbitmq_queue_length,并考虑使用 Cells v2 进行物理隔离。 - Placement 高可用:Placement API 是调度的心脏。必须将其部署在多节点,并使用 Apache + mod_wsgi 的模式运行,避免使用 Nova 自带的 eventlet 导致并发瓶颈。