跳转到: 导航, 搜索

NetworkServicePOC

Warning.svg 旧设计页面

此页面曾用于帮助设计 OpenStack 之前版本的一个特性。它可能已经被实现,也可能没有。因此,此页面可能不会被更新,并且可能包含过时的信息。上次更新时间为 2013-12-12

总结

在当前的 Nova 实现中,有三种类型的网络服务:VLAN、flat 和 flat DHCP。对于 Nova 的每次部署,只能配置其中一种服务一次使用。虽然 Nova 当前的网络架构在这种设计下运行良好,但我们希望提出一种更灵活的设计,在这种设计中,这些网络服务以更模块化的方式实现,允许它们“插件”到 Nova 中。有了这种设计,它将允许第三方网络服务轻松集成到 Nova 中。

在此 POC 实现中,我们将尝试解决当前网络实现中的以下问题

  1. 计算服务和网络服务之间的强耦合:在当前实现中,存在相当数量的网络相关代码,这些代码存在于计算代码中。这种耦合使得用自定义服务替换现有服务变得困难。
  2. 网络服务在部署/应用程序级别关联:网络服务应在较小的粒度级别关联,以便在 Nova 的一次部署中,可以拥有多种类型的网络。
  3. 缺乏 L2 支持:由于当前可用的网络服务都是基于 L3 的网络,因此没有创建基于 L2 的网络的选项。通过使网络服务可插拔,将更容易实现和使用 L2(或任何类型)网络。

最后,应该注意的是,尽管进行了这些更改,所有当前可用的功能都应该以现在的方式工作。

原理

网络服务应以可插拔的方式实现,以便可以使用各种类型的网络服务与 Nova 一起使用。

前提条件

  • 支持每个实例的多个虚拟 NIC。
  • EC2 API 不支持多个 NIC。

设计

网络服务 POC 概述

Openstack-network-service-apis-generic-vs-specific.png

可插拔的网络服务通常分为以下三个部分

  1. net-api:用于网络管理的 REST API。每个插件负责提供一个管理工具(就像 nova-manage 一样)来管理其网络。
  2. net-agent:可插拔模块,定义由计算服务调用的通用接口。这些 API 旨在在计算节点上运行。
  3. net-service:可插拔服务可以选择性地实现网络服务,这相当于当前 Nova 实现中的 nova-network 服务,处理各种网络任务,如 DHCP、NAT 和 IP 分配。

通过 net-api 完成网络的管理,例如创建网络、分配 IP 和虚拟 NIC。当前存在于计算代码中的所有网络相关代码都移动到 net-agent,从而将计算与网络服务分离。由于 net-service 是可选的,因此 Nova 不了解其存在。只有 net-apinet-agent 才能访问 net-service。例如,为了让 nova-computenet-service 请求服务,它必须通过 net-agent

Nova 网络服务插件

Nova 当前带有三种类型的网络管理器:VlanManager、 FlatManagerFlatDHCPManager。这些在新的模型中转换为单独的插件。这些插件在“nova/networks”目录中定义为不同的模块。这些插件模块的实际路径是

  • VlanManagernova.network.vlan
  • FlatManagernova.network.flat
  • FlatDHCPManagernova.network.flat_dhcp

OpenStack 网络概念

OpenStack 中的网络由以下主要概念组成

  • network:表示逻辑网络,但不指定它是 L3 还是 L2。
  • 虚拟 NIC (VNIC):表示连接到 VM 实例的虚拟网络接口卡。VNIC 的一个常见示例是以太网卡。
  • port:表示虚拟套接字,用于将 VNIC 插入其中以进行网络连接。端口属于特定的网络。

假设允许 VM 实例与多个 VNIC 相关联,每个 VNIC 连接到属于不同网络的端口。

项目-网络服务关联

项目与网络服务关联。项目不能与多个网络服务关联。默认情况下,每个项目都与由标志 --default_network_service 定义的网络服务关联,其中该值为插件模块的路径。如果未设置此标志,则默认值为 VLAN(nova.network.vlan)。提供了新的 nova-manage 命令来帮助管理关联。

网络服务配置文件

可用网络服务列表在网络服务配置文件中列出。此文件的位置由标志 --network_service_conf 定义。如果未定义此标志,则默认值为 /etc/nova/nova-network.conf。此文件的格式只是网络服务的 Python 模块路径列表。任何空行或以“#”开头的行都将被忽略。

示例


# Example network services
nova.network.flat
nova.network.flat_dhcp
nova.network.vlan

网络管理 REST API

所有网络管理都通过每个插件实现的 REST API 完成。在本提案中,仅适用于 OpenStack API。EC2 API 的工作方式与以前相同,但它不支持实例的多个 NIC。

每个插件都有自己的 REST API URL,其中包含路径中的插件名称。URL 的格式为:http://server:port/version/plugin_name/...

Flat、FlatDHCP 和 VLAN 定义相同的 API。它们是

请求和响应格式由插件决定。但是,它们应支持 JSON 和 XML。

这些 API 的路由由插件本身设置。实现方式如下所述。

注意:目前正在进行新的 OpenStack 计算 API(版本 1.1)的工作。保持网络 API 与新设计同步非常重要。(在撰写本文时,它尚未同步)。

数据存储

Nova 的数据库保存以下数据

  • 项目和网络服务的关联
  • 实例和虚拟 NIC 的关联

虚拟 NIC、网络和端口的实际数据都是插件特定的,因此它们属于数据存储。如果插件使用 SQL 作为其数据存储,则它有责任定义迁移脚本、数据模型和 DB API。

对于 VLAN、Flat 和 FlatDHCP,虚拟 NIC 是以太网卡,端口是固定 IP,网络与当前的 Nova 实现相同。

  • Nova 知道 Networks 和 VPorts 的存在,其中 VPorts 属于 Network。VPorts 表示用于网络连接的端口,您可以将 VNIC 插入其中。Network 是 VPorts 的一组,可以表示 L2 或 L3 网络。
  • Compute 的 API 接收要与正在创建的实例关联的 VNIC ID 列表。
  • OpenStack API 创建新实例应具有一个新定义的 API,该 API 将 VNIC 作为强制参数。如果未提供或 VNIC 无效,则应引发异常。
  • 遗留 OpenStack API 创建新实例(不接受 VNIC 作为参数),创建一个新的 VNIC 并使用此 VNIC 调用新的创建 VM API。
  • EC2 API 为要创建的每个实例创建一个新的 VNIC,并调用 Compute 的 API 来创建这些实例。
  • 在 VM 实例化期间,计算代码不会对网络节点进行任何 RPC 调用,也不会执行与网络相关的任何任务。在计算节点上执行的任何网络相关代码都定义在一个名为 Network Agent 的单独模块中。
  • 网络服务(在网络节点上运行的服务)由每个插件实现。Network Agent(也由插件实现)只能访问自己的网络服务。
  • 定义了 Network Agent 的通用 API,用于获取给定 VNIC 的 IP 地址,用于文件注入。
  • 定义了 Network Agent 的通用 API,用于生成 libvirt XML 网络接口定义,用于生成 libvirt 域 XML 文件。
  • 防火墙逻辑从 Compute 移动到 Network Agent。
  • 定义了 Network Agent 的通用 API,用于将 VNIC 绑定到 VPort(在大多数情况下,这只是分配 IP 地址)。

实现

nova-manage 脚本更改

nova_manage 脚本具有用于网络服务管理的新项目命令

  • nova-manage project network_set project_id network_service
    • 将网络服务模块路径 network_service 设置为 ID 为 project_id 的项目。如果项目已经设置了网络服务,则会覆盖它。
  • nova-manage project network_get project_id
    • 获取与 ID 为 project_id 的项目关联的网络服务。如果没有关联网络服务,则返回 None。

nova-manage 中的网络命令已过时,因为所有网络管理命令都已移动到特定于插件的管理工具脚本。

网络服务类

  • NetworkServiceManager
    • nova.network.service 中定义,NetworkServiceManager 类处理可用网络服务插件的加载,并向其他 Nova 服务提供对这些模块的访问。仅读取配置文件以加载网络服务一次,并将这些模块存储在内存中。
  • NetworkServiceRouteMap
    • NetworkServiceRouteMap 类在 nova.network.service 中定义,是一个包装 python-route map 对象的类,负责将适当的前缀添加到所有 REST API 路由。即使 API 的路由由插件本身在 OpenStack API 模块初始化时设置,但路由前缀(包括插件名称)仍然由此类设置。

数据库更改

在 Nova DB 中,添加了以下新表

ProjectNetworkServiceAssociation


+ id (PK)
+ project_id
+ network_service
+ deleted, created_at, deleted_at, ...

InstanceVirtualNicAssociation


+ id (PK)
+ instance_id(FK - instances.id)
+ virtual_nic_id
+ deleted, created_at, deleted_at, ...

在 VLAN、FlatDHCP 和 Flat 插件中,有一个 EthernetCards 表,它表示 VNIC

EthernetCards


+ id (PK)
+ mac_address
+ deleted, created_at, deleted_at, ...

此外,对于所有内置插件,networks 表都从 Nova DB 移植过来。对于 VLAN 和 FlatDHCP,fixed_ipsfloating_ips 表被复制过来。对于 Flat,fixed_ips 表被移植并重命名为 ip_addresses

插件通用 API

如前所述,每个插件由几个组件组成,其中一些组件是 Nova 所必需的。插件的实际实现由插件决定,但插件必须定义通用 API 以将这些模块/类返回给 Nova。

这些通用 API 是

  • get_os_service()
    • 返回实现 Nova 的 OpenStack/EC2 API 所需通用 API 的模块/类。
  • get_os_api_service()
    • 返回实现 Nova 的 OpenStack API 所需通用 API 的模块/类。
  • get_net_agent()
    • 返回实现 Nova 的计算所需的通用 API 的模块/类。

Net Agent 通用 API

所有 net agent API 都是通用的。

  • get_default_vnic_id():vnic_id
    • 获取插件的默认 VNIC。所有插件都必须实现此 API,因为当前 OpenStack/EC2 API 创建实例时不需要 VNIC 参数,这意味着必须在 VM 实例化时动态创建一个 VNIC。此 API 由 Compute API 类调用,并由插件的 API 模块/类从 get_api_service() 返回定义。Flat、FlatDHCP 和 VLAN 插件只需创建一个新的以太网卡。如果成功,则返回新的 VNIC ID,否则返回 None。
  • get_project_vpn_address_and_port(project_id):(vpn_ip, vpn_port)
    • 为给定的项目获取 VPN IP 地址和 VPN 端口的元组。如果服务具有任何 VPN 数据(例如 VLAN 插件),则仅适用。它用于为用户构造凭据。
  • bind_vnics_to_ports(vnic_ids)
    • 对于 vnic_id 列表,API 将它们绑定到端口(如果尚未绑定)。此绑定激活网络连接。插件确定应将这些 VNIC 插入到哪些端口。它不返回任何内容。它由 net agent 实现。
  • setup_compute_network(vnic_ids)
    • 此方法必须实现,以便在虚拟机启动时在计算节点上进行任何网络设置。
  • teardown_compute_network(vnic_ids)
    • 此方法必须实现,以便在计算主机上执行任何清理操作。当虚拟机终止时,会调用此方法。
  • requires_file_injection(vnic_id) : True/False
    • 如果与vnic_id关联的网络服务需要将网络信息注入到/etc/network/interfaces文件,则返回 True。此功能由 net agent 实现。
  • get_network_info(vnic_id) : (字典: cidr, cidr_v6, netmask, netmask_v6, gateway, gateway_v6, dhcp_server, broadcast, dns, ra_server, mac_address, ip_address, 和 address_v6)
    • 获取与 ID 为vnic_id的 VNIC 关联的网络数据。返回值是 VNIC 的网络数据字典。如果这些值不适用于该插件,则可以为 None。它定义在 net agent 中,并且需要为文件注入、Iptables 设置和 libvirt XML 创建实现。

测试/演示计划

  • 随着代码的开发,将添加单元测试。

未解决的问题

  • 诸如 DHCP 和防火墙之类的网络服务组件应可插拔且可选。
  • 需要重构防火墙逻辑。实际实现应特定于插件,因此不应像现在这样存在于 compute/libvirt 代码中。
  • 项目-网络服务关联命令应更加用户友好,并具有验证和合理性检查。
  • REST API 应检查请求中发送的项目与 URL 请求的网络服务是否匹配。
  • 使网络管理 API 遵循新计算 API(1.1)的格式。
  • 与当前正在进行的 multi-nic 实现集成。
  • 考虑将三个当前网络管理器合并为一个插件的可能性。