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 的阶段。

    相关阅读:

  • 相关阅读:
    Codeforces 992C(数学)
    Codeforces 990C (思维)
    Codeforces 989C (构造)
    POJ 1511 Invitation Cards(链式前向星,dij,反向建边)
    Codeforces 1335E2 Three Blocks Palindrome (hard version)(暴力)
    POJ 3273 Monthly Expense(二分)
    POJ 2566 Bound Found(尺取前缀和)
    POJ 1321 棋盘问题(dfs)
    HDU 1506 Largest Rectangle in a Histogram(单调栈)
    POJ 2823 Sliding Window(单调队列)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13310768.html
Copyright © 2011-2022 走看看