zoukankan      html  css  js  c++  java
  • Openstack Nova 源码分析 — Create instances (nova-conductor阶段)

    目录

    前言

    Nova 控制着一个个虚拟机的状态变迁和生命周期,这种对虚拟机生命周期的管理是由 nova-compute service 来完成的。
    在了解 Nova 创建虚拟机的流程之前,需要先补充一些 Openstack 基本概念。

    Instance

    Instance 表示一个虚拟机,是虚拟化世界的个体,类似与现实世界中的人类。所以,相同的,Instance 也具有一些特征性的标识,也可以称之为属性。如下:
    1. 一个唯一的 ID 去标识 Instance
    2. 一些描述 Instance 规格特征的信息。EG. Size/内存/InstanceName
    3. 有字段去表示 Instance 运行在哪一台 Host
    4. 有字段去表示 Instance Status
    5. 有字段去表示 Create | Delete Instance 的时间

    Nova 在 /opt/stack/nova/nova/objects/instance.py 中对 Instance 进行了描述。
    NOTE/opt/stack/nova/nova/objects/ 该目录下存放数据库表对象文件,一个 Class 映射到一个张数据库表。

    86   class _BaseInstance(base.NovaPersistentObject, base.NovaObject,
       1                     base.NovaObjectDictCompat):
       2     fields = {
       3         'id': fields.IntegerField(),
       4             
       5         'user_id': fields.StringField(nullable=True),
       6         'project_id': fields.StringField(nullable=True),
       7             
         ...

    Flavor

    在 Create Instance 之前,需要为 Instance 指定一组资源(Disk/Memory/VCPU/RootDisk/EphemeralDisk/Swap)。
    nova-compute 在执行创建之前,需要通过这些资源配置来判断是否由足够的 Host 资源来实现创建。这组资源的设置就是 flavor,即创建虚拟机的规格。每个 Instance 对象的 instance_type_id 字段就表示该 Instance 所拥有的 flavor 。

    执行 Commands :nova flavor-list 可以查看 Nova 默认 flavor 的信息 ; nova flavor-create 创建新的 flavor 。

    Instance Status

    Instance 拥有三个字段与描述其状态有关,这些状态刚被用于程序流的条件判断。

    • power_status: 使用 libvirt 或 Virt Driver 提供的接口从 Hypervisor 中获取的 Instance Power Status。

      • Running
      • Shutdown
      • NoState
    • vm_state: 虚拟机的稳定状态。

      • Active:正常运行
      • Suspended:停止运行
    • task_state:过渡状态,与 Compute API 的执行密切相关,表示 Instance 正在执行什么任务,只有在执行任务的时候才会有 task_state 。

    Virt Driver

    Openstack Nova 仅仅是作为云计算虚拟机的管理工具,其本身并不提供任何的虚拟化技术,而是交由具体的 Hypervisor 来实现虚拟机的创建和管理。因此,nova-compute 需要和不同的 Hpyervisor 进行交互,并使用 Virt Driver 来作为这种交互的支撑,其代码实现存放在 /opt/stack/nova/nova/virt/ 目录下。

    目前,Nova 实现了 Hyper-V/Libvirt/VMware/Xen 这四种 Virt Dirver 。可以通过配置选项 compute_dirver 来指定使用哪一种 Virt Driver 。

    compute_driver = libvirt.LibvirtDriver
    compute_driver=vmwareapi.VMwareVCDriver

    EXAMPLE:nova-compute 通过 Virt Dirver 来调用 Libvirt 库中提供的 API 来实现虚拟机的管理。
    这里写图片描述

    从上图可以看出,nova-compute 必须部署在 Linux+KVM 的 Host 上,当然,现在的 Linux Kernel Version 大多都嵌入了 KVM 虚拟化技术。

    Resource Tracker

    nova-compute 需要在数据库中存储 Host 的资源使用情况,以便于 nova-scheduler 获取作为选择 Host 依据的数据。Node Project 使用 ConputeNode 数据库表对象来保存 Compute Node的配置信息和资源使用情况(/opt/stack/nova/nova/objects/compute_node.py)。所以 nova-compute 会为每一个 Host 创建一个 ResourceTracker 对象,用于更新 ComputeNode 对象在数据库中对应的 compute_nodes 表。

    有两种更新*compute_nodes表的方式:*

    • Claim 机制:在创建 Instance 之前,预先测试 Host 的可用资源能否满足 Create Instance。如果满足,则首先更新数据库,将虚拟机申请的资源从可用资源中减去。 如果后来创建失败或者将虚拟机删除时,会再通过 Claim 将原来减去的部分再添加到可用资源中去。实现:nova.compute.resource_tracker:instance_claims

    • Periodic Task:在 nova.compute.manager.ComputeManager 中有个周期性任务 update_available_resource() 用于更新 Host 的资源数据。

    NOTE:上面两种数据库更新方式并不冲突。Claim 实在数据库当前数据的基础上去计算并更新,可以保证数据库里可用资源的及时更新。 Periodic Task 是为了数据库内信息的准确性,它每次执行都会通过 Hypervisor 去获取 Host 的信息,并将这些信息更新到数据库中。前者是在 Create Instance 的时候执行,后者是周期性执行。

    nova-conductor

    Conductor Service 的加入,使得 nova-compute 和数据库解耦,为数据库提供了一重安全保障,提高了对数据库的访问效率,而且还可以实现升级数据库 schema 的同时无需上级 nova-compute 。所以 nova-compute 所有访问数据库的操作都是交由 nova-conductor 去完成。

    随着 nova-conductor 的不断完善,它还需要承担部分原来属于 nova-compute 的 TaskAPI 的任务。TaskAPI 主要包含了耗时较长的任务,例如:Create Instance/Migrate Instance 等等。

    Create Instance(nova-conductor阶段)

    Create Instance 属于 TaskAPI 任务,耗时较长,由 nova-conductor 来承担。但是需要注意的是,对 Instance 管理的流程可以分为俩个阶段,就是调度阶段和执行阶段。调度阶段由 Openstack 负责,主要是 Nova Project 中的几个 Services 来协同完成。而执行阶段则由 Hypervisor 来具体实现。Openstack 仅仅扮演了 管理者的角色。

    这里写图片描述

    • nova.conductor.rpcapi 中定义一个 build_instances() RPC 接口函数:
    301     def build_instances(self, context, instances, image, filter_properties,                                 
      1             admin_password, injected_files, requested_networks,
      2             security_groups, block_device_mapping, legacy_bdm=True):
      3         image_p = jsonutils.to_primitive(image)
      4         version = '1.10'
      5         if not self.client.can_send_version(version):
      6             version = '1.9'
      7             if 'instance_type' in filter_properties:
      8                 flavor = filter_properties['instance_type']
      9                 flavor_p = objects_base.obj_to_primitive(flavor)
     10                 filter_properties = dict(filter_properties,
     11                                          instance_type=flavor_p)
     12         kw = {'instances': instances, 'image': image_p,
     13                'filter_properties': filter_properties,
     14                'admin_password': admin_password,
     15                'injected_files': injected_files,
     16                'requested_networks': requested_networks,
     17                'security_groups': security_groups}
     18         if not self.client.can_send_version(version):
     19             version = '1.8'
     20             kw['requested_networks'] = kw['requested_networks'].as_tuples()
     21         if not self.client.can_send_version('1.7'):
     22             version = '1.5'
     23             bdm_p = objects_base.obj_to_primitive(block_device_mapping)
     24             kw.update({'block_device_mapping': bdm_p,
     25                        'legacy_bdm': legacy_bdm})
     26          
     27         cctxt = self.client.prepare(version=version)
     28         cctxt.cast(context, 'build_instances', **kw)
    
    # /opt/stack/nova/nova/conductor/manager.py
    # 创建虚拟机属于 TaskAPI 任务,所有的 TaskAPI 都交由 nova-conductor 来处理,所以 manager.py 的实现在 Conductor 中
    515 class ComputeTaskManager(base.Base):                                                             
      1     """Namespace for compute methods.
      2  
      3     This class presents an rpc API for nova-conductor under the 'compute_task'
      4     namespace.  The methods here are compute operations that are invoked
      5     by the API service.  These methods see the operation to completion, which
      6     may involve coordinating activities on multiple compute nodes.
      7     """
        ... 
    526     def __init__(self):                                                     
      1         super(ComputeTaskManager, self).__init__()
      2         self.compute_rpcapi = compute_rpcapi.ComputeAPI()           
      3         self.image_api = image.API()
      4         self.servicegroup_api = servicegroup.API()
      5         self.scheduler_client = scheduler_client.SchedulerClient()  
      6         self.notifier = rpc.get_notifier('compute', CONF.host)
    
            # 其中 Scheduler client 是对 Scheduler_rpcapi 的封装,本质上是一个 Scheduler 提供的 rpcapi:
            #    nova.manager.ComputeTaskManager:scheduler_client 
            #        ==> nova.scheduler.client.__init__:__init__ 
            #             ==> nova.scheduler.client.query.SchedulerQueryClient:__init__
            #                 ==> self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()
        ...
    
            # 1.(被调用) HTTP Request ==> nova.api ==> RPC cast ==> nova-conductor (nova.conductor.manager:ComputeTaskManager.build_instances() 是 nova.conductor.rpcapi.build_instances RPC 接口的实际功能实现函数)     
            # 参数传递过程: nova-api 调用 conductor.rpcapi:build_instances() 并传入实参 
            #                 ==> 将实参和其他信息打包发送到消息队列(数据流形式) 
            #                    ==> 将实参传入 conductor.manager:build_instances() ; 
    708     def build_instances(self, context, instances, image, filter_properties,    
      1             admin_password, injected_files, requested_networks,
      2             security_groups, block_device_mapping=None, legacy_bdm=True):
      3         # TODO(ndipanov): Remove block_device_mapping and legacy_bdm in version
      4         #                 2.0 of the RPC API.
    713         request_spec = scheduler_utils.build_request_spec(context, image,
      1                                                           instances)
                # request_spec 是一个字典类型,包含了详细的虚拟机信息,nova-scheduler 依据这些信息来选择一个最佳的主机并返回给 nova-conductor
    
        ... 
                    # 2.(调用) nova-conductor 通过 RPC call 方式调用 nova-scheduler 的接口函数: nova.scheduler.rpcapi:select_destinations()
                    # 通过 nova-scheduler 来获取 HOSTS 
    738             hosts = self.scheduler_client.select_destinations(context,                               
      1                     request_spec, filter_properties)
        ...
    
                    # 3.(调用) nova-conductor ==> RPC cast ==> nova-compute (nova.compute.build_and_run_instance())  
    763             self.compute_rpcapi.build_and_run_instance(context,                
      1                     instance=instance, host=host['host'], image=image,
      2                     request_spec=request_spec,
      3                     filter_properties=local_filter_props,
      4                     admin_password=admin_password,
      5                     injected_files=injected_files,
      6                     requested_networks=requested_networks,
      7                     security_groups=security_groups,
      8                     block_device_mapping=bdms, node=host['nodename'],
      9                     limits=host['limits'])
    
    

    在 经过一番远程调用之后,终于进入到了 nova-compute 调用 Virt Dirver 的阶段。

  • 相关阅读:
    Leetcode709.To Lower Case转换成小写字母
    Leetcode709.To Lower Case转换成小写字母
    Leetcode717.1-bit and 2-bit Characters1比特与2比特字符
    Leetcode717.1-bit and 2-bit Characters1比特与2比特字符
    Leetcode703.Kth Largest Element in a Stream数据流中的第K大元素
    Leetcode703.Kth Largest Element in a Stream数据流中的第K大元素
    30套JSP网站源代码合集
    BeanUtils包的使用
    windows10+mysql8.0.11zip安装
    win10下vscode配置sftp
  • 原文地址:https://www.cnblogs.com/jmilkfan-fanguiju/p/7532327.html
Copyright © 2011-2022 走看看