ovn address_set 和 port_group 的关系

31 阅读5分钟

详细分析 ovn nb db port_group 和 address_set 是否有什么绑定关系, address_set 是否可以配合策略路由独立使用,,也就是说只创建 address_set 不使用 port_group

下面把 OVN 中 Port_GroupAddress_Set 的关系、语义差异、能否单独使用,以及在策略路由(routing-policy / PBR)中的可用性做一个详细、技术向的汇总与建议 —— 并给出常用命令/匹配写法示例与注意事项。


结论速览

  1. Address_Set 是可以独立使用的 —— 它是 NB(Northbound)表的一等对象,可以直接创建并在 ACL / routing-policy 的 match 表达式里引用,用于基于 IP/ETH 的匹配(因此可以只创建 Address_Set 而不建 Port_Group)。(ovn.org)
  2. Port_Group 与 Address_Set 语义不同且互补 —— Port_Group 是“逻辑端口的命名集合”(方便用 inport/outport 匹配);Port_Group 会被 ovn-northd/ovn-controller 转换成(或在 SB 中生成)对应的 Address_Set(以 <PortGroup>_ip4 / _ip6 等命名),因此 Port_Group 提供“按端口分组”的便利,Address_Set 提供“按地址集合”的便利。(Dash Dash)
  3. Routing policies(Logical_Router_Policy)使用的 match 表达式与 ACL 共享相同的表达语言,因此 routing-policy 可以引用 Address_Set(用于 PBR 的 match 条件),实践中已有使用实例(match 中出现 ip4.src == $a... / ip4.src == $setname)。(ovn.org)

详细解释与证据

1) Address_Set 的职责与使用方式

  • NB 的 Address_Set 表是“命名的一组地址(以太网地址 / IPv4 / IPv6 / CIDR)”,其目的就是在 ACL 或其他 match 表达式中复用一组地址定义,避免把一大堆地址直接写到每条 rule 里。你可用 ovn-nbctl create Address_Set name=set1 addresses=10.0.0.5,10.0.0.25 之类创建。(ovn.org)

  • 在 match 表达式里可引用 address set。文档和 patch 中给出两种常见写法/表现形式:

    • 高层面写法(更直观):ip4.src == $set1
    • 另外有 $setname / $a<hex> 之类的变量形式出现在生成的/翻译后的匹配(ovn-northd 会把 Address_Set 翻译、或生成内部变量名),例如 ip4.src == $a6757214... 在一些 routing-policy/acl 实例里可以看到(这是 ovn-northd/ovn-sb 的内部变量引用)。两者在实践中都能看到,使用 address_set(name) 在 nb 层写入更直观,ovn 会在下游转换为内部表示。(oVirt)

注意单个 Address_Set 必须只包含同一类型的地址

  • 只能全是 IPv4
  • 只能全是 IPv6、
  • 只能全是以太网地址

这是数据库约束。(Debian Manpages)


2) Port_Group 的职责与它与 Address_Set 的关系

  • Port_Group 表示“逻辑交换机端口的集合”(按端口名分组)。它常用于把一组端口作为 ACL 的目标(用 inport / outport 中的 port-group 名称)。Port_Group 更适合“按端口”而非“按 IP”来打包规则。(Dash Dash)
  • 自动生成的 Address_Sets:ovn-northd/ovn 会为每个 Port_Group 在 Southbound 的 Address_Set 表中生成对应的地址集合(通常是两个:IPv4 和 IPv6,命名为 <PortGroup>_ip4<PortGroup>_ip6),这些 generated address sets 可在 match(例如 ACL)中当作地址集合使用。
  • 也就是说,Port_Group → ovn 会在 SB 中产生 address_set 表项,方便把“端口分组”隐式映射为“该组的 IP 列表”。(Ubuntu Manpages)

3) 在 routing-policy(PBR)中可否使用 Address_Set?如何使用?

  • Routing-policy 的 match 字段使用与 ACL / logical_flow 相同的表达语言(支持 ip4.src / ip4.dst / inport / outport / address_set(...) 等)。因此你可以在路由策略里直接引用 Address_Set(例如做基于源 IP 的 reroute 或 permit/deny)。文档和邮件补丁都显示了将 routing-policy 用于 PBR,并在 match 中使用 IP 匹配的示例。(ovn.org)

  • 实际例子(命令形式)——伪示例(可直接在 nb 层执行):

    # 创建 address set
    ovn-nbctl create Address_Set name=web-servers addresses=10.10.1.5 10.10.1.6
    
    # 在某个 logical router 上添加 routing policy:匹配来自 web-servers 的流量并重路由
    ovn-nbctl lr-policy-add <router> 100 'ip4.src == $web-servers' reroute 192.0.2.1
    

    或者(在 ACL / 某些场景中):

    ovn-nbctl acl-add <ls> to-lport 100 'ip4 && ip4.src == $web-servers' allow
    

    这些写法在官方手册/示例与历史补丁里都有示例或等效形式。(mail.openvswitch.org)


4) 那么:只创建 Address_Set(不创建 Port_Group)能否满足策略路由/安全组需求?

  • 。如果你的需求是“基于 IP(或 CIDR)做匹配 / 重路由 / 放行/拒绝”,只用 Address_Set 就足够了 —— 创建 Address_Set,ACL 或 routing-policy 中引用它即可。很多系统(包括 OVN-Kubernetes / OpenStack 的实现)会直接往 Address_Set 写入 IP(例如将 Security Group 映射为 Address_Sets),然后把 ACL 或策略指向这些 sets。(docs.openstack.org)
  • 何时需要 Port_Group? 如果你想按“端口名字集合”来下发规则(例如“所有属于某安全组的端口名集合”并把 ACL 应用于这些端口,而不仅仅是 IP),Port_Group 更直接——它在 NB 层表达“端口集合”,并且 ovn 会为其生成与该端口集合对应的 address_sets,在使用场景上更贴合“安全组按端口”这种模型(OpenStack 的 Security Group 实现就是这样)。(Dash Dash)

5) 实践建议与注意事项(坑与优化)

  • 性能/规模:大量 Address_Set(或每个端口一个 address)会增加 ovn-northd/ovn-controller 生成的逻辑流数目,可能影响规模/性能。OVN 有合并/优化逻辑(conjunction 合并等),但在大规模场景下需要注意设计(例如把 IP 合并成 CIDR、避免过度碎片化的 sets)。(Patchwork)
  • 类型一致性:单个 Address_Set 只允许一种地址类型(v4 / v6 / eth),不要混合。(Debian Manpages)
  • 命名与引用:在 NB 层用 address_set(name)(或明文 $name)引用较直观;ovn 在下游会把它翻译为内部的 $a<hex> 形式 —— 因此看到 $a... 并不奇怪,它是 ovn 的内部变量表示。(mail.openvswitch.org)
  • Port_Group 自动生成的 address_sets:如果你用 Port_Group(例如由上层 CMS 自动创建),注意它会在 SB 生成 _ip4/_ip6 的 address_set;如果你也手动维护 Address_Set,注意名称冲突与同步关系。(Ubuntu Manpages)
  • 在 routing-policy 中的可见性:routing-policy 的 match 支持和 ACL 相同的表达式,因此任何在 ACL 中合法用到的 address_set 引用,在 routing-policy 的 match 中通常也是合法的(但要谨慎测试复杂表达式和优先级效果)。(ovn.org)

参考命令示例(可复制到你的环境验证)

# 1) 创建 address set(IPv4)
ovn-nbctl create Address_Set name=backend_ips addresses=10.244.1.5,10.244.1.6

# 2) 在 logical switch 的 ACL 中引用(放行来自 backend_ips 的流量)
ovn-nbctl acl-add ls1 to-lport 100 'ip4 && ip4.src == address_set(backend_ips)' allow

# 3) 在 logical router 上添加 routing policy,匹配来源为 backend_ips 并重路由(reroute)
ovn-nbctl lr-policy-add lr1 200 'ip4.src == address_set(backend_ips)' reroute 192.0.2.1

(根据你的 OVN 版本,address_set(name) / $name 两种引用形式可能都可以,ovn-northd 也会把它们转换为内部变量形式。)(mail.openvswitch.org)


若干实用参考(原始文档/讨论)

  • OVN NB schema — Address_Set / Port_Group 描述(官方手册)。(ovn.org)
  • SB 中说明:Port_Group 会在 SB Address_Set 产生 _ip4 / _ip6。(Ubuntu Manpages)
  • Patch / 邮件列表:address_set() 在 ACL 中的引入示例与用法。(mail.openvswitch.org)
  • routing-policy / PBR 的补丁与文档,表明 routing-policy 的 match 使用相同表达语言,可用于 reroute/permit/deny。(Patchwork)