获取网络

https://blueprints.launchpad.net/nova/+spec/get-me-a-network

Mitaka 版本中的 Neutron 增加了 auto-allocated-topology API [1]。Nova 计划使用此 API,在创建服务器实例时,如果创建请求中未提供特定网络,并且项目也没有可用的网络,则自动分配一个私有网络。 这也应该为 Neutron 和 nova-network 中的 VlanManager 之间的服务器创建流程带来一些功能对等性。 在两种情况下,部署者仍然需要进行一些网络设置,但此后,网络服务将自动处理为项目设置网络拓扑。

问题描述

在使用 nova-network 时,用户通常在创建简单实例时不会指定任何网络配置。 使用 Neutron 时,项目需要在 Nova 中设置实例网络之前,在 Neutron 中访问网络和子网。

此更改的目的是减少用户启动实例并能够 ssh 进入它的复杂性,而无需先在 Neutron 中设置网络/子网/路由器,然后在启动实例时指定 nic。

用例

作为最终用户,我希望在 Nova 中创建一个实例,并为我的项目自动分配网络,以便在实例激活后可以 ssh 进入该实例。

提议的变更

Nova 将添加一个微版本到 API,该版本在创建实例时需要特定的 nic 值。

当前使用 Neutron 的创建服务器请求的工作方式

当前,用户可以创建实例并使用 Neutron 作为 Nova 中的网络 API 指定以下网络值

  1. 请求特定的固定 IP。

  2. 请求特定的端口(或端口)。

  3. 请求特定的网络(或从 Juno 版本开始重复网络 [2])。

  4. 请求特定的固定 IP 和网络(Nova 将在该网络中创建一个端口并使用该固定 IP 地址)。

  5. 在创建请求中不提供任何内容。

由于端口已经关联了固定的 IP 地址,因此不能同时请求固定的 IP 和端口。 请求特定端口时,该端口所在的网络在创建请求中是隐含的。

在最后一种情况下(未请求任何内容),Nova 将尝试通过搜索来查找可用的网络:

  1. 项目的私有网络。

  2. 公共(shared=True)网络。

如果此搜索结果为多个网络,则会产生一个模糊的网络错误。

Nova 中还存在现有行为,即当用户未提供要使用的特定网络并且项目在 Neutron 中没有访问权限时,可以创建没有网络的实例。 这不是一个错误,因为稍后可以使用 os-attach-interfaces API 附加网络。

使用自动分配的创建服务器请求的工作方式

创建服务器请求中的 networks 对象现在将是一个列表或枚举,具有以下值

  1. 自动

  • 这意味着如果项目没有可用的网络,则自动分配网络给我。 对于 nova-network,这是默认行为和 VlanManager 的现有行为。 对于 Neutron,这意味着使用 auto-allocated-topology API。

  • 当指定端口 uuid 时,不能使用 ‘auto’ 值,因为端口意味着项目已经可以访问的网络。

注意

指定 ‘auto’ 表示 Nova 将尽最大努力自动分配实例的网络。 这不能保证有效,因为云操作员需要进行初始设置才能启用此功能(这与 nova-network 也是如此)。 有关详细信息,请参阅 其他部署者影响

  • 这意味着不要尝试设置网络。 计算管理器在创建服务器实例时将避免网络 API 调用。 实例所需的任何网络都必须稍后附加。

在内部,‘auto’ 或 ‘none’ 值将存储在 nova.objects.network_request.NetworkRequest.network_id 字段中。

错误条件

  • 如果请求中未指定任何内容,则返回 400 错误。

  • 指定 ‘auto’ 以及任何其他网络值(端口、‘none’、‘auto’ 或特定的网络 uuid)将导致 400 响应。

  • 指定 ‘none’ 以及任何其他网络值(端口、‘auto’ 或特定的网络 uuid)将导致 400 响应。

  • 如果指定 ‘auto’ 并且 nova-network 无法提供网络,则使实例构建请求失败(这可能会触发到另一个计算节点的重新调度)。

  • 如果指定 ‘auto’,并且 Nova 在 API 请求的生命周期内可以确定无法满足自动分配网络,则返回 400 错误。 如果自动分配在 API 请求返回后失败,则实例将发送到 ERROR 状态。

  • 另一个失败场景是,Neutron 足够新并且已设置为支持 auto-allocated-topology,但部署仍然具有未自动运行分配代码以创建网络资源的计算节点。 因此,我们必须限制在所有计算服务都运行添加该支持的版本时,才能使用新的微版本和 ‘auto’ 或 ‘none’ 网络 uuid 值。

    如果请求 ‘auto’ 或 ‘none’,但最低计算服务版本不够高,则 API 将表现为未请求网络。 这意味着

    • 将 ‘auto’ 更改为 None:如果项目有可用的网络,则实例将获得网络,这与今天的运作方式相同。 如果没有可用的网络,则实例将没有网络。

    • 将 ‘none’ 更改为 None:这基本上与上面的 None 情况相同 - 没有办法明确请求不设置任何网络。 这可能会让任何请求 ‘none’ 然后获得网络的人感到惊讶,但这被认为是一个边缘情况。 我们可以使请求失败,但由于我们要求在此微版本中为网络指定某些内容,因此用户唯一的选择是指定较低的微版本且没有网络,但他们仍然可能最终获得网络,因此效果相同。

    一旦所有计算都升级到支持计算节点自动分配的 Newton 版本,那么请求将被满足,即我们将有机会调用 Neutron 中的 auto-allocated-topology API。

计算 API 更改

计算 API 调用网络 API 来验证请求。 网络 API 验证代码需要进行更改才能处理 ‘auto’ 和 ‘none’ 网络的 uuid 情况。

对于 ‘none’,验证只是一个空操作,因为计算管理器在构建实例时不会分配网络。

对于 ‘auto’ 和 Neutron API,如果项目没有可用的网络,则验证

  • Neutron API 中是否可用 auto-allocated-topology 扩展。 请注意,auto-allocated-topology 扩展在 Neutron 中不是可选的,因此只要 Neutron 的版本足够新以具有该 API,该扩展将可用并启用。

  • 使用 dry-run 选项的 auto-allocated-topology Neutron API 通过检查是否有默认的公共外部网络和默认子网池来通过。 如果未准备好该设置,则 API 将返回 409 错误,Nova 将将其作为 400 错误返回给用户。

对于 ‘auto’ 和 nova-network,验证是一个空操作,因为我们只有在到达计算节点以构建实例并分配网络时才能知道是否会提供网络。

我们还需要检查在请求 ‘auto’ 或 ‘none’ 时,部署中的最低计算服务版本是否支持自动分配。 此检查可以在 Ocata 中删除,因为所有计算都应至少运行 Newton 代码。

网络 API 更改

传递到网络 API 的 allocate_for_instance 方法的 nova.objects.NetworkRequestList 应该包含足够的信息,以便网络 API 处理 ‘auto’ 和 ‘none’ 情况。

nova.objects.NetworkRequest.network_id 字段是一个可为空的字符串。 因此,如果 network_id 为 None,则为 Get Me a Network 之前的微版本情况。 否则,network_id 将具有特定的网络 uuid、‘auto’ 或 ‘none’,其中 ‘none’ 表示不分配网络。

NetworkRequest/NetworkRequestList 对象可能会有一些辅助方法,以便轻松确定请求是否为特殊的 ‘auto’ 或 ‘none’ 情况。

nova-network

nova-network API 的 ‘auto’ 情况是,(单条目) NetworkRequestList 中的 network_id 在通过 RPC 传递到网络管理器之前将被设置为 None。 这保持了管理器在创建实例时未请求特定网络时的现有行为。

Neutron

Neutron 的 ‘auto’ 情况意味着,如果项目没有可用的网络,则将调用 auto-allocated-topology API 来创建一个。 请注意,网络的 port-security-enabled 属性将是默认值,该值基于 ‘Port Security’ 扩展是否启用。

注意

在计算节点上自动分配 Neutron 网络时,可能会出现竞争条件,尤其是在使用单个服务器创建请求创建多个实例时。 这是一个每个项目一次性操作,因此项目首次请求自动分配的服务器创建将创建网络。 如果对同一项目进行并发请求,Neutron 基于项目 ID 在 auto_allocated_topologies 表中的唯一约束中具有回滚机制。 因此,第二个并发请求应该失败并回滚,但 API 将返回该项目已经创建的网络。 换句话说,配置调用是幂等的,并且在并发请求的情况下,第一个提交请求的请求获胜。 Nova 不需要实现任何重试机制。

备选方案

microversion 邮件列表中的线程operator 反馈线程 中讨论了两种替代方案

  1. 如果在启动时未提供任何网络信息且没有可用网络,则不提供网络(现有行为)。 如果用户希望自动分配网络,他们必须指定 --nic net-id=auto

    在这种情况下,用户必须选择自动分配网络。

  2. 如果在启动时未提供任何网络信息且没有可用网络,则 Nova 将尝试从 Neutron 自动分配网络。 如果用户明确不希望在实例创建时进行网络设置(出于任何原因),他们必须通过指定 --nic net-id=none 来选择该行为。

    这更接近于使用 nova-network 启动实例的方式,但这是 Neutron 情况下的默认行为的更改,这可能会引起任何编写工具以期望该默认行为的用户关注。

最终决定要求 API 用户在请求中明确说明他们想要的内容(auto/none/uuid)。 为了改善 CLI 的用户体验,CLI 将在未指定任何内容时默认为 ‘auto’(并且服务器支持该微版本)。

数据模型影响

REST API 影响

  • 将添加一个微版本用于创建新服务器,该版本需要指定网络的特定值。

    • 方法类型:POST

    • 正常的 http 响应代码:202

    • 预期的错误 http 响应代码:400、403

    • 资源的 URL

    • 如果允许,则请求正文数据的 JSON 模式定义

      • 服务器创建 API 模式将对 networks 对象更加严格,该对象必须是具有值 ‘auto’ 或 ‘none’ 的列表或枚举。

      'type': 'object',
      'properties': {
          'server': {
              'type': 'object',
              'properties': {
                  'name': parameter_types.name,
                  'imageRef': parameter_types.image_ref,
                  'flavorRef': parameter_types.flavor_ref,
                  'adminPass': parameter_types.admin_password,
                  'metadata': parameter_types.metadata,
                  'networks': {
                      'oneOf': [
                          {'type': 'array',
                           'items': {
                              'type': 'object',
                               'properties': {
                                  'fixed_ip': parameter_types.ip_address,
                                  'port': {
                                      'oneOf': [{'type': 'string', 'format': 'uuid'},
                                                {'type': 'null'}]
                                  },
                                  'uuid': {'type': 'string', 'format': 'uuid'},
                              },
                              'additionalProperties': False,
                          },
                         },
                         {'type': 'string', 'enum': ['none', 'auto']},
                      ]
                  }
              },
              'required': ['name', 'flavorRef', 'networks'],
              'additionalProperties': False,
          },
      },
      'required': ['server'],
      'additionalProperties': False,
      

      注意

      由于原始 Neutron v1 API 中存在一些遗留行为,该行为未强制网络 ID 必须是 uuid,并且允许带有 br- 前缀的 ID,因此请求的网络 uuid 当前不需要是严格的 uuid。 随着提出的模式更改,请求的网络 uuid 必须是严格的 uuid 值,将不再支持 br- 前缀,如果指定该前缀,将导致错误。

    • 如果有,则响应正文数据的 JSON 模式定义

      • 这与服务器创建 API 今天的运作方式没有变化。

示例

  • 使用特定的网络 uuid 启动服务器

REQ: curl -g -i -X POST \
http://localhost:8774/v2.1/812d057b80bf42fdb7db62d68f3c6983/servers \
-H "User-Agent: python-novaclient" -H "Content-Type: application/json" \
-H "Accept: application/json" -H "X-OpenStack-Nova-API-Version: 2.26" \
-H "X-Auth-Token: {SHA1}0ecb2c6e137a5bd778b5561fd9dc48a0919f85a5" \
-d '{"server": {"name": "net-uuid-test", \
"imageRef": "883db132-0312-411c-b546-5cad477864c6", "flavorRef": "1", \
"max_count": 1, "min_count": 1, \
"networks": [{"uuid": "c92eed77-c1c0-498f-8729-c0f4c21796e5"}]}}'
  • 使用 ‘auto’ 网络 ID 启动服务器

REQ: curl -g -i -X POST \
http://localhost:8774/v2.1/812d057b80bf42fdb7db62d68f3c6983/servers \
-H "User-Agent: python-novaclient" -H "Content-Type: application/json" \
-H "Accept: application/json" -H "X-OpenStack-Nova-API-Version: 2.26" \
-H "X-Auth-Token: {SHA1}0ecb2c6e137a5bd778b5561fd9dc48a0919f85a5" \
-d '{"server": {"name": "net-auto-test", \
"imageRef": "883db132-0312-411c-b546-5cad477864c6", "flavorRef": "1", \
"max_count": 1, "min_count": 1, "networks": "auto"}}'
  • 使用 ‘none’ 网络启动服务器。

REQ: curl -g -i -X POST \
http://localhost:8774/v2.1/812d057b80bf42fdb7db62d68f3c6983/servers \
-H "User-Agent: python-novaclient" -H "Content-Type: application/json" \
-H "Accept: application/json" -H "X-OpenStack-Nova-API-Version: 2.26" \
-H "X-Auth-Token: {SHA1}0ecb2c6e137a5bd778b5561fd9dc48a0919f85a5" \
-d '{"server": {"name": "net-none-test", \
"imageRef": "883db132-0312-411c-b546-5cad477864c6", "flavorRef": "1", \
"max_count": 1, "min_count": 1, "networks": "none"}}'

安全影响

无;用户以前无法执行任何新操作,这只是在幕后添加了一些方便的编排,因此用户无需在创建 Nova 中的服务器实例之前设置 Neutron 中的网络。

通知影响

其他最终用户影响

Nova REST API 将要求指定 networks 值。

然而,如果 boot 命令中没有请求任何网卡,并且服务器支持新的微版本(且用户没有指定较低的微版本),则 CLI 将默认设置为“auto”。

性能影响

每次 Nova 调用 Neutron 时都会产生额外的开销。在指定“auto”且项目没有可用的现有网络的情况下,计算 API 中将进行两次额外的网络请求验证检查。

  1. auto-allocated-topology 扩展可用。扩展已经在 nova.network.neutronv2.api.API 中缓存,因此开销应该很小。

  2. auto-allocated-topology API 通过了 *dry-run* 验证检查。对于租户而言,这只是一次性成本,因为第一次 Neutron 为租户自动分配网络后,后续检查可用网络会找到先前分配的网络,我们无需再次检查 auto-allocated-topology API,除非租户网络已被删除。

注意

Nova 可以通过使用类似 oslo.cache 的缓存来抵消使用 Neutron 进行此验证的成本,并设置过期时间(例如,每小时重新验证一次)。在这种情况下,“Positive”结果意味着仅缓存验证通过的结果,这样我们就不会遇到验证失败、管理员修复问题、然后下一个请求在缓存结果上失败(即使事情应该通过)的情况(然后用户必须等待缓存值过期)。

其他部署者影响

为了使自动网络分配与 Neutron 协同工作,必须发生以下情况

  • Neutron API 中必须启用 auto-allocated-topology 扩展。

  • 确保公共外部网络是默认外部网络。

  • 部署必须包含默认子网池:一个 ipv4 池,或一个 ipv6 池,或两者都有。为此需要 subnet_allocation 扩展。

有关更多详细信息,请参阅 Networking Guide

还有一个 devstack 更改可以启用此功能,可以用作参考。 [3]

开发人员影响

实现

负责人

主要负责人

Matt Riedemann (mriedem)

其他贡献者

工作项

  • Nova 中微版本和 auto/none/uuid 逻辑的 REST API 更改。

  • API 更改,以检查部署中的最小计算服务版本是否至少是添加到计算服务(包括网络 API)的自动分配逻辑的版本。此检查可以在 Ocata 中删除。

  • 计算 API 中的更新,以便在 NetworkRequest.network_id == ‘none’ 时不调用 network_api.validate_networks。

  • 更新 nova.network.neutronv2.api.API.validate_networks 方法,用于“auto”情况,即没有请求任何网络且没有可用的网络。还可能缓存与 Neutron 验证的结果。

  • 更新计算管理器,以便在 network_id 为“none”时不要调用 allocate_for_instance。在计算管理器中的一个位置执行此操作比在每个网络 API 中的 allocate_for_instance 方法中执行此操作更简单,尤其是在我们必须在 nova-network 的情况下转换为网络管理器时。

  • 更新 nova.network.api.API.allocate_for_instance,如果未分配任何网络信息且 NetworkRequest.network_id == ‘auto’,则失败。

  • 更新 nova.network.neutronv2.api.API.allocate_for_instance,如果未指定任何网络且项目没有可用的网络,则自动分配网络。

  • 更新 python-novaclient 以处理新的微版本,如果未请求任何网卡并且将满足微版本,则默认将“auto”传递给 Nova REST API。

  • 所有更改的单元测试。

  • REST API 微版本更改的功能测试。

  • Tempest 测试,用于 Nova / Neutron 的完整端到端场景。

Nova 的更改将按以下顺序进行,以便我们可以使用 Tempest 的更改测试分支的 HEAD。

  1. 网络 API 更改。

  2. 计算 API/管理器更改。

  3. REST API 更改。这是 Tempest 更改所依赖的。如果此更改无法通过测试,则更改堆栈中存在问题,在 REST API 更改通过测试之前,我们无法着陆任何更改。

依赖项

  • get-me-a-network 规范中定义的 Neutron API 更改。 [1] 这在 Mitaka 中实现。

  • 用于 Tempest 测试的 Devstack 更改。 [3] 这在 Mitaka 中实现。

  • 用于 auto-allocated-topology 的 python-neutronclient python API 更改。 [4] 这在 Mitaka 中实现,并且可在 python-neutronclient 的 4.1.0 版本中使用。

测试

单元测试

针对所有内容和所有内容的单元测试。

Nova 中的功能测试

将添加针对 WSGI / 微版本更改和负面场景的测试。

负面测试包括

  • 指定“auto”或“none”以及特定的 network_id/fixed_ip/port-uuid。

  • 在微版本之后不指定任何网络。

  • 在微版本之前指定“auto”或“none”(v2.1)。

Tempest 测试

  • 微版本测试,在微版本之后使用“auto”值。

  • 使用“auto”和“none”进行 nova-network 和 Neutron 测试。

    • nova-network + auto:应该像今天在 gate 中那样工作

    • nova-network + none:验证没有分配任何网络(这也可以使用 Nova 中的功能测试进行测试,但无论使用哪个网络服务,它都应该以相同的方式工作,因此在 Tempest 中也可以很好)。

    • neutron + auto:应该在启动实例时为项目分配网络。只有在 Neutron 中启用了 auto-allocated-topology 扩展时才能工作。它还需要默认公共网络和子网池设置,因此这需要在 Tempest 中使用功能切换(devstack 已经启用了此功能,因此它将在 gate 作业中工作)。

      • 还应该测试使用相同的项目使用“auto”启动第二个实例不会自动分配新的唯一网络,而应该重用第一次请求的相同网络。

      • 我们还应该测试使用“auto”从同一项目启动多个实例,并确保它是原子的。

文档影响

参考资料

历史

修订历史

发布名称

描述

Newton

引入

Newton

为 auto/none 作为枚举设计变更进行了修订。