Red Hat Training

A Red Hat training course is available for Red Hat OpenStack Platform

使用 Open Virtual Network 的网络

Red Hat OpenStack Platform 13

带有 OVN 的 OpenStack 网络

摘要

使用 OVN 进行 OpenStack 网络任务的说明书。

前言

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息

第 1 章 Open Virtual Network (OVN)

Open Virtual Network (OVN)是基于 Open vSwitch 的软件定义型网络(SDN)解决方案,用于为实例提供网络服务。OVN 为完整的 OpenStack Networking API 提供平台中立支持。使用 OVN,您可以以编程方式将客户机实例组连接到私有 L2 和 L3 网络。OVN 使用标准的虚拟网络来实现其他红帽平台和解决方案进行扩展。

此 Red Hat OpenStack Platform (RHOSP)发行版本不提供受支持的从 ML2/OVS 机制驱动程序迁移到 ML2/OVN 机制驱动程序的迁移。此 RHOSP 发行版本不支持 OpenStack 社区迁移策略。计划在未来的 RHOSP 发行版本获得迁移支持。

注意

需要的最小 OVS 版本是 OVS 2.9。

本节介绍了使用 director 部署 OVN 所需的步骤。

注意

只有在至少具有三个带有分布式虚拟路由(DVR)的控制器节点的 RHOSP 高可用性(HA)环境中支持 OVN。

1.1. RHOSP OVN 架构中的组件列表

RHOSP OVN 架构将 OVS Modular Layer 2 (ML2)机制驱动程序替换为 OVN ML2 机制驱动程序来支持网络 API。OVN 为红帽 OpenStack 平台提供网络服务。

OVN 架构由以下组件和服务组成:

ML2 插件与 OVN 机制驱动程序
ML2 插件将 OpenStack 特定的网络配置转换为平台中立的 OVN 逻辑网络配置。它通常在 Controller 节点上运行。
OVN 北向(NB)数据库(ovn-nb)
此数据库从 OVN ML2 插件存储逻辑 OVN 网络配置。它通常在 Controller 节点上运行,并侦听 TCP 端口 6641
OVN 北向服务(ovn-northd)
此服务将 OVN NB 数据库的逻辑网络配置转换为逻辑数据路径流,并在 OVN 南向数据库中填充它们。它通常在 Controller 节点上运行。
OVN 南向(SB)数据库(ovn-sb)
此数据库存储转换的逻辑数据路径流。它通常在 Controller 节点上运行,并侦听 TCP 端口 6642
OVN 控制器(ovn-controller)
此控制器连接到 OVN SB 数据库,充当控制和监控网络流量的 Open vSwitch 控制器。它在定义了 OS::Tripleo::Services::OVNController 的所有计算和网关节点上运行。
OVN 元数据代理(ovn-metadata-agent)
此代理创建 haproxy 实例,用于管理用于代理元数据 API 请求的 OVS 接口、网络命名空间和 HAProxy 进程。代理在所有定义了 OS::TripleO::Services::OVNMetadataAgent 的所有计算和网关节点上运行。
OVS 数据库服务器(OVSDB)
主机托管 OVN 北向和南向数据库。另外,也与 ovs-vswitchd 交互,以托管 OVS 数据库 conf.db
注意

NB 数据库的 schema 文件位于 /usr/share/ovn/ovn-nb.ovsschema 中,SB 数据库模式文件位于 /usr/share/ovn/ovn-sb.ovsschema 中。

OVN 组件

第 2 章 规划您的 OVN 部署

仅在包含至少三个控制器节点的高可用性 RHOSP 高可用性(HA)环境中部署 OVN。部署启用了分布式虚拟路由(DVR)的 OVN。

在新的 ML2/OVN 部署中默认启用 DVR,并在新的 ML2/OVS 部署中默认禁用。neutron-ovn-dvr-ha.yaml 环境文件为在 HA 环境中使用 OVN 的部署配置所需的特定于 DVR 的参数。

注意

要使用 OVN,您的 director 部署必须使用通用网络虚拟化封装(Geneve),而不使用 VXLAN。Geneve 允许 OVN 使用 24 位虚拟网络标识符(VNI)字段识别网络,并额外 32 位类型长度值(TLV)来指定源和目标逻辑端口。在决定 MTU 设置时,您应该考虑这个较大的协议标头。

2.1. Compute 节点上的 ovn-controller 服务

ovn-controller 服务在每个 Compute 节点上运行,并连接到 OVN southbound (SB)数据库服务器,以检索逻辑流。ovn-controller 将这些逻辑流转换为物理 OpenFlow 流,并将流添加到 OVS 网桥(br-int)。要与 ovs-vswitchd 进行通信并安装 OpenFlow 流,ovn-controller 使用启动 ovn-controller 时传递的 UNIX 套接字路径(如 unix:/var/run/openvswitch/db.sock)连接到本地 ovsdb-server

ovn-controller 服务需要在 Open_vSwitch 表的 external_ids 列中某些键值对; puppet-ovn 使用 puppet-vswitch 来填充这些字段。以下示例显示了 puppet-vswitchexternal_ids 列中配置的键值对:

hostname=<HOST NAME>
ovn-encap-ip=<IP OF THE NODE>
ovn-encap-type=geneve
ovn-remote=tcp:OVN_DBS_VIP:6642

2.2. OVN 可组合服务

Red Hat OpenStack Platform 通常由预定义角色中的一个节点组成,如 Controller 角色、计算角色和不同的存储角色类型。这些默认角色各自包含一组在核心 heat 模板集合中定义的服务。

在默认的 RHOSP ML2/OVN 部署中,ML2/OVN 可组合服务在 Controller 节点上运行。您可以选择创建自定义 Networker 角色,并在专用网络程序节点上运行 OVN 可组合服务。

OVN 可组合服务 ovn-dbs 部署在名为 ovn-dbs-bundle 的容器中。在默认安装中的 ovn-dbs 包含在 Controller 角色中,并在 Controller 节点上运行。由于服务是可组合的,所以您可以将该服务分配给另一个角色,如 Networker 角色。

如果将 OVN 可组合服务分配给另一个角色,请确保该服务与 pacemaker 服务共存在同一节点上,该服务控制 OVN 数据库容器。

2.3. 使用 ML2/OVN 部署自定义角色

在默认的 RHOSP ML2/OVN 部署中,ML2/OVN 可组合服务在 Controller 节点上运行。您可以选择使用支持的自定义角色,如 Networker,它在专用网络器节点上运行 OVN 可组合服务。

您还可以生成自己的自定义角色。

流程

  1. stack 用户身份登录 undercloud 主机,再提供 stackrc 文件。

    $ source stackrc
  2. 选择适合您的部署的自定义角色文件。例如,对于 Networker 角色,请选择 Networker.yaml。如果部署命令符合您的需求,请直接在部署命令中使用。或者生成可组合其他自定义角色文件的自定义角色文件。
  3. [可选] 生成一个新的自定义角色数据文件,该文件将其中一个自定义角色文件与其他自定义角色文件合并。按照 创建 roles_data 文件中的 说明操作。根据您的部署包含适当的源角色文件。
  4. [可选] 要为角色识别特定节点,您可以创建特定的硬件类别,并将类别分配到特定的节点。然后,使用环境文件定义角色的类别,并指定节点数。如需更多信息,请参阅 创建新角色 中的示例
  5. 根据您的部署创建环境文件。例如,对于 Networker 角色,创建名为 neutron-ovn-dvr-ha.yaml 的文件。
  6. 根据您的部署包括以下设置。例如,对于 Networker 角色,请包含以下设置:

    ControllerParameters:
        OVNCMSOptions: ""
    ControllerSriovParameters:
            OVNCMSOptions: ""
    NetworkerParameters:
        OVNCMSOptions: "enable-chassis-as-gw"
  7. 部署 overcloud。在您的部署命令中包括环境文件,并带有 -e 选项。在部署命令中包括自定义角色数据文件,使用 -r 选项。例如: ''-r Networker.yaml' 或 '-r mycustomrolesfile.yaml'。

验证步骤

  1. 确保 ovn_metadata_agent 在 Controller 和 Networker 节点上运行。

    [heat-admin@controller-0 ~]$ sudo docker ps | grep ovn_metadata

    预期的输出类似以下示例。

    a65125d9588d  undercloud-0.ctlplane.localdomain:8787/rh-osbs/rhosp13-openstack-neutron-metadata-agent-ovn:13.1_20200813.1  kolla_start           23 hours ago  Up 21 hours ago         ovn_metadata_agent
  2. 确保带有 OVN 服务或专用网络程序节点的 Controller 节点配置为 OVS 的网关。

    [heat-admin@controller-0 ~]$ sudo ovs-vsctl get Open_Vswitch .
    ...OS::TripleO::Services::NeutronDhcpAgent: OS::Heat::None

    预期的输出类似以下示例。

    external_ids:ovn-cms-options
        enable-chassis-as-gw

2.4. pacemaker 和 DVR 的高可用性

您可以选择两个 ovn-dbs 配置集之一:base profile、ovn-dbs-container 和 pacemaker 高可用性(HA)配置集,ovn-dbs-container-puppet。

启用 pacemaker HA 配置集后,ovsdb-servermaster-slave 模式下运行,由 pacemaker 和资源代理 Open Cluster Framework (OCF)脚本进行管理。OVN 数据库服务器在所有控制器上启动,而 pacemaker 则选择一个控制器来服务主角色。在 master 模式下运行的 ovsdb-server 实例可以写入数据库,而所有其他 slave ovsdb-server 服务可以从主卷在本地复制数据库,且无法写入到数据库。

此配置集的 YAML 文件是 tripleo-heat-templates/environments/services-docker/neutron-ovn-dvr-ha.yaml 文件。启用后,OVN 数据库服务器由 Pacemaker 管理,而 puppet-tripleo 会创建一个名为 ovn:ovndb-servers 的 pacemaker OCF 资源。

OVN 数据库服务器在每个 Controller 节点上启动,控制器将虚拟 IP 地址(OVN_DBS_VIP)在 master 模式下运行 OVN DB 服务器。OVN ML2 机制驱动程序和 ovn-controller 然后使用 OVN_DBS_VIP 值连接到数据库服务器。在故障转移时,Pacemaker 会将虚拟 IP 地址(OVN_DBS_VIP)移到另一个控制器,并将在该节点上运行的 OVN 数据库服务器提升为 master

2.5. 第 3 层高可用性与 OVN

OVN 支持第 3 层高可用性(L3 HA),无需特殊配置。OVN 自动将路由器端口调度到所有可用网关节点,它们可充当指定的外部网络上的 L3 网关。OVN L3 HA 使用 OVN Logical_Router_Port 表中 gateway_chassis 列。大多数功能由带捆绑的 active_passive 输出的 OpenFlow 规则管理。ovn-controller 处理地址解析协议(ARP)响应程序以及路由器启用和禁用。ovn-controller 定期发送 FIP 和路由器外部地址的 ARP。

注意

L3HA 使用 OVN 将路由器重新与原始网关节点进行平衡,以避免任何节点成为瓶颈。

BFD 监控

OVN 使用双向转发检测(BFD)协议来监控网关节点的可用性。这个协议封装在从节点建立的 Geneve 隧道之上。

每个网关节点会监控部署中的星号拓扑中的所有其他网关节点。网关节点也监控计算节点,使网关启用和禁用数据包和 ARP 响应和公告的路由。

每个计算节点使用 BFD 监控每个网关节点,并通过给定路由器的活跃网关节点通过源和目的地网络地址转换(SNAT 和 DNAT)自动抓取外部流量。Compute 节点不需要监控其他计算节点。

注意

因为将 ML2-OVS 配置发生,所以不会检测到外部网络失败。

OVN 的 L3 HA 支持以下故障模式:

  • 网关节点会从网络(隧道接口)断开连接。
  • OVS-vswitchd 停止(ovs-switchd 负责 BFD 信号)
  • OVN-controller 停止(ovn-controller 将自身移除为注册的节点)。
注意

这个 BFD 监控机制只适用于链路失败,不适用于路由失败。

第 3 章 使用 director 部署 OVN

当您在 Red Hat OpenStack Platform 上部署 OVN 时,会触发以下事件:

  1. 启用 OVN ML2 插件并生成必要的配置选项。
  2. 在控制器节点上部署 OVN 数据库和 ovn-northd 服务。
  3. 在每个 Compute 节点上部署 ovn-controller
  4. 在每个 Compute 节点上部署 neutron-ovn-metadata-agent

3.1. 使用 DVR 部署 ML2/OVN

要在 ML2/OVN 部署中部署和管理分布式虚拟路由(DVR),您可以在 heat 模板和环境文件中配置设置。

注意

本指南中的步骤使用 HA 环境中的默认 DVR 部署 OVN。

默认设置仅作为准则提供。它们不应在生产环境或测试环境中工作,这些环境可能需要自定义用于网络隔离、专用 NIC 或任何其他变量因素。

以下示例演示了如何使用典型默认值配置 ML2/OVN、HA 和 DVR 的概念验证部署。

流程

  1. 验证 environments/services/neutron-ovn-dvr-ha.yaml 文件中的 OS::TripleO::Compute::Net::SoftwareConfig 的值与正在使用的 OS::TripleO::Controller::Net::SoftwareConfig 值相同。这通常可在用于部署 overcloud 的网络环境文件中找到,如 environments/net-multiple-nics.yaml 文件。这会在 Compute 节点上创建适当的外部网络桥接。

    注意

    如果自定义 Compute 节点的网络配置,可能需要将适当的配置添加到自定义文件中。

  2. 在部署 overcloud 时,包含 environments/services/neutron-ovn-dvr-ha.yaml 作为环境文件。例如:

    $ openstack overcloud deploy \
        --templates /usr/share/openstack-tripleo-heat-templates \
        ...
     -e /usr/share/openstack-tripleo-heat-templates/environments/services/neutron-ovn-dvr-ha.yaml
  3. 确保 roles_data.yaml 中的 Compute 和 Controller 角色包含标签 external_bridge,并且外部网络条目已添加到 Compute 节点上。例如:

    - name: Compute
      description: |
        Basic Compute Node role
      CountDefault: 1
      # Create external Neutron bridge (unset if using ML2/OVS without DVR)
      tags:
        - external_bridge
      networks:
        External:
          subnet: external_subnet
    ...
    - name: Controller
      description: |
        Controller role that has all the controller services loaded and handles
        Database, Messaging and Network functions.
      CountDefault: 1
      tags:
        - primary
        - controller
        - external_bridge

3.2. 在 Compute 节点上部署 OVN 元数据代理

OVN 元数据代理在 tripleo-heat-templates/docker/services/ovn-metadata.yaml 文件中配置,并通过 OS::TripleO::Services::OVNMetadataAgent 包含在默认 Compute 角色中。因此,带有默认参数的 OVN 元数据代理被部署为 OVN 部署的一部分。请参阅 第 3 章 使用 director 部署 OVN

OpenStack 虚拟机实例访问位于本地链接 IP 地址 169.254.169.254 的联网元数据服务。neutron-ovn-metadata-agent 有权访问存在计算元数据 API 的主机网络。每个 HAProxy 都位于无法到达适当的主机网络的网络命名空间中。HAProxy 将必要的标头添加到元数据 API 请求,然后通过 UNIX 域套接字将请求转发到 neutron-ovn-metadata-agent

OVN 网络服务为每个虚拟网络创建启用元数据服务的唯一网络命名空间。Compute 节点上的实例访问的每个网络都有一个对应的元数据命名空间(ovnmeta-<net_uuid>)。

3.2.1. 元数据问题故障排除

您可以使用元数据命名空间进行故障排除来访问 Compute 节点上的本地实例。要排除元数据命名空间问题,请在 Compute 节点上以 root 用户身份运行以下命令:

# ip netns exec ovnmeta-fd706b96-a591-409e-83be-33caea824114 ssh USER@INSTANCE_IP_ADDRESS

USER@INSTANCE_IP_ADDRESS 是您要故障排除的本地实例的用户名和 IP 地址。

3.3. 使用 OVN 部署内部 DNS

要在本地网络上为 east-west 流量使用域名而不是 IP 地址,请使用内部域名服务(DNS)。使用内部 DNS,ovn-controller 在计算节点上本地响应 DNS 查询。请注意,内部 DNS 覆盖实例 /etc/resolv.conf 文件中指定的任何自定义 DNS 服务器。部署内部 DNS 时,实例的 DNS 查询由 ovn-controller 处理,而不是自定义 DNS 服务器。

流程

  1. 使用 NeutronPluginExtensions 参数启用 DNS:

    parameter_defaults:
      NeutronPluginExtensions: "dns"
  2. 在部署 overcloud 前设置 DNS 域:

      NeutronDnsDomain: "mydns-example.org"
  3. 部署 overcloud:

    $ openstack overcloud deploy \
        --templates /usr/share/openstack-tripleo-heat-templates \
        ...
     -e /usr/share/openstack-tripleo-heat-templates/environments/services-docker/neutron-ovn-dvr-ha.yaml

第 4 章 监控 OVN

您可以使用 ovn-trace 命令来监控 OVN 逻辑流并进行故障排除,您可以使用 ovs-ofctl dump-flows 命令来监控并进行故障排除 OpenFlows。

4.1. 为 OVN 故障排除命令创建别名

OVN 数据库命令(如 ovn-nbctl show)在 ovn_controller 容器上运行。容器在控制器节点和计算节点上运行。为简化您对命令的访问,可创建和提供定义别名的脚本。

前提条件

  • 部署带有 ML2/OVN 的 Red Hat OpenStack Platform 13 作为机制驱动程序。

创建和使用 OVN 数据库命令别名

  1. 在您要运行 ovn 命令的 overcloud 节点上,在适当的目录中创建 shell 脚本文件。例如,以 heat-admin 身份登录控制器节点,并在 heat-admin 用户的 ~/bin 目录中创建文件 ovn-alias.sh。
  2. 在脚本文件中保存以下命令。

    EXTERNAL_ID=\
    $(sudo ovs-vsctl get open . external_ids:ovn-remote | awk -F: '{print $2}')
    export NBDB=tcp:${EXTERNAL_ID}:6641
    export SBDB=tcp:${EXTERNAL_ID}:6642
    
    alias ovn-sbctl="sudo docker exec ovn_controller ovn-sbctl --db=$SBDB"
    alias ovn-nbctl="sudo docker exec ovn_controller ovn-nbctl --db=$NBDB"
    alias ovn-trace="sudo docker exec ovn_controller ovn-trace --db=$SBDB"
  3. 提供 脚本文件。例如,以 heat-admin 身份登录控制器节点,再运行以下命令:

    # source ovn-alias.sh
  4. 验证别名。例如,显示北向数据库。

    ovn-nbctl show

    输出示例

    switch 26ce22db-1795-41bd-b561-9827cbd81778 (neutron-f8e79863-6c58-43d0-8f7d-8ec4a423e13b) (aka internal_network)
    	port 1913c3ae-8475-4b60-a479-df7bcce8d9c8
        	addresses: ["fa:16:3e:33:c1:fc 192.168.254.76"]
    	port 1aabaee3-b944-4da2-bf0a-573215d3f3d9
        	addresses: ["fa:16:3e:16:cb:ce 192.168.254.74"]
    	port 7e000980-59f9-4a0f-b76a-4fdf4e86f27b
        	type: localport
        	addresses: ["fa:16:3e:c9:30:ed 192.168.254.2"]

4.2. 监控 OVN 逻辑流

OVN 使用逻辑流(即优先级为、匹配和操作)的流表。这些逻辑流分发到每个 Compute 节点上运行的 ovn-controller。您可以使用 Controller 节点上的 ovn-sbctl lflow-list 命令来查看完整的逻辑流集合,如下例所示。

$ ovn-sbctl --db=tcp:172.17.1.10:6642 lflow-list
    Datapath: "sw0" (d7bf4a7b-e915-4502-8f9d-5995d33f5d10)  Pipeline: ingress
      table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]), action=(drop;)
      table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present), action=(drop;)
      table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "sw0-port1" && eth.src == {00:00:00:00:00:01}), action=(next;)
      table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "sw0-port2" && eth.src == {00:00:00:00:00:02}), action=(next;)
      table=1 (ls_in_port_sec_ip  ), priority=0    , match=(1), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && arp.sha == 00:00:00:00:00:01), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:01) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:01)))), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port2" && eth.src == 00:00:00:00:00:02 && arp.sha == 00:00:00:00:00:02), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=90   , match=(inport == "sw0-port2" && eth.src == 00:00:00:00:00:02 && ip6 && nd && ((nd.sll == 00:00:00:00:00:00 || nd.sll == 00:00:00:00:00:02) || ((nd.tll == 00:00:00:00:00:00 || nd.tll == 00:00:00:00:00:02)))), action=(next;)
      table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "sw0-port1" && (arp || nd)), action=(drop;)
      table=2 (ls_in_port_sec_nd  ), priority=80   , match=(inport == "sw0-port2" && (arp || nd)), action=(drop;)
      table=2 (ls_in_port_sec_nd  ), priority=0    , match=(1), action=(next;)
      table=3 (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
      table=4 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
      table=5 (ls_in_pre_stateful ), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
      table=5 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
      table=6 (ls_in_acl          ), priority=0    , match=(1), action=(next;)
      table=7 (ls_in_qos_mark     ), priority=0    , match=(1), action=(next;)
      table=8 (ls_in_lb           ), priority=0    , match=(1), action=(next;)
      table=9 (ls_in_stateful     ), priority=100  , match=(reg0[1] == 1), action=(ct_commit(ct_label=0/1); next;)
      table=9 (ls_in_stateful     ), priority=100  , match=(reg0[2] == 1), action=(ct_lb;)
      table=9 (ls_in_stateful     ), priority=0    , match=(1), action=(next;)
      table=10(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
      table=11(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
      table=12(ls_in_dhcp_response), priority=0    , match=(1), action=(next;)
      table=13(ls_in_l2_lkup      ), priority=100  , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
      table=13(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:01), action=(outport = "sw0-port1"; output;)
      table=13(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:00:02), action=(outport = "sw0-port2"; output;)
    Datapath: "sw0" (d7bf4a7b-e915-4502-8f9d-5995d33f5d10)  Pipeline: egress
      table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
      table=1 (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
      table=2 (ls_out_pre_stateful), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
      table=2 (ls_out_pre_stateful), priority=0    , match=(1), action=(next;)
      table=3 (ls_out_lb          ), priority=0    , match=(1), action=(next;)
      table=4 (ls_out_acl         ), priority=0    , match=(1), action=(next;)
      table=5 (ls_out_qos_mark    ), priority=0    , match=(1), action=(next;)
      table=6 (ls_out_stateful    ), priority=100  , match=(reg0[1] == 1), action=(ct_commit(ct_label=0/1); next;)
      table=6 (ls_out_stateful    ), priority=100  , match=(reg0[2] == 1), action=(ct_lb;)
      table=6 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
      table=7 (ls_out_port_sec_ip ), priority=0    , match=(1), action=(next;)
      table=8 (ls_out_port_sec_l2 ), priority=100  , match=(eth.mcast), action=(output;)
      table=8 (ls_out_port_sec_l2 ), priority=50   , match=(outport == "sw0-port1" && eth.dst == {00:00:00:00:00:01}), action=(output;)
      table=8 (ls_out_port_sec_l2 ), priority=50   , match=(outport == "sw0-port2" && eth.dst == {00:00:00:00:00:02}), action=(output;)

OVN 和 OpenFlow 之间的主要区别包括:

  • OVN 端口是位于网络上某个位置的逻辑实体,而不是单一交换机上的物理端口。
  • 除了其编号外,OVN 会为管道中的每个表提供一个名称。name 描述管道中该阶段的用途。
  • OVN 匹配语法支持复杂的布尔值表达式。
  • OVN 逻辑流中支持的操作超出了 OpenFlow 的扩展。您可以在 OVN 逻辑流语法中实施更高级别的功能,如 DHCP。

OVN-trace

ovn-trace 命令可以模拟数据包如何通过 OVN 逻辑流,或者帮助您确定数据包被丢弃的原因。为 ovn-trace 命令提供以下参数:

数据路径
模拟数据包启动的逻辑交换机或逻辑路由器。
MICROFLOW
ovn-sb 数据库使用的语法中模拟数据包。

这个示例在模拟数据包中显示 --minimal 输出选项,并显示数据包到达其目的地:

$ ovn-trace --minimal sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00:00:00:02'
    # reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000
    output("sw0-port2");

如需更多详情,此同一模拟数据包的 --summary 输出会显示完整的执行管道:

$ ovn-trace --summary sw0 'inport == "sw0-port1" && eth.src == 00:00:00:00:00:01 && eth.dst == 00:00:00:00:00:02'
# reg14=0x1,vlan_tci=0x0000,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02,dl_type=0x0000
ingress(dp="sw0", inport="sw0-port1") {
    outport = "sw0-port2";
    output;
    egress(dp="sw0", inport="sw0-port1", outport="sw0-port2") {
        output;
        /* output to "sw0-port2", type "" */;
    };
};

示例输出显示:

  • 数据包进入来自 sw0 -port1 端口的 sw0 网络,并运行入口管道。
  • outport 变量设置为 sw0-port2,表示此数据包的目标为 sw0-port2
  • 数据包是从 ingress 管道的输出,它会把它设置为 sw0 的出口管道,并将 outport 变量设置为 sw0-port2
  • 输出操作在出口管道中执行,它会将数据包输出到 outport 变量的当前值,即 sw0-port2

有关完整详情,请参阅 ovn-trace man page。

4.3. 监控 OpenFlows

您可以使用 ovs-ofctl dump-flows 命令监控网络中的逻辑交换机上的 OpenFlow 流。

$ ovs-ofctl dump-flows br-int
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=72.132s, table=0, n_packets=0, n_bytes=0, idle_age=72, priority=10,in_port=1,dl_src=00:00:00:00:00:01 actions=resubmit(,1)
 cookie=0x0, duration=60.565s, table=0, n_packets=0, n_bytes=0, idle_age=60, priority=10,in_port=2,dl_src=00:00:00:00:00:02 actions=resubmit(,1)
 cookie=0x0, duration=28.127s, table=0, n_packets=0, n_bytes=0, idle_age=28, priority=0 actions=drop
 cookie=0x0, duration=13.887s, table=1, n_packets=0, n_bytes=0, idle_age=13, priority=0,in_port=1 actions=output:2
 cookie=0x0, duration=4.023s, table=1, n_packets=0, n_bytes=0, idle_age=4, priority=0,in_port=2 actions=output:1