节点本地虚拟 IP 地址 (本地 IP)

RFE: https://bugs.launchpad.net/neutron/+bug/1930200

本文档提出了一种新型的共享虚拟 IP 地址,可用于访问云中运行的分布式和/或多节点服务和应用程序。该功能主要侧重于非常大规模云和/或具有高网络吞吐量需求云的网络数据平面的高效率和性能。

问题描述

在多个工作负载通过网络访问共享资源的拓扑中,明显的瓶颈是网络和共享资源本身(或负载均衡器)。

../../_images/node-local-ip-problem.png

建议的功能通过部署共享服务的本地副本/缓存并透明地将本地工作负载的请求重新翻译到这些副本来解决此瓶颈问题。 通过将与主共享资源相同的 IP 地址分配给本地副本来实现透明性。

../../_images/node-local-ip-solution.png

此功能的主要用例在 RFE 描述中列出。 尽管所提出的虚拟 IP 可以单独用于简单的用例,但它主要旨在作为基本构建块,应与其他服务结合使用,以提供功能齐全的服务发现、负载平衡、代理和其他高级功能。

提议的变更

添加一个新的节点本地 IP(或简称本地 IP)资源 - 可以在多个端口/VM 之间共享的虚拟 IP(类似于 anycast IP),并且保证只能在同一物理服务器/节点边界内可达。 该机制类似于浮动 IP,区别在于本地 IP 可以同时分配给多个固定 IP(在不同节点上),并且所有地址转换都在节点的集成桥接器上尽早/本地进行。

此功能的范围限制在

  • API 和 CLI,以提供对本地 IP 地址分配和分配的精细控制

  • 网络数据平面机制,以有效地将流量重定向到同一物理节点内的端口(如果存在)或选择性地转发到备用目标

  • 本地 IP 只能在同一 L2 范围内访问

本地 IP 对象将由以下对象和属性组成

  • 表示本地 IP 的底层 Neutron 端口

  • 当数据包源端口位于同一物理节点上时,将作为数据包目标的一组关联的 Neutron 端口

  • 本地端口的 IP 模式

    • ‘translate’(默认)- 本地 IP 将对重定向的数据包表现为 DNAT

    • ‘passthrough’ - 数据包将在不修改 IP 标头的情况下被重定向;目标 VM 的客户操作系统将负责在相应的端口接口上配置本地 IP 的 IP 地址。 这类似于当前允许的地址对机制,但具有对 IP 分配和分配的精细控制的优点

  • 回退策略

    • ‘forward’(默认)- 如果物理节点上没有分配了本地 IP 的端口可用,则将数据包重定向到基础 Neutron 端口 IP 地址

    • ‘drop’ - 如果物理节点上没有分配了本地 IP 的端口可用,则数据包将被丢弃 - 目前超出范围

    • ‘reject’ - 类似于 iptables 的 ‘reject’ 策略,以帮助客户端在物理节点上没有分配了本地 IP 的端口可用时快速失败 - 目前超出范围

REST API 影响

新的本地 IP API 资源

属性

类型

必需

CRUD

描述

id

uuid-str

R

本地 IP 对象的唯一标识符。

name

字符串

CRU

本地 IP 的人类可读名称(255 个字符限制)。不必唯一。

description

字符串

CRU

本地 IP 的人类可读描述(255 个字符限制)。

project_id

uuid-str

CR

本地 IP 的所有者。

local_ip

字符串

CR

本地 IP CIDR(虚拟),将在同一物理服务器/节点内可达。 当提供的 local_port_id 的端口具有多个固定 IP 时,需要此 CIDR。

local_port_id

uuid-str

CR

由本地 IP 对象用于获取实际 IP 地址以进行本地转换的基础(备份)Neutron 端口 ID。 如果端口有多个固定 IP - 应该提供 local_ip。

network_id

uuid-str

CR

从中分配本地 IP 底层 Neutron 端口的网络 ID。 在创建时未提供 local_port_id 时需要此 ID。

ip_mode

字符串

CRU

上述 ‘translate’(用于 DNAT)或 ‘passthrough’(无 NAT)模式之一。 默认值:‘translate’


新的本地 IP 关联 API 资源

属性

类型

必需

CRUD

描述

local_ip_id

uuid-str

CR

本地 IP ID

fixed_port_id

uuid-str

CR

关联的 Neutron 固定端口的 ID

fixed_ip

字符串

CR

与本地 IP 关联的端口的精确固定 IP 地址

host

列表

R

关联端口绑定的主机


基本上,新的 API 将类似于现有的浮动 IP API,但有一些区别

  • 本地 IP 可以同时与多个固定端口关联。

  • 可以通过提供现有 Neutron 端口来创建本地 IP,该端口将用于获取 IP 地址并可以作为回退目标

  • 在没有显式指定端口的情况下创建本地 IP 将触发底层 Neutron 端口的创建,以处理 IPAM、网络边界和权限检查。 在这种情况下,创建时应指定网络 ID

  • 只要与该端口关联的本地 IP 存在,Neutron 服务器将禁止删除本地 IP 的底层回退端口

  • 父本地 IP 将忽略手动进行的底层 Neutron 端口更新(类似于当前的浮动 IP 行为)

  • 如果本地 IP 具有关联的本地端口,则应禁止删除本地 IP;可以提供 ‘force’ 选项以触发删除时的本地端口分离;删除本地 IP 还应删除表示本地 IP 的底层 Neutron 端口(如果该端口是专门为本地 IP 创建的并且之前不存在)

  • IPAM 和 IP 验证将由底层端口自动处理

  • 本地 IP 在用户/管理员访问权限方面将类似于端口和浮动 IP API

  • 本地 IP 可能具有类似于浮动 IP API 的配额(目前超出范围)

数据模型影响

以下是上述 REST API 的后端数据库表。


本地 IP

属性

类型

必需

描述

id (PK)

uuid-str

本地 IP 对象的唯一标识符。

name

string

本地 IP 的人类可读名称(255 个字符限制)。不必唯一。

project_id

uuid-str

本地 IP 的所有者。 只有管理员用户才能指定与其自身不同的项目标识符。

local_ip

string

本地 IP CIDR(虚拟),将在同一物理服务器/节点内可达。

local_port_id (FK)

uuid-str

由本地 IP 对象用于获取实际 IP 地址以进行本地 NAT 的底层(备份)Neutron 端口 ID

ip_mode

string

上述 ‘translate’(用于 DNAT)或 ‘passthrough’(无 NAT)模式之一。 默认值:‘translate’


本地 IP 关联

属性

类型

必需

描述

local_ip_id (PK)

uuid-str

本地 IP 的 UUID

fixed_port_id (PK)

uuid-str

将在此端口的主机上提供本地 IP 请求的端口的 UUID

fixed_ip

字符串

与本地 IP 关联的端口的精确固定 IP 地址

客户端影响

  • 用于创建、更新、删除、列出和显示本地 IP 以及关联/取消关联固定 IP 端口的新 CLI 和 OpenStack 客户端命令

OVS、ML2 驱动程序影响

服务器和 OVS 代理之间的 RPC 接口将被更新,以包含有关与代理的端口关联的本地 IP 的信息。 服务器将使用此信息更新 port_details。

OVS 代理将根据本地 IP 信息执行以下流更新

  • 更新关联端口的 ARP 欺骗流(如对允许的地址对所做的那样)

  • 识别关联端口的网络/本地 VLAN

  • 对于此网络中的每个端口 - 将来自表 0 或 24(ARP_SPOOF)/25(MAC_SPOOF) 的数据包重定向到新表 - 50 (LOCAL_EGRESS)

以下流示例是固定端口(id=56fbc1e7-2c.., MAC=fa:16:3e:9a:1a:de, IP=10.0.0.51)与本地 IP 10.0.0.10 关联的情况

table=25, n_packets=0, n_bytes=0, priority=2,in_port="tap56fbc1e7-2c",
dl_src=fa:16:3e:9a:1a:de actions=resubmit(,50)
  • 表 50(LOCAL_EGRESS) 用于记住本地 VLAN,以便以后区分本地 IP 流量与不同网络并进一步将数据包重定向到表 51(LOCAL_IP_HANDLE)

table=50, n_packets=0, n_bytes=0, priority=9,in_port="tap56fbc1e7-2c"
actions=load:0x4->NXM_NX_REG6[],resubmit(,51)
  • 表 51(LOCAL_IP_HANDLE) 具有用于本地 IP 处理的实际流

    • ARP 响应器流,用于处理来自同一子网端口的本地 IP ARP 请求(固定端口和与它关联的本地 IP 来自相同的 IP 子网)

      table=51, n_packets=0, n_bytes=0, priority=1,arp,reg6=0x4,
      arp_tpa=10.0.0.10
      actions=load:0x2->NXM_OF_ARP_OP[],
      move:NXM_NX_ARP_SHA[]->NXM_NX_ARP_THA[],
      move:NXM_OF_ARP_SPA[]->NXM_OF_ARP_TPA[],
      load:0xfa163e9a1ade->NXM_NX_ARP_SHA[],
      load:0x1010102->NXM_OF_ARP_SPA[],
      move:NXM_OF_ETH_SRC[]->NXM_OF_ETH_DST[],
      mod_dl_src:fa:16:3e:9a:1a:de,IN_PORT
      
    • NAT 流,用于执行实际的本地 IP 地址转换

      table=51, n_packets=0, n_bytes=0, priority=10,ip,reg6=0x4,
      nw_dst=10.0.0.10
      actions=ct(commit,table=60,zone=4,nat(dst=10.0.0.51))
      
      table=51, n_packets=0, n_bytes=0, priority=10,ct_state=-trk,ip,reg6=0x4,
      dl_src=fa:16:3e:9a:1a:de,nw_src=10.0.0.51 actions=ct(table=60,zone=4,nat)
      

      转换后,数据包将重新提交到 TRANSIENT_TABLE (60)

      或者可以使用静态 NAT 来避免内核 conntrack:学习带有 7 元组(src_mac、dest_mac、src_ip、dest_ip、protocol、src_protocol_port、dest_protocol_port)的反向流

      table=51, priority=30,tcp,dl_vlan=1,dl_dst=fa:16:3e:9a:1a:de,
      dl_src=fa:16:3e:4f:26:fd,nw_src=10.0.0.100,nw_dst=10.0.0.10,
      tp_dst=0x8000/0x8000
      actions=learn(table=62,idle_timeout=30,hard_timeout=1800,priority=90,
      eth_type=0x800,nw_proto=6,NXM_OF_ETH_SRC[]=NXM_OF_ETH_DST[],
      NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],NXM_OF_IP_SRC[]=NXM_OF_IP_DST[],
      NXM_OF_IP_DST[]=NXM_OF_IP_SRC[],NXM_OF_TCP_DST[]=NXM_OF_TCP_SRC[],
      NXM_OF_TCP_SRC[]=NXM_OF_TCP_DST[],NXM_OF_VLAN_TCI[0..11],
      load:NXM_NX_REG0[0..11]->NXM_OF_VLAN_TCI[0..11],
      output:NXM_OF_IN_PORT[]),set_field:10.0.0.10->ip_dst,goto_table:60
      

      这在 OVS 卸载的情况下可用(例如,SmartNIC)。 这将在 ovs 代理端可配置。

    • 未匹配(与本地 IP 无关)的数据包将进一步传输

      table=51, n_packets=0, n_bytes=0, priority=0 actions=resubmit(,60)
      

数据包处理示例

VM1 <10.0.0.100> tries to access Local IP 10.0.0.10
Local IP is assigned to port with MAC_2/10.0.0.51:

ARP:
VM1 -> ARP -> 10.0.0.10 and response <10.0.0.10 has MAC_2>

Egress:
<VM1_MAC_1 + 10.0.0.100> to <MAC_2 + 10.0.0.10>
<<ct NAT>>
<VM1_MAC_1 + 10.0.0.100> to <MAC_2 + 10.0.0.51>

Ingress (back):
<MAC_2 + 10.0.0.51> to <VM1_MAC_1 + 10.0.0.100>
<<ct NAT>>
<MAC_2 + 10.0.0.10> to <VM1_MAC_1 + 10.0.0.100>

调度

本地 IP 不会影响 VM 调度/放置。 本地 IP 的假设是,在任何给定时间,云中的任何物理节点都不应有一个以上的活动端口/VM 与给定的本地 IP 关联。 用户负责利用 OpenStack 放置/调度功能(例如,反亲和性规则)以避免将来自同一物理节点的多个端口分配给相同的本地 IP。

但是,可能存在有效的场景,多个本地 IP 的本地端口可能位于同一物理节点上(例如,由于其他节点维护期间的临时实时迁移)。 本地 IP 应提供一种确定性方法来处理这种情况(例如,在多个本地端口的情况下,应仅使用最旧的端口)。

初始版本限制

  • 仅支持 IPv4。 IPv6 支持将在未来的版本中考虑

  • 只有 ‘openvswitch’ ML2 机制驱动程序将支持该功能

  • 仅支持隧道(VxLAN、GRE)网络。 如果需要最小开销,将考虑 ‘vlan’

  • 如果节点包含来自同一 L2 分段的与相同本地 IP 关联的多个本地端口,则没有确定性处理

  • 没有 ‘reject’ 和 ‘drop’ 回退策略;仅支持 ‘forward’

参考资料