浮动IP端口转发以支持端口范围¶
https://blueprints.launchpad.net/neutron/+spec/floatingips-portforwarding-ranges
在NAT中使用端口范围可以简化规则创建过程,因为它用一个条目代替了iptables中的许多条目。此外,一些用户在请求具有一些端口暴露到互联网的虚拟机时,更喜欢请求暴露一个端口范围,以避免针对网络配置向操作员提出许多请求。因此,他们通常会请求一部分外部端口来部署他们的应用程序,以便他们能够在不联系任何人或在OpenStack中配置的情况下,随时选择和更改他们想要的端口。
此外,FTP、视频会议系统、流媒体等应用程序使用多个端口(顺序端口)。
因此,在一个配置中启用所有这些(请求/需要的端口范围)会更容易。
问题描述¶
目前,如果用户想要创建涵盖多个端口的NAT规则,他/她需要逐个创建它们,在某些用例中这很繁琐。
通过iptables [1](和其他网络系统/应用程序)配置NAT时,操作员可以在配置规则时使用端口范围;因此,网络工程师在他们的NAT配置中使用端口范围是很自然的。
提议的变更¶
更改浮动IP端口转发API,以允许使用端口范围来创建NAT规则。更改如下所示。今天,当用户创建端口转发规则时,他/她通过API或CLI创建一个规则,并发送一个JSON,例如
{
"port_forwarding": {
"protocol": "tcp",
"internal_ip_address": "172.16.0.7",
"internal_port": 80,
"internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
"external_port": 8080,
"description": "desc"
}
}
外部/内部端口是整数,如果用户希望在浮动IP上为许多端口创建端口转发,他/她需要多次发送此JSON以适应他/她想要的端口数量。
建议更改API/CLI以接受外部/内部端口范围中的字符串。这将允许用户使用端口范围创建规则(而不是执行多次调用)。因此,用户不再需要创建100条规则来在他们的虚拟机上实现100个端口转发,他/她可以只发送一个JSON,例如
{
"port_forwarding": {
"protocol": "tcp",
"internal_ip_address": "172.16.0.7",
"internal_port_range": "8000:8100",
"internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
"external_port_range": "9000:9100",
"description": "desc"
}
}
API仍然会接受 internal_port 和 external_port 属性,以保持向后兼容性。
新的预期响应将是一个JSON,例如
{
"port_forwarding": {
"protocol": "tcp",
"internal_ip_address": "172.16.0.7",
"internal_port_range": "8000:8100",
"internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
"external_port_range": "9000:9100",
"description": "desc",
"id": "825ade3c-9760-4880-8080-8fc2dbab9acc"
}
}
将创建新的验证,以避免用户输入端口中的无效范围。以下是系统执行的所有验证的摘要
只允许N(外部端口[s])到N(内部端口[s])或N(外部端口[s])到1(内部端口)。因此,所有其他组合(1:N、N:M、M:N)都不允许,并且会生成错误。
在定义端口范围时,该范围内的端口不能被同一浮动IP和协议的任何其他端口转发规则使用。
有效的端口是1到65535之间的数字。所有其他情况都将生成错误。即使“0”是一个有效的端口,我们也不会允许使用它,因为它已被保留。
定义端口范围的符号如下:<port_range_begin>[:<port_range_end>];任何不符合此定义的都会生成错误。
在进行请求时,用户可以选择发送带有
internal_port_range(字符串)或internal_port(整数)的JSON,对于外部端口也是如此,同时发送internal_port_range和internal_port将引发验证错误。
数据模型影响¶
今天,port_forwarding表模式如下
id |
floatingip_id |
external_port |
internal_neutron_port_id |
protocol |
socket |
|---|---|---|---|---|---|
A1 |
C2 |
80 |
A2 |
tcp |
172.16.0.7:8080 |
B1 |
C2 |
81 |
B2 |
tcp |
172.16.0.7:8081 |
为了使port_forwarding表更像PortForwarding对象和JSON,port_forwarding表将被更新,将socket列拆分为三个新列(internal_ip_address、internal_port_start、internal_port_end),此外,external_port列将被拆分为两个新列(external_port_start和external_port_end)。新的表如下所示
id |
floatingip_id |
external_port |
external_port_start |
external_port_end |
internal_neutron_port_id |
protocol |
internal_ip_address |
internal_port_start |
internal_port_end |
socket |
|---|---|---|---|---|---|---|---|---|---|---|
A1 |
C2 |
80 |
80 |
80 |
A2 |
tcp |
172.16.0.7 |
8080 |
8080 |
172.16.0.7:8080 |
B1 |
C2 |
81 |
81 |
81 |
B2 |
tcp |
172.16.0.7 |
8081 |
8081 |
172.16.0.7:8081 |
遗留数据迁移将通过 alembic 迁移升级脚本完成。
我们有5个步骤来进行数据迁移
创建
internal_ip_address、internal_port_start、external_port_start、internal_port_end、external_port_end列,值为NULL;为表中的每个条目选择id、socket和external_port列;
对于每个条目,通过‘:’分割socket值,并将结果放入新的
internal_ip_address和internal_port_start列中,与socket相同的id。将internal_port_start列的值迁移到internal_port_end列,并将external_port列的值迁移到external_port_start和external_port_end列;将socket列更改为nullable;
将external_port列更改为nullable;
子资源扩展¶
它将被创建为一个扩展,覆盖参数(external_port和internal_port),以便也接受其验证中的端口范围。新的子资源的属性映射如下
SUB_RESOURCE_ATTRIBUTE_MAP = {
'port_forwarding': {
'parameters': {
'external_port_range': {
'allow_post': True, 'allow_put': True,
'validate': {'type:port_range': None},
'is_visible': True,
'is_sort_key': True,
'is_filter': True},
'internal_port_range': {
'allow_post': True, 'allow_put': True,
'validate': {'type:port_range': None},
'is_visible': True},
}
}
}
REST API 影响¶
无。
实现¶
负责人¶
主要负责人
Pedro <phpm13@gmail.com>
Rafael <rafael@apache.org>
其他贡献者
工作项¶
API扩展(neutron-lib)
DB扩展/数据迁移(neutron)
扩展Neutron API,为端口范围添加新的验证(neutron)
扩展l3代理,将范围应用于iptable规则(neutron)
扩展
floating ip port forwarding命令,以接受和验证CLI中的范围(python-openstackclient)将PortForwarding对象中的端口类型从int更改为string(openstacksdk)
测试
文档
未来版本中完成¶
1) 删除neutron数据库的port_forwarding表中的“socket”和“external_port”列,因为这些列在wallaby版本之后不再使用。
依赖项¶
无