当前位置: 首页 > news >正文

OpenStack Nova 创建虚拟机

创建虚拟机的过程是一个经典的分布式、异步、状态驱动的工作流。其核心设计哲学是:API 接收请求 -> 调度决策 -> 资源分配 -> 虚拟化层执行。整个过程涉及多个 Nova 服务以及外部组件(Glance, Neutron, Cinder, Keystone)。

1、基本流程

CinderNeutronGlanceLibvirtComputeConductorSchedulerMessage QueueNova DBnova-apiUserCinderNeutronGlanceLibvirtComputeConductorSchedulerMessage QueueNova DBnova-apiUser1. POST /servers (创建实例)2. 创建初始实例记录(state: BUILDING)3. cast(run_instance to scheduler)4. 获取消息5. 查询资源6. cast(build_and_run_instance to compute.X)7. 获取消息8. 请求资源(镜像、网络等)9. 查询数据10. 返回信息11. 下载镜像12. 分配网络13. 挂接卷(如适用)14. 定义并启动域(XML)15. 成功16. 更新状态(state: ACTIVE)17. 发送状态事件

流程可分为三大阶段:

  1. API 阶段 (nova-api):接收并验证请求,创建数据库记录,立即返回响应,将后续任务异步下发。
  2. 调度阶段 (nova-scheduler):决策虚拟机在哪个计算节点上启动。
  3. 构建阶段 (nova-compute):与各类服务交互准备资源,调用 Hypervisor 真正创建虚拟机。

2、详细流程源码分析

2.1 API请求入口

nova/api/openstack/compute/servers.py

# nova/api/openstack/compute/servers.py (Caracal版本)class ServersController(wsgi.Controller):@wsgi.response(202)@validation.schema(schema_server_create_v242, '2.42')def create(self, req, body):"""处理创建虚拟机API请求"""context = req.environ['nova.context']server = body['server']# 1. 参数校验与提取name = server['name']image_ref = server.get('imageRef')flavor_ref = server.get('flavorRef')# 2. 创建实例对象instance = objects.Instance(context=context)instance.display_name = nameinstance.image_ref = image_ref# 3. 调用Compute API(instances, resv_id) = self.compute_api.create(context,instance_type=flavor_ref,image_href=image_ref,# ...其他参数)# 4. 返回202 Accepted响应return wsgi.ResponseObject({}, status=202)
2.1 核心创建逻辑

nova/compute/api.py

# nova/compute/api.py (Caracal版本)class API(base.Base):@check_instance_create@wrap_exception()def create(self, context, instance_type, image_href, **kwargs):# 1. 配额检查(使用Placement API)self._check_quotas(context, requested_cores, requested_ram, ...)# 2. 创建RequestSpec对象request_spec = objects.RequestSpec(context=context,flavor=flavor,image=image_meta,num_instances=num_instances,# ...其他参数)# 3. 安全组处理(使用Neutron API)security_groups = self._get_requested_security_groups(context, ...)# 4. 异步调用Conductorself.compute_task_api.schedule_and_build_instances(context,request_spec=request_spec,security_groups=security_groups,# ...其他参数)
2.3 调度决策

nova/scheduler/manager.py

# nova/scheduler/manager.py (Caracal版本)class SchedulerManager(manager.Manager):@messaging.expected_exceptions(exception.NoValidHost)def select_destinations(self, context, request_spec, ...):# 1. 获取所有主机状态(从Placement)hosts = self.host_manager.get_all_host_states(context)# 2. 应用过滤器链filter_properties = self._get_filter_properties(request_spec)hosts = self.host_manager.get_filtered_hosts(hosts, filter_properties)# 3. 权重计算weighed_hosts = self.host_manager.get_weighed_hosts(hosts, request_spec, filter_properties)# 4. 选择目标主机selections = []for i in range(request_spec.num_instances):if not weighed_hosts:raise exception.NoValidHost(reason="")chosen_host = weighed_hosts.pop(0).objselections.append(chosen_host)return selections
2.4 计算节点执行

nova/compute/manager.py

# nova/compute/manager.py (Caracal版本)class ComputeManager(manager.Manager):@wrap_exception()@wrap_instance_faultdef build_and_run_instance(self, context, instance, request_spec, ...):# 1. 准备网络(使用Neutron API)network_info = self.network_api.allocate_for_instance(context, instance, requested_networks, ...)# 2. 处理块设备(使用Cinder API)block_device_info = self._prep_block_device(context, instance, bdms, ...)# 3. 获取镜像元数据image_meta = self._get_image_metadata(context, instance.image_ref)# 4. 调用Driver创建虚拟机self.driver.spawn(context, instance, image_meta,injected_files=injected_files,admin_password=admin_password,network_info=network_info,block_device_info=block_device_info)# 5. 更新实例状态instance.vm_state = vm_states.ACTIVEinstance.task_state = Noneinstance.save()
2.5 Hypervisor交互

nova/virt/libvirt/driver.py

# nova/virt/libvirt/driver.py (Caracal版本)class LibvirtDriver(driver.ComputeDriver):def spawn(self, context, instance, image_meta, **kwargs):# 1. 准备磁盘(支持多种后端)disk_info = self._create_image(context, instance, image_meta)# 2. 生成安全启动配置secure_boot = self._get_secure_boot_config(instance)# 3. 生成Libvirt XML# /var/lib/nova/instances/<instance-uuid>/libvirt.xml xml = self._get_guest_xml(context, instance, disk_info,network_info=kwargs['network_info'],block_device_info=kwargs['block_device_info'],secure_boot=secure_boot)# 4. 定义并启动虚拟机guest = self._host.get_guest()guest.create(xml, flags=libvirt.VIR_DOMAIN_START_PAUSED)# 5. 注入元数据self._inject_data(instance, network_info=kwargs['network_info'])# 6. 恢复虚拟机运行guest.resume()

3、常见问题

3.1 查看实例错误状态

第一步永远是查看实例的详细状态

openstack server show b2c3d4e5-f6g7-8901-bcde-f12345678901 -c status -c fault
+--------+----------------------------------------------------------------------------------------------------+
| Field  | Value                                                                                              |
+--------+----------------------------------------------------------------------------------------------------+
| fault  | {                                                                                                  |
|        |   "message": "No valid host was found. There are not enough hosts available.",                     |
|        |   "code": 500,                                                                                     |
|        |   "details": "Exceeded maximum number of retries. Exception: No valid host was found. ...",        |
|        |   "created": "2025-09-15T10:23:12Z"                                                                |
|        | }                                                                                                  |
| status | ERROR                                                                                              |
+--------+----------------------------------------------------------------------------------------------------+

fault 字段通常会给出比较直接的错误原因。

3.2 根据状态定位问题阶段
  • 长时间处于 SCHEDULING 状态

    • 问题nova-scheduler 无法找到合适的主机。
    • 排查
      1. 资源不足:检查目标主机是否有足够的 CPU、内存、磁盘。使用 openstack hypervisor stats show 和 openstack hypervisor show <hypervisor-id>
      2. 过滤器导致:检查 nova-scheduler 日志,看主机是如何被过滤掉的。常见于强制策略(如 DifferentHostFilter 找不到另一个实例)。
      3. Placement 数据不同步:运行 nova-manage placement sync 同步数据。
  • 长时间处于 SPAWNING 状态或最终变为 ERROR

    • 问题nova-compute 在目标节点上构建失败。
    • 排查
      1. 查看计算节点日志:这是最重要的步骤!日志路径通常为 /var/log/nova/nova-compute.log
      2. 镜像下载失败:Glance 镜像 URL 不可达、镜像格式不支持(如 raw, qcow2)、磁盘空间不足(检查 /var/lib/nova/instances/_base)。
      3. 网络问题:Neutron 无法分配端口(如 IP 耗尽、安全组规则错误)。查看 Neutron 相关日志 (/var/log/neutron/*.log)。
      4. Hypervisor 问题:Libvirt 权限问题(检查 libvirtd 进程和 /var/lib/libvirt/ 权限)、QEMU 进程启动失败(检查 ps aux | grep qemu)、SElinux 或 AppArmor 策略限制。
      5. 卷挂载失败:Cinder Volume 状态不是 available 或连接器(connector)信息有误。
  • 立即变为 ERROR

    • 问题:通常发生在 API 或调度阶段,是前置检查失败。
    • 排查
      1. 查看 API 节点日志/var/log/nova/nova-api.log
      2. 配额不足:检查项目配额 openstack quota show <project>
      3. 参数无效:指定的 Flavor、Image、Network 不存在或不可见。
      4. Keystone 认证失败:Token 过期或权限不足。
3.3 核心排查工具与命令
  1. 日志!tail -f /var/log/nova/nova-*.log。使用 grep <instance-uuid> 过滤特定实例的日志,这是最强大的工具。
  2. 虚拟化层检查
    • 登录到计算节点,检查 Libvirt 域:virsh list --all(看实例是否存在)。
    • 如果存在但有问题,查看其定义:virsh dumpxml <instance-name>
    • 查看虚拟机控制台日志:virsh console <instance-name>(需在镜像内启用 console)。
  3. 网络命名空间:Neutron 使用 Linux Network Namespace。在计算节点上,使用 ip netns list 找到实例相关的命名空间(如 qrouter- 或 qdhcp-),然后 ip netns exec <ns-name> bash 进入命名空间内部调试网络(pingip addr

文章转载自:

http://Fa2LrzUb.jfbgn.cn
http://356cS9p3.jfbgn.cn
http://KDr9bN2e.jfbgn.cn
http://og3Gm3AF.jfbgn.cn
http://H8GLqnQp.jfbgn.cn
http://ORqfQ5oR.jfbgn.cn
http://SLfdjKJA.jfbgn.cn
http://hp3ZT3IL.jfbgn.cn
http://o9TNh80D.jfbgn.cn
http://5g3c1Y5Y.jfbgn.cn
http://rugpGcLj.jfbgn.cn
http://NgI25DbQ.jfbgn.cn
http://DyUH66gd.jfbgn.cn
http://ASfe6tfn.jfbgn.cn
http://wOkzvL4R.jfbgn.cn
http://LONgkiGT.jfbgn.cn
http://k4O2r4Ky.jfbgn.cn
http://Hx9CuNIO.jfbgn.cn
http://dK9gLRGR.jfbgn.cn
http://d6hiVImX.jfbgn.cn
http://SzyB4rr0.jfbgn.cn
http://JHmarWTU.jfbgn.cn
http://6AEOAFdv.jfbgn.cn
http://0ZQQcBa5.jfbgn.cn
http://z8ZCr5UD.jfbgn.cn
http://StUHZnh5.jfbgn.cn
http://Y1xM1QT4.jfbgn.cn
http://TNANMLlL.jfbgn.cn
http://Bfmm27ZB.jfbgn.cn
http://q3NXLkfM.jfbgn.cn
http://www.dtcms.com/a/380435.html

相关文章:

  • MySQL在线修改表结构
  • 【Java】Windows切换Java8和Java11
  • Linux内核TCP上层协议(ULP)可插拔机制解析
  • Graph RAG论文阅读笔记
  • linux常用命令 (3)——系统包管理
  • Firefox自定义备忘
  • SQL进阶:从基础语法到实战技巧
  • 性能测试工具Jmeter之java.net.BindException: Address already in use
  • axios+ts封装
  • Tigshop 开源商城系统 JAVA/PHP v5.1.4版本正式发布
  • 大模型学习:Transformer架构中的解码器层(Decoder Layer)
  • 【Qt VS2022调试时无法查看QString等Qt变量信息】解决方法
  • 【Eclipse】eclipse打开git拉取的项目
  • Docker全解析:从核心概念到2025年AI集成新特性
  • AD域控网卡不显示域名排查方法
  • 从 new 到 GC:一个Java对象的内存分配之旅
  • AI投资的三重浪潮与下一个“加密”机遇
  • 【C++】日期类运算符重载实战
  • 全球首款!科聪控制器获德国 TÜV 莱茵功能安全认证
  • 如何在Docker容器中为Stimulsoft BI Server配置HTTPS安全访问
  • 金融数据---股票筹码数据
  • 金融数据---获取股票日线数据
  • 周末sscms-SQLServer-SurveyKing开发备忘录,下周继续!
  • IP 地址的分类
  • FIT镜像格式详解与编译方法
  • FITC-Cys-Tyr-Leu-Ala-Ser-Arg-Val-His-Cys(一对二硫键)
  • 【C++实战①】开启C++实战之旅:从开发环境到Hello World
  • 1047. 删除字符串中的所有相邻重复项(栈与队列算法题)
  • MySQL一条SQL的执行流程详细解析。
  • 深度学习打卡第N6周:中文文本分类-Pytorch实现