资源提供者 - 计算节点清单

https://blueprints.launchpad.net/nova/+spec/compute-node-inventory-newton

随着我们向使用资源提供者建模系统对系统中的所有定量资源进行通用跟踪的系统发展,我们需要过渡计算节点的对象模型和数据库模式,以便将库存信息存储在资源提供者的 inventories 表中,而不是 compute_nodes 表中。本规范概述了此过渡过程的一部分,该部分处理计算节点上资源的能力 - 库存记录。

问题描述

从长远来看,我们希望能够向系统中添加新的资源类型(请参阅 resource-classes 蓝图),并在无需进行侵入性数据库模式更改的情况下进行添加。为了过渡到这种更通用的定量资源和容量记录建模(请参阅 resource-providers 蓝图),我们必须将库存信息从其当前所在的位置过渡到资源提供者建模系统中的新的 inventories 表。

用例

作为部署者,我希望向我的系统添加新的资源类别,并且在数据库模式迁移导致任何停机时间的情况下进行添加。

提议的变更

本规范的两个主要组成部分是对底层数据库模式的对齐以及对 nova.objects.ComputeNode 对象模型所需进行的更改,以便从 inventories 表而不是 compute_nodes 表读取和写入库存/容量信息。

数据库模式对齐

为了对齐库存记录的底层数据库存储,我们建议将资源使用量和容量字段从数据库中当前的位置移动到 resource-providers 蓝图中添加的新 inventories 表中。

当前,Nova 数据库存储以下资源类别的库存记录

  • vCPU

  • compute_nodes.vcpus: 计算节点上的总物理 CPU 核心数

  • compute_nodes.vcpus_used: 分配给在所述计算节点上运行的虚拟机的 vCPU 数量

  • compute_nodes.cpu_allocation_ratio: 计算节点上 vCPU 的超卖比率

  • RAM

  • compute_nodes.memory_mb: 计算节点上总物理 RAM 容量,单位为 MB

  • compute_nodes.memory_mb_used: 分配给在所述计算节点上运行的虚拟机的 RAM 容量

  • compute_nodes.ram_allocation_ratio: 计算节点上内存的超卖比率

  • compute_nodes.free_ram_mb: 可以删除的已计算字段,因为其值可以通过查看已用容量值来确定

  • 磁盘

  • compute_nodes.local_gb: 可用于存储虚拟机临时磁盘的计算节点的磁盘存储量。虽然这被标记为“本地”磁盘存储,但当前如果临时磁盘的本地存储是共享存储,则计算节点不知道该存储在其他计算节点之间共享。请参阅 generic-resource-poolsresource-providers 蓝图,以获取解决此问题的方案

  • compute_nodes.local_gb_used: 分配给在所述计算节点上运行的虚拟机的临时磁盘的磁盘存储量。与临时磁盘的共享存储一样,此字段也存在相同的问题

  • compute_nodes.free_disk_gb: 可以删除的已计算字段,因为其值可以通过查看已用容量值来确定

  • disk_available_least: 存储本地计算节点上实际使用的磁盘总量的字段。此信息可以存储在 DISK_GB 资源类的 inventories 表中的新 max_unit 字段中

  • PCI 设备

  • pci_stats: 存储有关设备“池”(每个 product_id 和 vendor_id 组合)的摘要信息。 pci-generate-stats 蓝图使此信息变得冗余,该蓝图从主记录表 pci_devices 表生成 PCI 设备的池信息摘要视图

  • pci_devices 表存储所有单个 PCI 设备记录,包括设备的状态以及设备是否已分配给任何实例(如果有)。

  • NUMA 拓扑

  • compute_nodes.numa_topology: 序列化的 nova.objects.numa.NUMATopology 对象,该对象表示计算节点的 NUMA 拓扑以及分配给计算节点上实例的 NUMA 拓扑

resource-providers 蓝图中回顾,数据库中 inventories 表的模式如下

CREATE TABLE inventories (
    id INT UNSIGNED NOT NULL AUTOINCREMENT PRIMARY KEY,
    resource_provider_id INT UNSIGNED NOT NULL,
    resource_class_id INT UNSIGNED NOT NULL,
    total INT UNSIGNED NOT NULL,
    min_unit INT UNSIGNED NOT NULL,
    max_unit INT UNSIGNED NOT NULL,
    step_size INT UNSIGNED NOT NULL,
    allocation_ratio FLOAT NOT NULL,
    INDEX (resource_provider_id),
    INDEX (resource_class_id)
);

我们建议将上述位置的所有库存/容量字段整合到以下方式的新的 inventories 表中

请记住,所有计算节点都是资源提供者,但并非所有资源提供者都是计算节点。OpenStack 部署中没有计算节点的全局唯一标识符,我们需要资源提供者的全局唯一标识符。

1) (已在 Mitaka 中完成) 我们必须首先将新的 uuid 字段添加到 compute_nodes 表中

ALTER TABLE compute_nodes ADD COLUMN uuid VARCHAR(36) NULL;

注意

uuid 字段最初必须为 NULL,因为我们不会在模式迁移脚本中生成值。请参阅下文,了解我们在读取数据库中的没有指定 UUID 的计算节点时,按需为每个计算节点生成 UUID 的位置。

由于我们不想在 SQL 迁移脚本中执行任何数据迁移,我们需要在 nova.objects.ComputeNode 对象中执行以下数据迁移。我们建议创建一个名为 _migrate_inventory() 的方法来处理数据迁移步骤,该方法在找到某些条件存在时在 _from_db_object() 上调用(例如,计算节点没有 UUID 字段值)。 _migrate_inventory() 方法应使用单个数据库事务来确保所有 DB 写入都是原子性的,并且它应首先检查以确保所有 API 和 conductor 节点都已升级到支持迁移的版本。

2) (已在 Mitaka 中完成) 应该为没有设置 uuid 字段的计算节点生成新的随机 UUID。

3) 必须为每个计算节点在 resource_providers 表中添加一条记录

INSERT INTO resource_providers (uuid)
SELECT uuid FROM compute_nodes;

4) 我们需要为每个计算节点创建库存记录。对于计算节点提供的每个资源类别,我们需要存储容量、最小和最大单位值以及分配比率。

4a) 对于 vCPU 资源类别,我们对每个计算节点执行以下步骤。从 resource_classes 表中获取 CPU 的资源类别标识符(请参阅 resource-classes 蓝图)。

将记录插入到 inventories 表中,用于 CPU 资源类别,其中包含总数、最小值、最大值和分配比率。例如

INSERT INTO inventories (
    resource_provider_id,
    resource_class_id,
    total,
    min_unit,
    max_unit,
    allocation_ratio
)
SELECT
    rp.id,
    $CPU_RESOURCE_CLASS_ID,
    cn.vcpus,
    1,
    cn.vcpus,
    cn.cpu_allocation_ratio
FROM compute_nodes AS cn
    JOIN resource_providers rp
       ON cn.uuid = rp.uuid
WHERE cn.id = $COMPUTE_NODE_ID;

4b) 对 RAM 和 DISK 资源类别执行相同的操作。对于 DISK 资源类别,如果计算节点使用共享存储来存储临时磁盘,则不要执行 INSERT。

4c) 对于 PCI 设备资源类别(PCI_GENERICPCI_SRIOV_PFPCI_SRIOV_VF),inventories 表中的记录表示整个资源类别,而不是例如 SR-IOV 支持的 NIC PF 上的单个 VF。因此,将代表每个 PCI 资源类别的总量的单个记录添加到具有 PCI 设备的每个计算节点的 inventories 表中。

例如,假设一个计算节点具有一个 SR-IOV 支持的 NIC,支持 255 个虚拟功能 (VF),并且不暴露物理功能 (PF) 以供云用户使用。我们希望将任何单个实例可以消耗的 VF 数量限制为 8。

我们将插入以下内容到 inventories 表中

INSERT INTO inventories (
    resource_provider_id,
    resource_class_id,
    total,
    min_unit,
    max_unit,
    allocation_ratio
)
SELECT
    rp.id,
    $PCI_SRIOV_VF_RESOURCE_CLASS_ID,
    255,
    1,
    8,
    1.0
FROM compute_nodes AS cn
    JOIN resource_providers rp
       ON cn.uuid = rp.uuid
WHERE cn.id = $COMPUTE_NODE_ID;

4d) 对于 NUMA 资源类别(NUMA_SOCKETSNUMA_CORESNUMA_THREADSNUMA_MEMORY),为暴露 NUMA 拓扑资源的每个计算节点创建一个库存记录。

例如,假设我们有一个计算节点,暴露 2 个 NUMA 节点(单元),每个节点具有 4 个核心和 8 个线程。我们将 inventories 记录的 min_unit 和 max_unit 值设置为单个 NUMA 单元的约束,并将总值设置为资源的组合数。因此,例如,对于 NUMA_CORES,我们将总数设置为 8(2 个套接字,每个套接字具有 4 个核心),min_unit 设置为 1,max_unit 设置为 4(因为每个单元具有 4 个核心)。

注意

在代码合并后的下一个版本中,我们将进行后续补丁,该补丁使 UUID 列变为非空,并在 compute_nodes.uuid 列上添加唯一约束。

ComputeNode 对象模型更改

为了简化从旧式机制确定库存/容量信息的过程,我们建议以以下方式修改 nova.objects.ComputeNode 对象

1) 使用对 inventories 表的单个查询来读取现有的 vcpusmemory_mblocal_gbcpu_allocation_ratioram_allocation_ratiodisk_allocation_ratio 字段,并填充对象字段的值,以便用户不会注意到存储机制在幕后发生了变化。可以使用单个 SQL 查询来获取上述字段

SELECT
    i.resource_class_id,
    i.total,
    i.min_unit,
    i.max_unit,
    i.allocation_ratio
FROM inventories i
  JOIN resource_providers rp
  ON i.resource_provider_id = rp.id
WHERE rp.uuid = $COMPUTE_NODE_UUID;

2) 唯一写入更改到 vcpusmemory_mblocal_gbcpu_allocation_ratioram_allocation_ratio 字段的 ComputeNode 的代码位于资源跟踪器中,该资源跟踪器设置字段值并调用 save()ComputeNode 对象上。我们可以修改 save() 方法,以便将库存/容量信息的任何更改写入新的 inventories 表,而不是 compute_nodes 表。

注意

对象应更改为仅将容量信息保存到库存表,但仅当所有 conductor 和 API 节点都已升级到支持新库存模式的版本时。

备选方案

这是完全改变 Nova 中定量事物跟踪和声明方式的不可逆过程的第 3 步。

数据模型影响

此蓝图不需要其他数据库模式更改。此蓝图中的工作仅填充在 resource-providers 蓝图中创建的 inventories 表。

REST API 影响

无。

安全影响

无。

通知影响

无。

其他最终用户影响

无。

性能影响

无。

其他部署者影响

需要一个数据库模式迁移,该迁移将 uuid 列添加到 compute_nodes 表中。

开发人员影响

无。

实现

负责人

主要负责人

jaypipes

其他贡献者

cdent dansmith

工作项

本规范的实施涉及以下不同的任务

  • 创建将 uuid 列添加到 compute_nodes 表的数据库模式迁移

  • 修改 nova.objects.ComputeNode.create() 以填充计算节点的 uuid 属性,在 resource_providers 表中插入记录,并将任何库存/容量字段添加到 inventories 表中。

  • 添加一个 nova.objects.ComputeNode._migrate_inventory() 方法,以将库存/容量字段从 compute_nodes 迁移到 inventories 并填充 uuid 列值(如果为 None,则为旧的 nova-compute 守护程序将序列化的 ComputeNode 对象模型发送到更新的 conductor)。 _migrate_inventory() 方法还应在 resource_providers 表中为计算节点创建一个记录

  • 修改 nova.objects.ComputeNode 模型,以便从 inventories 表而不是 compute_nodes 表读取库存/容量信息

  • 修改 nova.objects.ComputeNode 模型,以便将更改的库存信息(总数、最小和最大单位约束以及分配比率)存储到 inventories 表而不是 compute_nodes 表,并从 inventories 表而不是 compute_nodes 表读取库存信息

依赖项

  • resource-classes 蓝图已实施

  • resource-providers 蓝图已实施

测试

对执行数据迁移本身的 ComputeNode._migrate_inventory() 方法进行完整的单元、功能和集成测试。

文档影响

仅开发人员参考文档。预计本规范的实施不会对用户产生任何影响。

参考资料

历史

修订版

发布名称

描述

Newton

引入