Port Forwarding API¶
https://blueprints.launchpad.net/neutron/+spec/port-forwarding
端口转发是网络中一种常见的特性,尤其是在 PaaS 和 SaaS 云系统中,旨在为使用不同虚拟机提供服务的不同客户端重用相同的公网 IP。
这对于缺乏大量可分配的公网 IP 的部署尤其重要。
此功能的一个常见用例是客户端请求特定服务,服务平台(PaaS、SaaS)分配虚拟机来运行该服务,然后分配客户端端口来访问该服务。这意味着不同的客户端使用相同的公网 IP,但 TCP/UDP 目标端口用于区分终端虚拟机。
例如,Web 服务器的映射
client1 172.24.4.2:4001 TCP => 映射到 10.0.0.2 端口 80 TCP (VM1)
client2 172.24.4.2:4002 TCP => 映射到 10.0.0.3 端口 80 TCP (VM2)
本规范将重点关注基于浮动 IP 的端口转发。未来将提交基于路由器外部网关接口的端口转发规范。
问题描述¶
在 IP 资源有限的环境中,运营商希望重用公网 IP,而不是为每个虚拟机分配自己的公网 IP(浮动 IP)。
Docker 支持端口映射功能,因此大量的自动化编排和管理插件利用它。我们希望使 Neutron 与这些工具和系统兼容,并提供类似的 API [1]。
提议的变更¶
为浮动 IP 引入端口转发 API 和实现。
用户可以在浮动 IP 上定义各种端口转发规则,包含内部/客户端端口和外部/目标端口,与他们想要暴露的虚拟机连接。并且用户只能在“空闲”浮动 IP 上创建端口转发规则,即未直接关联到租户虚拟机固定 IP 的浮动 IP。
我们将有四种部署变体
a) 传统路由器:对于通用的路由器部署,端口转发规则将安装在网络节点上的路由器命名空间中,并执行转发功能。
b) HA 路由器:对于 HA 路由器部署,端口转发规则将安装在位于网络节点上的 ACTIVE 和 BACKUP 路由器命名空间中。
c) DVR:由于 [2] 已合并,我们现在能够在 DVR 支持的部署中创建集中的浮动 IP。这有助于将目标虚拟机所在的计算节点与用于端口转发的集中 FIP 映射起来。这种机制不仅在浮动 IP 与绑定到启用 dvr_no_external 选项的主机上的端口关联时,而且在向其添加端口转发属性时,都会集中一个浮动 IP。
d) DVR + HA:如果创建的路由器不是 HA 路由器,则我们可以继续使用选项 (c)。如果路由器是 HA 路由器,则我们将使用集中的 HA 路由器来安装端口转发规则。
在所有部署变体中,端口转发条目 NAT 特定浮动 IP:端口和协议到特定的 Neutron 端口(以及连接到该端口的私有 IP)。这意味着它将维护类似于“FIP:extport 协议”到“Neutron Port Fixed IP:intport 协议”的映射。因此,如果 Neutron 端口包含多个固定 IP,则可以为特定的 Neutron 端口创建多个端口转发条目,使用不同的外部端口,例如
FIPX:EXTPORTX PROTOCOLA => Neutron PortQ Fixed IPA:INTPORTA PROTOCOLA (VM1)
FIPX:EXTPORTY PROTOCOLA => Neutron PortQ Fixed IPB:INTPORTA PROTOCOLA (VM1)
但是,相同的 Fixed IP:intport 套接字不能映射到不同的协议。
如果删除 Neutron 端口,则与该端口匹配的端口转发条目也会被删除。如果删除浮动 IP,则情况相同。
数据模型影响¶
作为端口转发功能的一部分,将添加以下新表
CREATE TABLE port_forwarding (
id CHAR(36) NOT NULL PRI KEY,
floating_ip_id VARCHAR(36) NOT NULL,
external_port INT NOT NULL,
internal_neutron_port_id VARCHAR(36) NOT NULL FOREIGN KEY,
protocol CHAR(4) NOT NULL,
socket VARCHAR(20) NOT NULL,
CONSTRAINT floating_ip_id_external_port_constraint UNIQUE (floating_ip_id, external_port),
CONSTRAINT internal_neutron_port_id_socket_constraint UNIQUE (
internal_neutron_port_id, socket)
);
socket 列将存储类似于“Fixed IP:Port”的字符串。
注意
此表缺少 project_id,因为此 port_forwarding 的所有者必须是关联浮动 IP 的所有者。因此,存在一个 project_id 检查,以防止将浮动 IP 与内部 Neutron 端口关联,如果它们的 project_id 不同。此外,允许关联浮动 IP/内部 Neutron 端口存在于共享网络上,供不同 project_id 情况下的管理员用户使用,例如来自共享公共网络(由管理员用户创建)的 FloatingIP 和来自特定内部租户网络(由租户用户创建)的 Neutron 端口,然后管理员用户希望关联它们,这些具有不同的 project_ids。对于普通用户,只有相同 project_id 的情况。
子资源扩展¶
Neutron floatingips 将使用子资源 port_forwarding 进行扩展,它将包含一些字段来暴露分配给 floatingip 资源的 port_forwarding。
对于此新功能,将引入一个新的服务插件,并添加以下方法
‘create_floatingip_port_forwarding()’
‘delete_floatingip_port_forwarding()’
‘get_floatingip_port_forwarding()’
‘get_floatingip_port_forwardings()’
对于更新操作,如果可能,我们将在未来扩展该函数。但目前,我们只支持创建/删除/获取功能。
因此,新子资源的属性映射如下
SUB_RESOURCE_ATTRIBUTE_MAP = {
'port_forwarding': {
'parent': {'collection_name': 'floatingips',
'member_name': 'floatingip'},
'parameters': {
'external_port': {'allow_post': True, 'allow_put': False,
'convert_to':
convert_validate_port_value,
'is_visible': True},
'internal_port': {'allow_post': True, 'allow_put': False,
'convert_to':
convert_validate_port_value,
'is_visible': True},
'internal_ip_address': {'allow_post': True,
'allow_put': False,
'validate': {
'type:ip_address_or_none': None},
'is_visible': True},
'protocol': {'allow_post': True, 'allow_put': False,
'validate': {
'type:values': constants.IPTABLES_PROTOCOL_MAP.keys()},
'is_visible': True,
'convert_to': converters.convert_to_protocol},
'internal_port_id': {'allow_post': True,
'allow_put': False,
'validate': {'type:int':None},
'is_visible': True},
}
}
}
REST API 影响¶
其想法是使用以下定义的属性扩展浮动 IP Rest API,并添加一个新的扩展 floating_ip_port_forwarding。
属性名称 |
类型 |
CRUD |
默认值 |
描述 |
port_forwardings |
列表 |
R |
无 |
与特定浮动 IP 资源关联的“port-forwarding”子资源。 |
浮动 IP 扩展定义将扩展为
RESOURCE_ATTRIBUTE_MAP = {
'floatingips': {
'port_forwardings': {'allow_post': False,
'allow_put': False,
'is_visible': True, 'default': None}
}
}
此新字段将在浮动 IP 资源的 GET/POST/PUT 请求期间公开。这意味着用户不能通过 CRU FloatingIP 更改转发资源,只能使用下面介绍的新端口转发 API 一次创建一个转发。
例如,获取浮动 IP
GET /v2.0/floatingips/<floatingip-uuid>
{
"floatingip": {
"floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
"router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
"fixed_ip_address": "",
"floating_ip_address": "172.24.4.228",
"project_id": "4969c491a3c74ee4af974e6d800c62de",
"tenant_id": "4969c491a3c74ee4af974e6d800c62de",
"status": "ACTIVE",
"port_id": "",
"id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7",
"port_forwardings": [
{
"internal_ip_address": "10.0.0.3",
"protocol": "tcp",
"internal_port": "22",
"external_port": "7001"
},
{
"internal_ip_address": "192.168.4.32",
"protocol": "tcp",
"internal_port": "22",
"external_port": "7002"
}
]
}
}
对于新的子资源“port_forwarding”,将引入一个新的 URL
/v2.0/floatingips/<floatingip-uuid>/port_forwardings
列出端口转发¶
GET /v2.0/floatingips/<floatingip-uuid>/port_forwardings
{
"port_forwardings": [
{
"id": "ae34051f-aa6c-4c75-abf5-50dc9ac99ef3",
"external_port": "7003",
"internal_port": "22",
"internal_ip_address": "10.0.0.10",
"protocol": "tcp",
"internal_port_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf"
},
{
"id": "915a14a6-867b-4af7-83d1-70efceb146f9",
"external_port": "7004",
"internal_port": "22",
"internal_ip_address": "10.0.0.11",
"protocol": "tcp",
"internal_port_id": "0c56df5d-ace5-46c8-8f4c-45fa4e334d18"
}
]
}
参数 |
风格 |
类型 |
描述 |
|---|---|---|---|
port_forwardings |
plain |
xsd:list |
一个 port_forwarding 对象列表 |
更多参数请参见 显示端口转发
显示端口转发¶
GET /v2.0/floatingips/<floatingip-uuid>/port_forwardings/<port-forwarding-id>
{
"port_forwarding": {
"id": "ae34051f-aa6c-4c75-abf5-50dc9ac99ef3",
"external_port": "7003",
"internal_port": "22",
"internal_ip_address": "10.0.0.10",
"protocol": "tcp",
"internal_port_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf"
}
}
参数 |
风格 |
类型 |
描述 |
|---|---|---|---|
port_forwarding |
plain |
xsd:dict |
一个 port_forwarding 对象 |
id |
plain |
xsd:string |
port_forwarding 对象的 ID |
external_port |
plain |
xsd:string |
暴露的外部协议端口号 |
internal_port |
plain |
xsd:string |
端口转发映射的内部协议端口号 |
internal_ip_address |
plain |
xsd:string |
来自特定端口的固定 IP 的 IP 地址 |
protocol |
plain |
xsd:string |
流量协议类型,例如 TCP 或 UDP。默认值为“TCP”。 |
internal_port_id |
plain |
xsd:string |
Neutron 内部端口 ID。 |
创建端口转发¶
POST /v2.0/floatingips/<floatingip-uuid>/port_forwardings
{
"port_forwarding": {
"external_port": "7233",
"internal_port": "22",
"internal_port_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf"
}
}
响应参数
参见 显示端口转发
{
"port_forwarding": {
"id": "f8a44de0-fc8e-45df-93c7-f79bf3b01c95",
"external_port": "7233",
"internal_port": "22",
"internal_ip_address": "192.168.43.33",
"protocol": "tcp",
"internal_port_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf"
}
}
删除端口转发¶
DELETE /v2.0/floatingips/<floatingip-uuid>/port_forwardings/<port-forwarding-id>
此操作不接受请求体,也不返回响应体。
对现有浮动 IP API 的影响¶
对现有浮动 IP API 的轻微调整
创建浮动 IP 与当前行为相同。
将 Neutron 内部端口与浮动 IP 关联,如果请求的 URL 与之前相同,则浮动 IP 将像当前的 1:1 DNAT 行为一样工作。如果请求使用新的 URL,则表示请求需要针对浮动 IP 的端口转发功能。
获取浮动 IP 资源与之前相同,如果浮动 IP 资源已经与用于 1:1 DNAT 的 neutron 端口关联。如果浮动 IP 资源包含多个端口转发子资源,最好在浮动 IP 响应主体中显示
port-forwardings摘要,以区分哪些浮动 IP 资源可用于不同的要求,例如 1:1 DNAT、端口转发。
命令行客户端影响¶
Openstack Client 将为浮动 IP CLI 增加额外的选项 portforwarding,这将定义端口转发的特性。
安全影响¶
端口转发本质上与集中式 DNAT 类似,因此不应带来额外的安全隐患。但是,如果用户实际上想使用端口转发,他们必须确保允许与虚拟机 neutron 端口使用的内部 IP 相关的传入安全组。
通知影响¶
取决于实现规范
其他最终用户影响¶
无
性能影响¶
必须进行性能测试,以查看启用此功能会产生什么开销,当然,如果禁用该功能,则不应注意到任何性能影响。
IPv6 影响¶
不支持 IPv6
其他部署者影响¶
部署者可以利用端口转发以独特的方式访问私有 VM/容器,而无需浪费新的公网 IP
开发人员影响¶
未来的 SNAT 分发计划应考虑端口转发。Kuryr 可以利用端口转发与 Docker 端口映射的兼容性。
备选方案¶
用户可以使用提供此 NAT 功能的外部 VM,或者为每个 VM 分配新的浮动 IP。
实现¶
负责人¶
- 主要负责人
reedip <reedip.banerjee@nectechnologies.in>
- 其他贡献者
gal-sagie <gal.sagie@gmail.com>
tian-mingming <tian.mingming@h3c.com>
zhaobo <zhaobo6@huawei.com>
工作项¶
API 实现
DB 实现
参考实现
测试
文档
依赖项¶
无
测试¶
Tempest 测试¶
需要添加 tempest 测试
功能测试¶
需要添加功能测试
API 测试¶
需要添加 API 测试
Fullstack 测试¶
需要添加全栈测试。
文档影响¶
用户文档¶
需要用户文档
开发人员文档¶
需要 devref 文档