详细分析 ovn nb db port_group 和 address_set 是否有什么绑定关系, address_set 是否可以配合策略路由独立使用,,也就是说只创建 address_set 不使用 port_group
下面把 OVN 中 Port_Group 与 Address_Set 的关系、语义差异、能否单独使用,以及在策略路由(routing-policy / PBR)中的可用性做一个详细、技术向的汇总与建议 —— 并给出常用命令/匹配写法示例与注意事项。
结论速览
- Address_Set 是可以独立使用的 —— 它是 NB(Northbound)表的一等对象,可以直接创建并在 ACL / routing-policy 的 match 表达式里引用,用于基于 IP/ETH 的匹配(因此可以只创建 Address_Set 而不建 Port_Group)。(ovn.org)
- 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) - 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)