一、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:
1 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。
1 2 3 4 5 6 [root@control01 ~] +---+----------------------------------+--------------------------------------+----------------------------------------------+--------------------------------------------------------------+ | +---+----------------------------------+--------------------------------------+----------------------------------------------+--------------------------------------------------------------+ | 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 逻辑中也发挥着重要的作用。
1 2 3 4 5 6 7 8 9 10 11 12 { "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 及其预期分配的资源清单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 "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 的各项资源总量和使用量信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 "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 的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 消费者就是要创建的虚拟机了。
二、Palcement 配置
(1) mysql 创建数据库并授权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 登陆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
(2) 在Keystone上创建用户,关联角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@controller ~] +---------------------+----------------------------------+ | Field | Value | +---------------------+----------------------------------+ | domain_id | default | | enabled | True | | id | dd6e8e32bf864e9ca9f5fedf287571ca | | name | placement | | options | {} | | password_expires_at | None | +---------------------+----------------------------------+ [root@controller ~]
(3) 在Keystone上注册API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 # 创建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服务
1 [root@controller ~]# yum install openstack-placement-api -y
(5) 修改placement配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [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) 同步数据库
1 [root@controller ~]# su -s /bin/sh -c "placement-manage db sync" placement
(7) 修改httpd配置文件(此处为bug)
1 2 3 4 5 6 7 8 9 10 11 [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服务
1 [root@controller ~]# systemctl restart httpd
(9) 验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 执行状态检查 [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)