搜 索

Openstack 部署之 Palcement(五)

  • 275阅读
  • 2021年08月30日
  • 0评论
首页 / ☁️Cloud / 正文

一、Palcement基础

1、Palcement背景

私有云的用户,尤其是传统 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(布局)。

2、项目简介

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

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

Placement API 开始了 openstack/nova repo 剥离流程,从 Placement API 蜕变为 OpenStack Placement,并在 Stein 版本中成为独立项目。Placement服务的监听端口是8778。

3、工作原理

nova-compute向placement报告资源信息。nova-scheduler在向placement询问满足一系列资源请求的节点的同时,仍然使用部分保留的filter和weight。(目前placement只替代了 nova-scheduler的CpuFilter、CoreFilter 和 DiskFilter常用的过滤器)

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。

[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
                    }
                }
            }
        }
    ],

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 消费者就是要创建的虚拟机了。

二、Palcement 配置

(1) mysql 创建数据库并授权

#登陆mysql ,如果有密码则使用 mysql -u root -p
[root@controller ~]# mysql

#创建数据库 placement
MariaDB [(none)]> CREATE DATABASE placement;

#授予权限
MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' IDENTIFIED BY 'PLACEMENT_DBPASS';

MariaDB [(none)]> MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' IDENTIFIED BY 'PLACEMENT_DBPASS';

MariaDB [(none)]> flush privileges;

#退出数据库
MariaDB [(none)]> quit

<br/>

(2) 在Keystone上创建用户,关联角色

# 创建placement用户
[root@controller ~]# openstack user create --domain default --password PLACEMENT_PASS placement
+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | default                          |
| enabled             | True                             |
| id                  | dd6e8e32bf864e9ca9f5fedf287571ca |
| name                | placement                        |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+

# 关联角色
[root@controller ~]# openstack role add --project service --user placement admin

<br/>

(3) 在Keystone上注册API

# 创建API服务
[root@controller ~]# openstack service create --name placement  --description "Placement API" placement
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | Placement API                    |
| enabled     | True                             |
| id          | 1fccd7613fd64af0988285fa0378a234 |
| name        | placement                        |
| type        | placement                        |
+-------------+----------------------------------+

# 创建endpoint
[root@controller ~]# openstack endpoint create --region RegionOne placement public http://controller:8778
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 066b909623d345908cd9123ad1141066 |
| interface    | public                           |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 1fccd7613fd64af0988285fa0378a234 |
| service_name | placement                        |
| service_type | placement                        |
| url          | http://controller:8778           |
+--------------+----------------------------------+

[root@controller ~]# openstack endpoint create --region RegionOne placement internal http://controller:8778
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | e2e9f8f703ff4c8da5819bd31f975347 |
| interface    | internal                         |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 1fccd7613fd64af0988285fa0378a234 |
| service_name | placement                        |
| service_type | placement                        |
| url          | http://controller:8778           |
+--------------+----------------------------------+

[root@controller ~]# openstack endpoint create --region RegionOne placement admin http://controller:8778
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | be55ca7fbda841449ee467fb820e4eb6 |
| interface    | admin                            |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 1fccd7613fd64af0988285fa0378a234 |
| service_name | placement                        |
| service_type | placement                        |
| url          | http://controller:8778           |
+--------------+----------------------------------+

(4) 安装placement服务

[root@controller ~]# yum install openstack-placement-api -y

(5) 修改placement配置文件

[root@controller ~]# cp /etc/placement/placement.conf /etc/placement/placement.conf.bak
[root@controller ~]# grep -Ev "^#|^$" /etc/placement/placement.conf.bak > /etc/placement/placement.conf
[root@controller ~]# vi /etc/placement/placement.conf
[DEFAULT]
[api]
auth_strategy = keystone
[cors]
[keystone_authtoken]
auth_url = http://controller:5000/v3
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = placement
password = PLACEMENT_PASS
[oslo_policy]
[placement]
[placement_database]
connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement
[profiler]

(6) 同步数据库

[root@controller ~]# su -s /bin/sh -c "placement-manage db sync" placement

(7) 修改httpd配置文件(此处为bug)

[root@controller ~]# vi /etc/httpd/conf.d/00-placement-api.conf 
#末尾添加:
<Directory /usr/bin>            #此处是bug,必须添加下面的配置来启用对placement api的访问,否则在访问apache的
<IfVersion >= 2.4>                  #api时会报403;添加在文件的最后即可
  Require all granted
</IfVersion>
<IfVersion < 2.4>                   #apache版本;允许apache访问/usr/bin目录;否则/usr/bin/placement-api将不允许被访问
  Order allow,deny
  Allow from all                        #允许apache访问
</IfVersion>
</Directory>

(8) 重启httpd服务

[root@controller ~]# systemctl restart httpd

(9) 验证

#执行状态检查
[root@controller ~]# placement-status upgrade check
+----------------------------------+
| Upgrade Check Results            |
+----------------------------------+
| Check: Missing Root Provider IDs |
| Result: Success                  |
| Details: None                    |
+----------------------------------+
| Check: Incomplete Consumers      |
| Result: Success                  |
| Details: None                    |
+----------------------------------+

三、参考文章

感谢以下文章和博主的帮助!

OpenStack Placement - 云+社区 - 腾讯云 (tencent.com)

打 赏
  • 微信
WeChatPay
评论区
暂无评论
avatar