OpenStack Placement Project 目录 背景 Placement 简介 Placement Web Application 的实现与分析 Placement 在启动虚拟机时的调度过程 Resource provider aggregates 功能测试 Resource traits 功能测试 最后 扩展阅读

OpenStack Placement Project
目录
背景
Placement 简介
Placement Web Application 的实现与分析
Placement 在启动虚拟机时的调度过程
Resource provider aggregates 功能测试
Resource traits 功能测试
最后
扩展阅读

背景

私有云的用户,尤其是传统 IT 架构转型的私有云用户一般会拥有各式各样的存量资源系统,与这些系统对接会让 OpenStack 的资源体系变得复杂。

从用户的角度出发,或许你会希望

  • 作为使用共享存储解决方案的用户,我会希望 Nova 和 Horizon 能够正确报告共享存储磁盘资源的总量和使用量信息。

  • 作为高级的 Neutron 用户,我预期会使用外部的第三方路由网络功能,希望 Nova 能够掌握和使用特定的网络端口与特定的子网池相关联,确保虚拟机能够在该子网池上启动。

  • 作为高级的 Cinder 用户,我希望当我在 nova boot 命令中指定了 cinder volume-id 后 Nova 能够知道哪一些计算节点与 Request Volume 所在的 Cinder 存储池相关联。

所以,OpenStack 除了要处理计算节点 CPU,内存,PCI 设备、本地磁盘等内部资源外,还经常需要纳管有如 SDS、NFS 提供的存储服务,SDN 提供的网络服务等外部资源。

但在以往,Nova 只能处理由计算节点提供的资源。Nova Resource Tracker 假定所有资源均来自计算节点,因此在周期性上报资源状况时,Resource Tracker 只会单纯对计算节点清单进行资源总量和使用量的加和统计。显然,这无法满足上述复杂的生产需求,也违背了 OpenStack 一向赖以自豪的开放性原则。而且随着 OpenStack 的定义被社区进一步升级为「一个开源基础设施集成引擎」,意味 OpenStack 的资源系统将会由更多外部资源类型构成。

所以,当资源类型和提供者变得多样时,自然就需求一种高度抽象且简单统一的管理方法,让用户和代码能够便捷的使用、管理、监控整个 OpenStack 的系统资源,这就是 Placement(布局)

Placement 简介

Placement 肩负着这样的历史使命,最早在 Newton 版本被引入到 openstack/nova repo,以 API 的形式进行孵化,所以也经常被称呼为 Placement API。它参与到 nova-scheduler 选择目标主机的调度流程中,负责跟踪记录 Resource Provider 的 Inventory 和 Usage,并使用不同的 Resource Classes 来划分资源类型,使用不同的 Resource Traits 来标记资源特征。

NOTE:Ocata 版本的 Placement API 是一个可选项,建议用户启用并替代 CpuFilter、CoreFilter 和 DiskFilter。Pike 版本则强制要求启动 Placement API 服务,否则 nova-compute service 无法正常运行。

直至成文前段时间(2018/11),Placement API 开始了 openstack/nova repo 剥离流程,从 Placement API 蜕变为 OpenStack Placement,并计划在 Stein 版本中成为独立项目,期望最终能替代 nova-scheduler service。虽然现在的 OpenStack Placement 还不稳定,但毋容置疑,Placement 就是 OpenStack 云平台统一资源管理的未来,是开放集成引擎蓝图的地基。

OpenStack Placement provides an HTTP service for managing, selecting, and claiming providers of classes of inventory representing available resources in a cloud.

Placement 拥有独立的 REST API。

[root@control01 ~]# openstack catalog show placement
+-----------+------------------------------------------+
| Field     | Value                                    |
+-----------+------------------------------------------+
| endpoints | RegionOne                                |
|           |   public: http://172.18.22.222/placement |
|           |                                          |
| id        | 9b5683b4a5284369bafad76944a0610f         |
| name      | placement                                |
| type      | placement                                |
+-----------+------------------------------------------+

Placement 拥有独立的数据库和数据模型。

MariaDB [(none)]> use placement

MariaDB [placement]> show tables;
+------------------------------+
| Tables_in_placement          |
+------------------------------+
| alembic_version              |
| allocations                  |
| consumers                    |
| inventories                  |
| placement_aggregates         |
| projects                     |
| resource_classes             |
| resource_provider_aggregates |
| resource_provider_traits     |
| resource_providers           |
| traits                       |
| users                        |
+------------------------------+

NOTE:本篇主要分析、记录 1.0 版本的 Placement 实现。

[root@control01 ~]# openstack versions show --service placement
+-------------+--------------+---------+---------+---------------------------------+------------------+------------------+
| Region Name | Service Type | Version | Status  | Endpoint                        | Min Microversion | Max Microversion |
+-------------+--------------+---------+---------+---------------------------------+------------------+------------------+
| RegionOne   | placement    | 1.0     | CURRENT | http://172.18.22.222/placement/ | 1.0              | 1.30             |
+-------------+--------------+---------+---------+---------------------------------+------------------+------------------+

基本概念

Resource Provider:资源提供者,实际提供资源的实体,例如:Compute Node、Storage Pool、IP Pool 等。

Resource Class:资源种类,即资源的类型,Placement 为 Compute Node 缺省了下列几种类型,同时支持 Custom Resource Classes。

[root@control01 ~]# export OS_PLACEMENT_API_VERSION=1.17

[root@control01 ~]# openstack resource class list
+----------------------------+
| name                       |
+----------------------------+
| VCPU                       |
| MEMORY_MB                  |
| DISK_GB                    |
| PCI_DEVICE                 |
| SRIOV_NET_VF               |
| NUMA_SOCKET                |
| NUMA_CORE                  |
| NUMA_THREAD                |
| NUMA_MEMORY_MB             |
| IPV4_ADDRESS               |
| VGPU                       |
| VGPU_DISPLAY_HEAD          |
| NET_BW_EGR_KILOBIT_PER_SEC |
| NET_BW_IGR_KILOBIT_PER_SEC |
+----------------------------+

Inventory:资源清单,资源提供者所拥有的资源清单,例如:Compute Node 拥有的 vCPU、Disk、RAM 等 inventories。

Provider Aggregate:资源聚合,类似 HostAggregate 的概念,是一种聚合类型。

Traits:资源特征,不同资源提供者可能会具有不同的资源特征。Traits 作为资源提供者特征的描述,它不能够被消费,但在某些 Workflow 或者会非常有用。例如:标识可用的 Disk 具有 SSD 特征,有助于 Scheduler 灵活匹配 Launch Instance 的请求。

Resource Allocations:资源分配状况,包含了 Resource Class、Resource Provider 以及 Consumer 的映射关系。记录消费者使用了该类型资源的数量。

数据模型解析

Data Models

  • ResourceProvider:资源提供者
  • Inventory:资源提供者的资源清单
  • ResourceClass:资源种类
  • ResourceProviderAggregate:资源聚合,实际上是资源提供者和主机聚合的映射关系
  • Trait:资源特征描述类型
  • ResourceProviderTrait:资源提供者和特征描述的对应关系
  • Allocation:分配给消费者的资源状况
  • Consumer:消费者,本质是一串 UUID
  • User:Keystone User

Resource Provider Inventory 的属性

MariaDB [nova_api]> desc inventories;
+----------------------+----------+------+-----+---------+----------------+
| Field                | Type     | Null | Key | Default | Extra          |
+----------------------+----------+------+-----+---------+----------------+
| created_at           | datetime | YES  |     | NULL    |                |
| updated_at           | datetime | YES  |     | NULL    |                |
| id                   | int(11)  | NO   | PRI | NULL    | auto_increment |
| resource_provider_id | int(11)  | NO   | MUL | NULL    |                |
| resource_class_id    | int(11)  | NO   | MUL | NULL    |                |
| total                | int(11)  | NO   |     | NULL    |                |  总大小
| reserved             | int(11)  | NO   |     | NULL    |                |  保留大小
| min_unit             | int(11)  | NO   |     | NULL    |                |  最小分配单位
| max_unit             | int(11)  | NO   |     | NULL    |                |  最大分配单位
| step_size            | int(11)  | NO   |     | NULL    |                |  步长
| allocation_ratio     | float    | NO   |     | NULL    |                |  超分比
+----------------------+----------+------+-----+---------+----------------+

每个 Compute Node 缺省有 3 条 inventories 记录 0,1,2 分别对应 3 种资源种类 CPU(s)、RAM(MB) 和 DISK(GB)

MariaDB [nova_api]> select * from resource_providers;
+---------------------+---------------------+-----+--------------------------------------+------------------------------------------------------+------------+----------+
| created_at          | updated_at          | id  | uuid                                 | name                                                 | generation | can_host |
+---------------------+---------------------+-----+--------------------------------------+------------------------------------------------------+------------+----------+
| 2018-05-03 09:07:01 | 2018-07-02 07:03:57 |   1 | e367ded8-9501-42b1-a18d-e7f3bab233c6 | domain-c69.22bebe01-eb68-4a5c-839d-11398df43232      |        252 |     NULL |

MariaDB [nova_api]> select * from inventories;
+---------------------+---------------------+----+----------------------+-------------------+--------+----------+----------+----------+-----------+------------------+
| created_at          | updated_at          | id | resource_provider_id | resource_class_id | total  | reserved | min_unit | max_unit | step_size | allocation_ratio |
+---------------------+---------------------+----+----------------------+-------------------+--------+----------+----------+----------+-----------+------------------+
| 2018-05-03 09:07:07 | 2018-07-02 07:03:57 |  1 |                    1 |                 0 |     42 |        0 |        1 |       42 |         1 |                2 |
| 2018-05-03 09:07:07 | 2018-07-02 07:03:57 |  2 |                    1 |                 1 | 407562 |     2048 |        1 |   407562 |         1 |                1 |
| 2018-05-03 09:07:07 | 2018-07-02 07:03:57 |  3 |                    1 |                 2 |    736 |        2 |        1 |      736 |         1 |                1 |

如何查看消费者使用了哪一个资源提供者的哪几种资源种类及数量?e.g. 消费者(虚拟机 648bda64-1d7a-44d2-ba38-20c84959dabe)使用了资源提供者 97 的 1U/256M/1G 的 CPU/RAM/DISK 资源。

MariaDB [nova_api]> select * from allocations;
+---------------------+------------+-----+----------------------+--------------------------------------+-------------------+------+
| created_at          | updated_at | id  | resource_provider_id | consumer_id                          | resource_class_id | used |
+---------------------+------------+-----+----------------------+--------------------------------------+-------------------+------+
| 2018-05-23 10:40:49 | NULL       |  97 |                   97 | 648bda64-1d7a-44d2-ba38-20c84959dabe |                 0 |    1 |
| 2018-05-23 10:40:49 | NULL       |  98 |                   97 | 648bda64-1d7a-44d2-ba38-20c84959dabe |                 1 |  256 |
| 2018-05-23 10:40:49 | NULL       |  99 |                   97 | 648bda64-1d7a-44d2-ba38-20c84959dabe |                 2 |    1 |

如何查看消费者分配了的资源状况?e.g. 查看分配给消费者(虚拟机 648bda64-1d7a-44d2-ba38-20c84959dabe)的资源状况。

MariaDB [nova_api]> select * from allocations;
+---------------------+------------+----+----------------------+--------------------------------------+-------------------+------+
| created_at          | updated_at | id | resource_provider_id | consumer_id                          | resource_class_id | used |
+---------------------+------------+----+----------------------+--------------------------------------+-------------------+------+
| 2018-08-01 10:52:15 | NULL       |  7 |                    1 | f8d55035-389c-47b8-beea-02f00f25f5d9 |                 0 |    1 |
| 2018-08-01 10:52:15 | NULL       |  8 |                    1 | f8d55035-389c-47b8-beea-02f00f25f5d9 |                 1 |  512 |
| 2018-08-01 10:52:15 | NULL       |  9 |                    1 | f8d55035-389c-47b8-beea-02f00f25f5d9 |                 2 |    1 |
+---------------------+------------+----+----------------------+--------------------------------------+-------------------+------+

# consumer_id 消费者
# resource_class_id 资源类型
# resource_provider_id 资源提供者
# used 分配的数量

Command Line

Placement CLI 以 OS Client Placement Plugin 的形式提供,是 openstackclient 子命令的扩展。

Installation

pip install python-openstackclient
pip install osc-placement

EXAMPLE

[root@control01 ~]# export OS_PLACEMENT_API_VERSION=1.17

[root@control01 ~]# openstack resource provider list
+--------------------------------------+-----------+------------+--------------------------------------+----------------------+
| uuid                                 | name      | generation | root_provider_uuid                   | parent_provider_uuid |
+--------------------------------------+-----------+------------+--------------------------------------+----------------------+
| 5c5a578f-51b0-481c-b38c-7aaa3394e585 | control01 |         25 | 5c5a578f-51b0-481c-b38c-7aaa3394e585 | None                 |
+--------------------------------------+-----------+------------+--------------------------------------+----------------------+

[root@control01 ~]# openstack resource provider inventory list 5c5a578f-51b0-481c-b38c-7aaa3394e585
+----------------+------------------+----------+----------+-----------+----------+-------+
| resource_class | allocation_ratio | max_unit | reserved | step_size | min_unit | total |
+----------------+------------------+----------+----------+-----------+----------+-------+
| VCPU           |             16.0 |       32 |        0 |         1 |        1 |    32 |
| MEMORY_MB      |              1.5 |    40959 |      512 |         1 |        1 | 40959 |
| DISK_GB        |              1.0 |       49 |        0 |         1 |        1 |    49 |
+----------------+------------------+----------+----------+-----------+----------+-------+

[root@control01 ~]# openstack resource provider usage show 5c5a578f-51b0-481c-b38c-7aaa3394e585
+----------------+-------+
| resource_class | usage |
+----------------+-------+
| VCPU           |     5 |
| MEMORY_MB      |  3648 |
| DISK_GB        |     7 |
+----------------+-------+

[root@control01 ~]# openstack allocation candidate list --resource VCPU=1
+---+------------+--------------------------------------+-------------------------+--------------------------------------------------------------+
| # | allocation | resource provider                    | inventory used/capacity | traits                                                       |
+---+------------+--------------------------------------+-------------------------+--------------------------------------------------------------+
| 1 | VCPU=1     | 5c5a578f-51b0-481c-b38c-7aaa3394e585 | VCPU=5/512              | HW_CPU_X86_SSE2,HW_CPU_X86_SSE,HW_CPU_X86_MMX,HW_CPU_X86_SVM |
+---+------------+--------------------------------------+-------------------------+--------------------------------------------------------------+

更多详细请浏览 Command Line Reference

NOTE:这里指定 micro-version 为 1.17,通过环境变量 OS_PLACEMENT_API_VERSION 指定,也可以通过 request header OpenStack-API-Version: placement 1.17 指定。详细的版本 ChangeLog 请浏览 Placement API

Placement Web Application 的实现与分析

要分析 Placement 的实现,实际是分析 placement-api service 的实现,当前 Placement 只提供单一的 API 服务。placement-api 是一个标准的 Python WSGI 实现,WSGI Script 为 placement-api,存放在 usr/bin 或 /usr/local/bin 目录下,WSGI-capable web servers 加载启动。e.g.

/usr/bin/uwsgi --procname-prefix placement --ini /etc/placement/placement-uwsgi.ini

**WSGI(Web Server Gateway Interface,Web 服务器网关接口)**指代一种编程规范,将 Web 系统抽象为 Web Server、Middleware 和 Application 三个层次,实现让不同协议之间的实现可以互相通信,故称之为 “网关”。实现了 WSGI 规范的程序可称为 WSGI 组件,常见的 WSGI 组件有 mod_wsgi、uwsgi 等,Python 代码可以运行在 Apache、Nginx 等 HTTP Server 上也得益于此。简而言之,WSGI 定义了 Web Server 如何与 Python Web Application 进行交互的规则。OpenStack 项目常使用 Apache + WSGI 的组合来支撑 REST API 服务。
— — 范桂飓’s 博客

NOTE:如果是 Devstack 部署的环境,会应用 Apache ProxyPass 机制将 http://<ip>/placement 的访问重定向到 devstack@placement-api service 处理。所以从 catalog 看见的 URL 才会长成这个样子。

ProxyPass "/placement" "unix:/var/run/uwsgi/placement-api.socket|uwsgi://uwsgi-uds-placement-api/" retry=0.

当然了,这种方式对于开发调试有着诸多不便,所以作为开发者可以直接执行指令 placement-api 来启动一个用于测试的 API 服务进程。

[root@control01 placement]# placement-api
...
********************************************************************************
STARTING test server placement.wsgi.init_application
Available at http://control01:8000/
DANGER! For testing only, do not use in production
********************************************************************************

回到正题,这里我们只关注 Web Application 层面的实现。通过 setup.cfg 我们可以找到 placement-api 的程序入口。

wsgi_scripts =
    placement-api = placement.wsgi:init_application

顺着入口往下撸,很快就能找到 placement-api 的实现模块和 Application 类:

# file: /opt/master/placement/placement/handler.py

class PlacementHandler(object):
    """Serve Placement API.

    Dispatch to handlers defined in ROUTE_DECLARATIONS.
    """

    def __init__(self, **local_config):
        self._map = make_map(ROUTE_DECLARATIONS)
        self.config = local_config['config']

API 的 URL Routes、HTTP Method 以及 View function 的 Mapping 实现到了 ROUTE_DECLARATIONS 字典类型对象,所有的 API Resources Class 都被封装在 plcement.handlers 包下,是一个风格非常典型的 REST API 实现。不多赘述。

Placement 在启动虚拟机时的调度过程

OpenStack Placement Project
目录
背景
Placement 简介
Placement Web Application 的实现与分析
Placement 在启动虚拟机时的调度过程
Resource provider aggregates 功能测试
Resource traits 功能测试
最后
扩展阅读

图1. Launch Instance 流程图

上图可见(红色部分)Placement 主要参与到了 nova-scheduler 选择主机的过程。以此切入,继续深入其中的调用细节。

OpenStack Placement Project
目录
背景
Placement 简介
Placement Web Application 的实现与分析
Placement 在启动虚拟机时的调度过程
Resource provider aggregates 功能测试
Resource traits 功能测试
最后
扩展阅读
图2. nova-scheduler 调度主机 UML 图

对于上面整个流程,我们主要关心 nova-scheduler 对 placement-api 的两次调用。第一次,nova-scheduler 向 placement-api 获取一组 Allocation Candidates(分配候选人),所谓 Allocation Candidates 就是能够满足资源需求的 Resource Provider。

EXAMPLE

GET /allocation_candidates?resources=VCPU:1,MEMORY_MB:2048,DISK_GB:100

NOTE:获取 Allocation Candidates 的实现是一系列复杂的数据库级联查询与过滤操作,以 query params 作为过滤条件。该例子传递了 Launch Instance 所需的 vCPU、RAM 和 Disk 资源,除此之外,还可以提供 required 和 member_of 参数,分别用于指定 Resource Traits 和 Resource Provider Aggregate 特性,使 Allocation Candidates 的获取方式更加灵活。更多详情请浏览 Allocation candidates

PS:版本较新的 placement-api 还支持 allocation candidate 指令行操作。

[root@control01 ~]# openstack allocation candidate list --resource VCPU=1,MEMORY_MB=2048,DISK_GB=10 --required HW_CPU_X86_SSE2
+---+----------------------------------+--------------------------------------+----------------------------------------------+--------------------------------------------------------------+
| # | allocation                       | resource provider                    | inventory used/capacity                      | traits                                                       |
+---+----------------------------------+--------------------------------------+----------------------------------------------+--------------------------------------------------------------+
| 1 | VCPU=1,MEMORY_MB=2048,DISK_GB=10 | 5c5a578f-51b0-481c-b38c-7aaa3394e585 | VCPU=5/512,MEMORY_MB=3648/60670,DISK_GB=7/49 | HW_CPU_X86_SSE2,HW_CPU_X86_SSE,HW_CPU_X86_MMX,HW_CPU_X86_SVM |
+---+----------------------------------+--------------------------------------+----------------------------------------------+--------------------------------------------------------------+

placement-api 返回给 nova-scheduler 的 JSON object with a list of allocation requests and a JSON object of provider summary objects 数据结构如下,关键在于 allocation_requests 和 provider_summaries 两个字段,它们在后续的 Scheduler Filters 逻辑中也发挥着重要的作用。

{
  "allocation_requests": [
    <ALLOCATION_REQUEST_1>,
    ...
    <ALLOCATION_REQUEST_N>
  ],
  "provider_summaries": {
    <COMPUTE_NODE_UUID_1>: <PROVIDER_SUMMARY_1>,
    ...
    <COMPUTE_NODE_UUID_N>: <PROVIDER_SUMMARY_N>,
  }
}
  • allocation_requests:包含了所有能够满足需求的 resource provider 及其预期分配的资源清单。
"allocation_requests": [
        {
            "allocations": {
                "a99bad54-a275-4c4f-a8a3-ac00d57e5c64": {
                    "resources": {
                        "DISK_GB": 100
                    }
                },
                "35791f28-fb45-4717-9ea9-435b3ef7c3b3": {
                    "resources": {
                        "VCPU": 1,
                        "MEMORY_MB": 1024
                    }
                }
            }
        },
        {
            "allocations": {
                "a99bad54-a275-4c4f-a8a3-ac00d57e5c64": {
                    "resources": {
                        "DISK_GB": 100
                    }
                },
                "915ef8ed-9b91-4e38-8802-2e4224ad54cd": {
                    "resources": {
                        "VCPU": 1,
                        "MEMORY_MB": 1024
                    }
                }
            }
        }
    ],

NOTE:有趣的是,可以看见提供 VCPU/MEMORY 和 DISK 的 resource provider 并不相同,说明一台虚拟机的资源并非只能由一个 ComputeNode 提供,也可以是 ComputeNode 与外部 Storage Pool 组合提供。

  • provider_summaries:包含了所有满足需求的 resource providers 的各项资源总量和使用量信息。
 "provider_summaries": {
        "a99bad54-a275-4c4f-a8a3-ac00d57e5c64": {
            "resources": {
                "DISK_GB": {
                    "used": 0,
                    "capacity": 1900
                }
            },
            "traits": ["MISC_SHARES_VIA_AGGREGATE"],
            "parent_provider_uuid": null,
            "root_provider_uuid": "a99bad54-a275-4c4f-a8a3-ac00d57e5c64"
        },
        "35791f28-fb45-4717-9ea9-435b3ef7c3b3": {
            "resources": {
                "VCPU": {
                    "used": 0,
                    "capacity": 384
                },
                "MEMORY_MB": {
                    "used": 0,
                    "capacity": 196608
                }
            },
            "traits": ["HW_CPU_X86_SSE2", "HW_CPU_X86_AVX2"],
            "parent_provider_uuid": null,
            "root_provider_uuid": "35791f28-fb45-4717-9ea9-435b3ef7c3b3"
        },
        "915ef8ed-9b91-4e38-8802-2e4224ad54cd": {
            "resources": {
                "VCPU": {
                    "used": 0,
                    "capacity": 384
                },
                "MEMORY_MB": {
                    "used": 0,
                    "capacity": 196608
                }
            },
            "traits": ["HW_NIC_SRIOV"],
            "parent_provider_uuid": null,
            "root_provider_uuid": "915ef8ed-9b91-4e38-8802-2e4224ad54cd"
        },
        "f5120cad-67d9-4f20-9210-3092a79a28cf": {
            "resources": {
                "SRIOV_NET_VF": {
                    "used": 0,
                    "capacity": 8
                }
            },
            "traits": [],
            "parent_provider_uuid": "915ef8ed-9b91-4e38-8802-2e4224ad54cd",
            "root_provider_uuid": "915ef8ed-9b91-4e38-8802-2e4224ad54cd"
        }
    }

NOTE:可以看出 SRIOV_NET_VF 亦被当做为一种资源类型,由专门的 resource provider 提供。

nova-scheduler 在获得了 Allocation Candidates 之后再进一步通过 Filtered 和 Weighed 机制来最终确定目标主机。然后再根据 allocation requests 和 provider summaries 的数据来扣除(claim_resources)目标主机对应的 resource provider 的资源使用量,这就是 nova-scheduler 第二次调用 placement-api 所做的事情。回顾一下 allocations tables 的内容:

MariaDB [nova_api]> select * from allocations;
+---------------------+------------+----+----------------------+--------------------------------------+-------------------+------+
| created_at          | updated_at | id | resource_provider_id | consumer_id                          | resource_class_id | used |
+---------------------+------------+----+----------------------+--------------------------------------+-------------------+------+
| 2018-08-01 10:52:15 | NULL       |  7 |                    1 | f8d55035-389c-47b8-beea-02f00f25f5d9 |                 0 |    1 |
| 2018-08-01 10:52:15 | NULL       |  8 |                    1 | f8d55035-389c-47b8-beea-02f00f25f5d9 |                 1 |  512 |
| 2018-08-01 10:52:15 | NULL       |  9 |                    1 | f8d55035-389c-47b8-beea-02f00f25f5d9 |                 2 |    1 |
+---------------------+------------+----+----------------------+--------------------------------------+-------------------+------+

# consumer_id 消费者
# resource_class_id 资源类型
# resource_provider_id 资源提供者
# used 分配的数量
# 上述记录表示为虚拟机分配了 vCPU 1颗,RAM 512MB,Disk 1GB

显然,其中的 Consumer 消费者就是要创建的虚拟机了。

Resource provider aggregates 功能测试

Resource provider aggregates 是一个类似于 Host Aggregate 的功能,获取 Allocation Candidates 时,支持通过 member_of request query parameter 从特定的 Aggregate 中获取。Resource provider aggregates 非常适用于拥有不同主机聚合( e.g. 高性能主机聚合,大存储容量主机聚合)类型的生产场景中。

  • Create resource provider aggregates
[root@control01 ~]# openstack aggregate create --zone nova host_aggregate_1
+-------------------+----------------------------+
| Field             | Value                      |
+-------------------+----------------------------+
| availability_zone | nova                       |
| created_at        | 2018-12-08T05:49:55.051678 |
| deleted           | False                      |
| deleted_at        | None                       |
| id                | 1                          |
| name              | host_aggregate_1           |
| updated_at        | None                       |
+-------------------+----------------------------+

[root@control01 ~]# openstack aggregate add host host_aggregate_1 control01
+-------------------+---------------------------------+
| Field             | Value                           |
+-------------------+---------------------------------+
| availability_zone | nova                            |
| created_at        | 2018-12-08T05:49:55.000000      |
| deleted           | False                           |
| deleted_at        | None                            |
| hosts             | [u'control01']                  |
| id                | 1                               |
| metadata          | {u'availability_zone': u'nova'} |
| name              | host_aggregate_1                |
| updated_at        | None                            |
+-------------------+---------------------------------+

[root@control01 ~]# openstack aggregate show host_aggregate_1
+-------------------+----------------------------+
| Field             | Value                      |
+-------------------+----------------------------+
| availability_zone | nova                       |
| created_at        | 2018-12-08T05:49:55.000000 |
| deleted           | False                      |
| deleted_at        | None                       |
| hosts             | [u'control01']             |
| id                | 1                          |
| name              | host_aggregate_1           |
| properties        |                            |
| updated_at        | None                       |
+-------------------+----------------------------+

[root@control01 ~]# openstack resource provider list
+--------------------------------------+-----------+------------+--------------------------------------+----------------------+
| uuid                                 | name      | generation | root_provider_uuid                   | parent_provider_uuid |
+--------------------------------------+-----------+------------+--------------------------------------+----------------------+
| 5c5a578f-51b0-481c-b38c-7aaa3394e585 | control01 |         26 | 5c5a578f-51b0-481c-b38c-7aaa3394e585 | None                 |
+--------------------------------------+-----------+------------+--------------------------------------+----------------------+

[root@control01 ~]# openstack resource provider aggregate list 5c5a578f-51b0-481c-b38c-7aaa3394e585
+--------------------------------------+
| uuid                                 |
+--------------------------------------+
| 5eea7084-0207-44f0-bbeb-c759e8c766a1 |
+--------------------------------------+
  • List allocation cadidates filter by aggregates
# REQ
curl -i "http://172.18.22.222/placement/allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:5&member_of=5eea7084-0207-44f0-bbeb-c759e8c766a1" 
-X GET 
-H 'Content-type: application/json' 
-H 'Accept: application/json' 
-H 'X-Auth-Project-Id: admin' 
-H 'OpenStack-API-Version: placement 1.21' 
-H 'X-Auth-Token:gAAAAABcC12qN3GdLvjYXSSUODi7Dg9jTHUfcnF7I_ljmcffZjs3ignipGLj6iqDvDJ1gXkzGIDW6rRRNcXary-wPfgsb3nCWRIEiAS8LrReI4SYL1KfQiGW7j92b6zTz7RoSEBXACQ9z7UUVfeJ06n8WqVMBaSob4BeFIuHiVKpYCJNv7LR6cI'

# RESP
{
	"provider_summaries": {
		"5c5a578f-51b0-481c-b38c-7aaa3394e585": {
			"traits": ["HW_CPU_X86_SSE2", "HW_CPU_X86_SSE", "HW_CPU_X86_MMX", "HW_CPU_X86_SVM"],
			"resources": {
				"VCPU": {
					"used": 5,
					"capacity": 512
				},
				"MEMORY_MB": {
					"used": 3648,
					"capacity": 60670
				},
				"DISK_GB": {
					"used": 7,
					"capacity": 49
				}
			}
		}
	},
	"allocation_requests": [{
		"allocations": {
			"5c5a578f-51b0-481c-b38c-7aaa3394e585": {
				"resources": {
					"VCPU": 1,
					"MEMORY_MB": 512,
					"DISK_GB": 5
				}
			}
		}
	}]
}

Resource traits 功能测试

Resource traits 特征标签功能,用于标识 Resource Provider 的特征性质,每个 Resource Provider 有着其各自的缺省 traits,也支持为指定的 Resource Provider 自定义 traits。

Resource traits 是非常灵活的一种设计,类似于 “标签” 的作用,用户可以建立起 “标签云” 并决定为某一个 Resource Provider 贴上 “标签”,是一种资源归纳分类需求的辅助工具。

  • List traits
curl -i "http://172.18.22.222/placement/traits" 
-X GET 
-H 'Content-type: application/json' 
-H 'Accept: application/json' 
-H 'X-Auth-Project-Id: admin' 
-H 'OpenStack-API-Version: placement 1.21' 
-H 'X-Auth-Token:gAAAAABcC12qN3GdLvjYXSSUODi7Dg9jTHUfcnF7I_ljmcffZjs3ignipGLj6iqDvDJ1gXkzGIDW6rRRNcXary-wPfgsb3nCWRIEiAS8LrReI4SYL1KfQiGW7j92b6zTz7RoSEBXACQ9z7UUVfeJ06n8WqVMBaSob4BeFIuHiVKpYCJNv7LR6cI'
  • Create custom traits
curl -i "http://172.18.22.222/placement/traits/CUSTOM_FANGUIJU_HOST" 
-X PUT 
-H 'Content-type: application/json' 
-H 'Accept: application/json' 
-H 'X-Auth-Project-Id: admin' 
-H 'OpenStack-API-Version: placement 1.21' 
-H 'X-Auth-Token:gAAAAABcC12qN3GdLvjYXSSUODi7Dg9jTHUfcnF7I_ljmcffZjs3ignipGLj6iqDvDJ1gXkzGIDW6rRRNcXary-wPfgsb3nCWRIEiAS8LrReI4SYL1KfQiGW7j92b6zTz7RoSEBXACQ9z7UUVfeJ06n8WqVMBaSob4BeFIuHiVKpYCJNv7LR6cI'

NOTE:自定义 traits 建议以 CUSTOM_ 开头。

  • Update all traits for a specific resource provider
curl -i "http://172.18.22.222/placement/resource_providers/5c5a578f-51b0-481c-b38c-7aaa3394e585/traits" 
-X PUT 
-H 'Content-type: application/json' 
-H 'Accept: application/json' 
-H 'X-Auth-Project-Id: admin' 
-H 'OpenStack-API-Version: placement 1.21' 
-H 'X-Auth-Token:gAAAAABcC12qN3GdLvjYXSSUODi7Dg9jTHUfcnF7I_ljmcffZjs3ignipGLj6iqDvDJ1gXkzGIDW6rRRNcXary-wPfgsb3nCWRIEiAS8LrReI4SYL1KfQiGW7j92b6zTz7RoSEBXACQ9z7UUVfeJ06n8WqVMBaSob4BeFIuHiVKpYCJNv7LR6cI' 
-d '{"resource_provider_generation": 28, "traits": ["HW_CPU_X86_SSE2", "HW_CPU_X86_SSE", "HW_CPU_X86_MMX", "HW_CPU_X86_SVM", "CUSTOM_FANGUIJU_HOST"]}'
  • Return all traits associated with a specific resource provider
[root@control01 ~]# openstack resource provider trait list 5c5a578f-51b0-481c-b38c-7aaa3394e585
+----------------------+
| name                 |
+----------------------+
| HW_CPU_X86_SSE2      |
| HW_CPU_X86_SSE       |
| HW_CPU_X86_MMX       |
| HW_CPU_X86_SVM       |
| CUSTOM_FANGUIJU_HOST |
+----------------------+
  • List allocation cadidates filter by traits
# REQ
curl -i "http://172.18.22.222/placement/allocation_candidates?resources=VCPU:1,MEMORY_MB:512,DISK_GB:5&member_of=5eea7084-0207-44f0-bbeb-c759e8c766a1&required=CUSTOM_FANGUIJU_HOST" 
-X GET 
-H 'Content-type: application/json' 
-H 'Accept: application/json' 
-H 'X-Auth-Project-Id: admin' 
-H 'OpenStack-API-Version: placement 1.21' 
-H 'X-Auth-Token:gAAAAABcC12qN3GdLvjYXSSUODi7Dg9jTHUfcnF7I_ljmcffZjs3ignipGLj6iqDvDJ1gXkzGIDW6rRRNcXary-wPfgsb3nCWRIEiAS8LrReI4SYL1KfQiGW7j92b6zTz7RoSEBXACQ9z7UUVfeJ06n8WqVMBaSob4BeFIuHiVKpYCJNv7LR6cI'

# RESP
{
	"provider_summaries": {
		"5c5a578f-51b0-481c-b38c-7aaa3394e585": {
			"traits": ["HW_CPU_X86_SSE2", "HW_CPU_X86_SSE", "HW_CPU_X86_MMX", "HW_CPU_X86_SVM", "CUSTOM_FANGUIJU_HOST"],
			"resources": {
				"VCPU": {
					"used": 5,
					"capacity": 512
				},
				"MEMORY_MB": {
					"used": 3648,
					"capacity": 60670
				},
				"DISK_GB": {
					"used": 7,
					"capacity": 49
				}
			}
		}
	},
	"allocation_requests": [{
		"allocations": {
			"5c5a578f-51b0-481c-b38c-7aaa3394e585": {
				"resources": {
					"VCPU": 1,
					"MEMORY_MB": 512,
					"DISK_GB": 5
				}
			}
		}
	}]
}

最后

至此,对目前最新的 Placement 实现做一个概括性的介绍和分析。笔者认为 Placement 的核心价值还是在于其高度的 “灵活性” 上,可以适配用户在生产环境中的复杂多样的资源管理需求,也为云平台开发者带来了一种代码方案的可行性。如果以后能够提供 API 来支持可视化的资源管理面板,相信也会是一个不错的用户爽点。美中不足的是,笔者认为 Placement 的数据库设计似乎缺乏弹性,哪怕追加一个 metadata 字段,对开发者而言也算是只一种慰藉。

扩展阅读

《OpenStack 2018 年终盘点》