NetworkServicePOC
| |
旧设计页面
此页面曾用于帮助设计 OpenStack 之前版本的一个特性。它可能已经被实现,也可能没有。因此,此页面可能不会被更新,并且可能包含过时的信息。上次更新时间为 2013-12-12 |
- Launchpad Entry: https://code.launchpad.net/~ntt-pf-lab/nova/network-service
- Created: Hisaharu Ishii
- Contributors: Hisaharu Ishii
目录
总结
在当前的 Nova 实现中,有三种类型的网络服务:VLAN、flat 和 flat DHCP。对于 Nova 的每次部署,只能配置其中一种服务一次使用。虽然 Nova 当前的网络架构在这种设计下运行良好,但我们希望提出一种更灵活的设计,在这种设计中,这些网络服务以更模块化的方式实现,允许它们“插件”到 Nova 中。有了这种设计,它将允许第三方网络服务轻松集成到 Nova 中。
在此 POC 实现中,我们将尝试解决当前网络实现中的以下问题
- 计算服务和网络服务之间的强耦合:在当前实现中,存在相当数量的网络相关代码,这些代码存在于计算代码中。这种耦合使得用自定义服务替换现有服务变得困难。
- 网络服务在部署/应用程序级别关联:网络服务应在较小的粒度级别关联,以便在 Nova 的一次部署中,可以拥有多种类型的网络。
- 缺乏 L2 支持:由于当前可用的网络服务都是基于 L3 的网络,因此没有创建基于 L2 的网络的选项。通过使网络服务可插拔,将更容易实现和使用 L2(或任何类型)网络。
最后,应该注意的是,尽管进行了这些更改,所有当前可用的功能都应该以现在的方式工作。
原理
网络服务应以可插拔的方式实现,以便可以使用各种类型的网络服务与 Nova 一起使用。
前提条件
- 支持每个实例的多个虚拟 NIC。
- EC2 API 不支持多个 NIC。
设计
网络服务 POC 概述
可插拔的网络服务通常分为以下三个部分
- net-api:用于网络管理的 REST API。每个插件负责提供一个管理工具(就像 nova-manage 一样)来管理其网络。
- net-agent:可插拔模块,定义由计算服务调用的通用接口。这些 API 旨在在计算节点上运行。
- net-service:可插拔服务可以选择性地实现网络服务,这相当于当前 Nova 实现中的 nova-network 服务,处理各种网络任务,如 DHCP、NAT 和 IP 分配。
通过 net-api 完成网络的管理,例如创建网络、分配 IP 和虚拟 NIC。当前存在于计算代码中的所有网络相关代码都移动到 net-agent,从而将计算与网络服务分离。由于 net-service 是可选的,因此 Nova 不了解其存在。只有 net-api 和 net-agent 才能访问 net-service。例如,为了让 nova-compute 从 net-service 请求服务,它必须通过 net-agent。
Nova 网络服务插件
Nova 当前带有三种类型的网络管理器:VlanManager、 FlatManager 和FlatDHCPManager。这些在新的模型中转换为单独的插件。这些插件在“nova/networks”目录中定义为不同的模块。这些插件模块的实际路径是
- VlanManager:nova.network.vlan
- FlatManager:nova.network.flat
- FlatDHCPManager:nova.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。它们是
- 创建网络(以及网络的 IP 地址)
- URL:http://server:port/version/plugin_name/networks
- 动词:POST
- 请求参数与“nova-manage network create”命令的参数相同。
- 以状态 200 返回创建的网络 ID 列表。
- 创建虚拟 NIC
- URL:http://server:port/version/plugin_name/vnics
- 动词:POST
- 以状态 200 返回新的虚拟 NIC 的 ID。
- 删除虚拟 NIC
- URL:http://server:port/version/plugin_name/vnics/vnic_id
- 动词:DELETE
- 以状态 200 返回。
请求和响应格式由插件决定。但是,它们应支持 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_ips 和 floating_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 实现集成。
- 考虑将三个当前网络管理器合并为一个插件的可能性。
