Open vSwitch 入门实践

2026-02-06 01:51:186963

Open vSwitch 入门实践

Open vSwitch 入门实践(1)简介

来源 https://zhuanlan.zhihu.com/p/336487371

OVS简介

Open vSwitch 是什么?

Open vSwitch(以下简称OVS)是一个用C语言开发的多层虚拟交换机,使用Apcahe 2开源许可证,现如今基本上已经成为了开源SDN(软件定义网络)基础设施层的事实标准。

OVS支持哪些功能?

支持NetFlow、sFlow(R)、IPFIX、SPAN、RSPAN和GRE隧道镜像等多种流量监控协议

支持LACP (IEEE 802.1AX-2008)

支持标准802.1Q VLAN协议,允许端口配置trunk模式

支持组播

支持BFD和802.1ag链路监控

支持STP(IEEE 802.1D-1998)和RSTP(IEEE 802.1D-2004)

支持细粒度的QoS(服务质量)配置

支持HFSC qdisc

支持接管每一个虚拟机的流量

支持基于源MAC的负载均衡、主备模式和L4哈希的端口绑带

支持OpenFlow协议(包含了很多对虚拟化的扩展)

支持IPv6

支持多种隧道协议(GRE、VXLAN、STT、Geneve和IPsec)

支持C和Python的远程配置协议

支持内核和用户空间的转发引擎选项

具有流缓存引擎的多表转发管道

转发层抽象以简化向新软件和硬件平台的移植

OVS的术语解释

Bridge

中文名称网桥,一个Bridge代表一个以太网交换机(Switch),一台主机中可以创建一个或多个Bridge,Bridge可以根据一定的规则,把某一个端口接收到的数据报文转发到另一个或多个端口上,也可以修改或者丢弃数据报文。

Port

中文名称端口,需要注意的是它和TCP里面的端口不是同样的概念,它更像是物理交换机上面的插口,可以接水晶头的那种。Port隶属于Bridge,必须先添加了Bridge才能在Bridge上添加Port。Port有以下几种类型:

Normal用户可以把操作系统中已有的网卡添加到Open vSwitch上,Open vSwitch会自动生成一个同名的Port开处理这张网卡进和出的数据报文。不过需要注意的是这种方式添加的Port不支持分配IP地址,如果之前网卡上配置的有IP,挂载到OVS上面之后将不可访问。此类型的Port常用于VLAN模式的多台物理主机相连的那个口,交换机一端属于Trunk模式。

Internal当Port的类型是Internal时,OVS会自动创建一个虚拟网卡(Interface),此端口收到的数据报文都会转发给这块网卡,从这块网卡发出的数据报文也会通过Port交给OVS处理。当OVS创建一个新的网桥时,会自动创建一个与网桥同名的Internal Port,同时也会创建一个与网桥同名的Interface,因此可以通过ip命令在操作系统中查看到这张虚拟网卡,但是状态是down的。

PatchPatch Port和veth pair功能相同,总是成双成对的出现,在其中一端收到的数据报文会被转发到另一个Patch Port上,就像是一根网线一样。Patch Port常用于连接两个Bridge,这样两个网桥就和一个网桥一样了。

TunnelOVS 支持 GRE、VXLAN、STT、Geneve和IPsec隧道协议,这些隧道协议就是overlay网络的基础协议,通过对物理网络做的一层封装和扩展,解决了二层网络数量不足的问题,最大限度的减少对底层物理网络拓扑的依赖性,同时也最大限度的增加了对网络的控制。

Interface

(iface/接口)接口是OVS与操作系统交换数据报文的组件,一个接口即是操作系统上的一块网卡,这个网卡可能是OVS生成的虚拟网卡,也有可能是挂载在OVS上的物理网卡,操作系统上的虚拟网卡(TUN/TAP)也可以被挂载在OVS上。

Controller

OpenFlow控制器,OVS可以接收一个或者多个OpenFlow控制器的管理,功能主要是下发流表,控制转发规则。

Flow

流表是OVS进行数据转发的核心功能,定义了端口之间转发数据报文的规则,一条流表规则主要分为匹配和动作两部分,匹配部分决定哪些数据报文需要被处理,动作决定了匹配到的数据报文该如何处理。

OVS常用操作

安装

yum install openvswitch

systemctl enable openvswitch

systemctl start openvswitch

如果当前软件源中没有openvswitch,可以通过阿里云官方镜像站下载和操作系统版本对应的rpm包到本地再安装。 示例命令: yum localinstall openvswitch-2.9.0-3.el7.x86_64.rpm

Bridge 操作

添加网桥

ovs-vsctl add-br br-int

查询网桥列表

ovs-vsctl list-br

删除网桥

ovs-vsctl del-br br-int

Port 操作

Normal Port

# 将物理网卡eth0添加到网桥br-int上

ovs-vsctl add-port br-int eth0

# 移除网桥br-int上的Port

ovs-vsctl del-port br-int eth0

Internal Port

# 添加Internal Port

ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal

# 把网卡vnet0启动并配置IP

ip link set vnet0 up

ip addr add 192.168.0.1/24 dev vnet0

# 设置VLAN tag

ovs-vsctl set Port vnet0 tag=100

# 移除vnet0上面的VLAN tag配置

ovs-vsctl remove Port vnet0 tag 100

# 设置vnet0允许通过的VLAN tag

ovs-vsctl set Port vnet0 trunks=100,200

# 移除vnet0允许通过的的VLAN tag配置

ovs-vsctl remove Port vnet0 trunks 100,200

Patch Port

ovs-vsctl add-br br0

ovs-vsctl add-br br1

ovs-vsctl \

-- add-port br0 patch0 -- set interface patch0 type=patch options:peer=patch1 \

-- add-port br1 patch1 -- set interface patch1 type=patch options:peer=patch0

Tunnel Port

#主机10.1.7.21上

ovs-vsctl add-br br-tun

ovs-vsctl add-port br-tun vxlan-vx01 -- set Interface vxlan-vx01 type=vxlan options:remote_ip=10.1.7.22 options:key=flow

ovs-vsctl add-port br-tun vxlan-vx02 -- set Interface vxlan-vx02 type=vxlan options:remote_ip=10.1.7.23 options:key=flow

#主机10.1.7.22上

ovs-vsctl add-br br-tun

ovs-vsctl add-port br-tun vxlan-vx01 -- set Interface vxlan-vx01 type=vxlan options:remote_ip=10.1.7.21 options:key=flow

ovs-vsctl add-port br-tun vxlan-vx02 -- set Interface vxlan-vx02 type=vxlan options:remote_ip=10.1.7.23 options:key=flow

#主机10.1.7.23上

ovs-vsctl add-br br-tun

ovs-vsctl add-port br-tun vxlan-vx01 -- set Interface vxlan-vx01 type=vxlan options:remote_ip=10.1.7.21 options:key=flow

ovs-vsctl add-port br-tun vxlan-vx02 -- set Interface vxlan-vx02 type=vxlan options:remote_ip=10.1.7.22 options:key=flow

其他基本操作

# 设置VLAN mode

ovs-vsctl set port VLAN_mode=trunk|access|native-tagged|native-untagged

# 设置VLAN tag

ovs-vsctl set port tag=<1-4095>

# 设置VLAN trunk

ovs-vsctl set port trunk=100,200

# 移除Port的属性

ovs-vsctl remove port

# 查看Port的属性

ovs-vsctl list interface

接下来我们将使用OVS来实现单机和多台物理服务器下的虚拟VLAN网络。

Open vSwitch 入门实践(2)使用OVS构建隔离网络

来源 https://zhuanlan.zhihu.com/p/336692269

前言

在前面我们已经使用Linux Bridge完成了多台网络设备的通信,但是它对于网络隔离的支持不是很好,长期以来,在Linux平台上缺少一个功能完备的虚拟交换机,直到OVS的出现。

实验

接下来我们来尝试完成两个实验,单机无隔离网络、单机隔离网络。

实验一:单机无隔离网络

使用ovs构建无隔离网络非常简单,只需要添加一个网桥,然后在这个网桥上再增加几个内部端口,最后把端口移动到netns中即可。

# 添加网桥

ovs-vsctl add-br br-int

# 添加三个内部端口

ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal

ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal

ovs-vsctl add-port br-int vnet2 -- set Interface vnet2 type=internal

# 添加三个netns

ip netns add ns0

ip netns add ns1

ip netns add ns2

# 将内部端口分别移动到netns中

ip link set vnet0 netns ns0

ip link set vnet1 netns ns1

ip link set vnet2 netns ns2

# 启动端口并配置IP

ip netns exec ns0 ip link set lo up

ip netns exec ns0 ip link set vnet0 up

ip netns exec ns0 ip addr add 10.0.0.1/24 dev vnet0

ip netns exec ns1 ip link set lo up

ip netns exec ns1 ip link set vnet1 up

ip netns exec ns1 ip addr add 10.0.0.2/24 dev vnet1

ip netns exec ns2 ip link set lo up

ip netns exec ns2 ip link set vnet2 up

ip netns exec ns2 ip addr add 10.0.0.3/24 dev vnet2

测试

测试ns0和ns1能否通信ip netns exec ns0 ping 10.0.0.2

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.

64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=1.05 ms

64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.059 ms

64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.056 ms

64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.053 ms

^C

--- 10.0.0.2 ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 3000ms

rtt min/avg/max/mdev = 0.053/0.304/1.051/0.431 ms

测试ns0和ns2能否通信ip netns exec ns0 ping 10.0.0.3

PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.

64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=1.17 ms

64 bytes from 10.0.0.3: icmp_seq=2 ttl=64 time=0.067 ms

64 bytes from 10.0.0.3: icmp_seq=3 ttl=64 time=0.058 ms

64 bytes from 10.0.0.3: icmp_seq=4 ttl=64 time=0.064 ms

^C

--- 10.0.0.3 ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 3001ms

rtt min/avg/max/mdev = 0.058/0.341/1.177/0.482 ms

根据测试结果可以看到,三台设备都是可以互相访问的,这样我们就成功搭建了一个无隔离的二层互通网络。

实验二: 单机隔离网络

使用ovs构建隔离网络也很简单,只需要给相应的端口设置上VLAN标签,就能实现网络的隔离。

# 设置vnet0的VLAN tag为100

ovs-vsctl set Port vnet0 tag=100

# 设置vnet1和vnet2的VLAN tag为200

ovs-vsctl set Port vnet1 tag=200

ovs-vsctl set Port vnet2 tag=200

使用ovs-vsctl show命令查看VLAN tag是否配置成功

90139c71-8d11-49b2-b44c-f34174259dc8

Bridge br-int

Port "vnet0"

tag: 100

Interface "vnet0"

type: internal

Port br-int

Interface br-int

type: internal

Port "vnet2"

tag: 200

Interface "vnet2"

type: internal

Port "vnet1"

tag: 200

Interface "vnet1"

type: internal

ovs_version: "2.9.0"

测试

测试ns0与ns1的能否通信 ip netns exec ns0 ping 10.0.0.2

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.

^C

--- 10.0.0.2 ping statistics ---

2 packets transmitted, 0 received, 100% packet loss, time 1000ms

测试ns0与ns2的能否通信 ip netns exec ns0 ping 10.0.0.3

PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.

^C

--- 10.0.0.3 ping statistics ---

2 packets transmitted, 0 received, 100% packet loss, time 999ms

测试ns1与ns2的能否通信 ip netns exec ns1 ping 10.0.0.3

PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.

64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=0.930 ms

64 bytes from 10.0.0.3: icmp_seq=2 ttl=64 time=0.057 ms

64 bytes from 10.0.0.3: icmp_seq=3 ttl=64 time=0.056 ms

64 bytes from 10.0.0.3: icmp_seq=4 ttl=64 time=0.057 ms

^C

--- 10.0.0.3 ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 3000ms

rtt min/avg/max/mdev = 0.056/0.275/0.930/0.378 ms

测试ns2与ns1的能否通信 ip netns exec ns2 ping 10.0.0.2

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.

64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.088 ms

64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.057 ms

64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.050 ms

64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.060 ms

^C

--- 10.0.0.2 ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 2999ms

rtt min/avg/max/mdev = 0.050/0.063/0.088/0.017 ms

根据测试结果可以看出,ns0是无法访问到ns1和ns2的,ns1和ns2可以互相访问。这是因为端口vnet0的数据报文发出后被OVS修改了包头,增加了VLAN 100标签,与vnet1、vnet2的VLAN 200标签不匹配,OVS交换机便不再将vnet0的数据报文发送给其他两个端口,由此便实现了网络隔离。

清理实验环境

ovs-vsctl del-br br-int

ip netns del ns0

ip netns del ns1

ip netns del ns2

Open vSwitch 入门实践(3)使用OVS构建分布式隔离网络

来源 https://zhuanlan.zhihu.com/p/337210249

使用OVS构建分布式隔离网络

前言

上一节我们使用OVS构建了单机隔离网络,但是随着网络规模的扩张,单节点已经不再能满足业务的需要,分布式网络成了必不可少的环节。分布式网络与单节点网络在细节实现上基本一致,只有物理环境网络连线上的一点区别。

实验1:分布式无隔离网络

网络拓扑如下图所示,我们每一台节点都有两张网卡,一张用于管理,一张用于业务。之所以使用两张网卡有两个原因:

管理网卡用于日常的维护登录,业务网卡用于传输虚拟节点的数据报文,避免相互之间影响。

我们要将业务网卡绑定到OVS网桥上,也就是Normal类型的Port。这种方式添加的Port不支持分配IP地址,如果之前网卡上配置的有IP,挂载到OVS上面之后将不可访问。

需要注意的是,如果是使用物理环境搭建网络拓扑,需要把业务网卡对应的交换机端口配置为trunk模式。如果是使用VmWare搭建网络拓扑,业务网卡需要配置网络类型为仅主机模式。

配置

配置环境 主机A

ovs-vsctl add-br br-int

# 请修改eth1为当前实验环境的业务网卡名称

ovs-vsctl add-port br-int eth1

# 添加两个内部端口

ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal

ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal

# 添加两个netns

ip netns add ns0

ip netns add ns1

# 将内部端口分别移动到netns中

ip link set vnet0 netns ns0

ip link set vnet1 netns ns1

# 启动端口并配置IP

ip netns exec ns0 ip link set lo up

ip netns exec ns0 ip link set vnet0 up

ip netns exec ns0 ip addr add 10.0.0.1/24 dev vnet0

ip netns exec ns1 ip link set lo up

ip netns exec ns1 ip link set vnet1 up

ip netns exec ns1 ip addr add 10.0.0.2/24 dev vnet1

配置环境 主机B

ovs-vsctl add-br br-int

# 请修改eth1为当前实验环境的业务网卡名称

ovs-vsctl add-port br-int eth1

# 添加两个内部端口

ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal

ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal

# 添加两个netns

ip netns add ns0

ip netns add ns1

# 将内部端口分别移动到netns中

ip link set vnet0 netns ns0

ip link set vnet1 netns ns1

# 启动端口并配置IP

ip netns exec ns0 ip link set lo up

ip netns exec ns0 ip link set vnet0 up

ip netns exec ns0 ip addr add 10.0.0.3/24 dev vnet0

ip netns exec ns1 ip link set lo up

ip netns exec ns1 ip link set vnet1 up

ip netns exec ns1 ip addr add 10.0.0.4/24 dev vnet1

测试

测试 主机A

ip netns exec ns0 ping 10.0.0.3

ip netns exec ns0 ping 10.0.0.4

ip netns exec ns1 ping 10.0.0.3

ip netns exec ns1 ping 10.0.0.4

测试 主机B

ip netns exec ns0 ping 10.0.0.1

ip netns exec ns0 ping 10.0.0.2

ip netns exec ns1 ping 10.0.0.1

ip netns exec ns1 ping 10.0.0.2

测试结果

主机A主机Bping 结果

根据测试结果可以看到我们使用OVS成功的联通了分布在不同主机上的虚拟网络设备。

实验2:分布式隔离网络

构建分布式隔离网络和单节点的操作方法一致,即给对应的端口配置VLAN tag。如下图所示,我们分别给主机A、B上的端口配置VLAN tag为100和200。

配置

配置环境 主机A

ovs-vsctl set Port vnet0 tag=100

ovs-vsctl set Port vnet1 tag=200

配置环境 主机B

ovs-vsctl set Port vnet0 tag=100

ovs-vsctl set Port vnet1 tag=200

测试

测试 主机A

ip netns exec ns0 ping 10.0.0.3

ip netns exec ns0 ping 10.0.0.4

ip netns exec ns1 ping 10.0.0.3

ip netns exec ns1 ping 10.0.0.4

测试 主机B

ip netns exec ns0 ping 10.0.0.1

ip netns exec ns0 ping 10.0.0.2

ip netns exec ns1 ping 10.0.0.1

ip netns exec ns1 ping 10.0.0.2

测试结果

主机A主机Bping 结果

根据测试结果可以看到我们使用OVS成功的隔离了分布在不同主机上的虚拟网络设备。

Open vSwitch 入门实践(4)使用OVS配置端口镜像

来源 https://zhuanlan.zhihu.com/p/337436733

前言

当我们想要在不影响虚拟网络设备数据报文收发的情况下获取对应虚拟网络设备的流量时,端口镜像是一个很好的选择。端口镜像是指将经过指定端口(镜像端口)的报文复制一份到另一个指定端口(观察端口),通过观察端口接收到的数据报文,就可以有效识别虚拟网络的运行情况。

OVS提供了相关命令来配置或删除端口镜像,下面我们来实验一下。

如何使用

端口镜像类型

端口镜像分为镜像源和镜像目的两部分。

镜像源

select_all:布尔类型(true,false)。设置为 true 时,表示此网桥上的所有流量。

select_dst_port:字符串(端口名称)。表示此端口接收的所有流量。

select_src_port:字符串(端口名称)。表示此端口发送的所有流量。

select_vlan:整形(1-4096)。表示携带此VLAN标签的流量。

镜像目的

output_port:字符串(端口名称)。接收流量报文的观察端口。

output_vlan:整形(1-4096)。表示只修改VLAN标签,原VLAN标签会被剥离。

基础操作命令

新增端口镜像

ovs-vsctl -- set Bridge mirrors=@m \

-- --id=@ get Port \

-- --id=@ get Port \

-- --id=@m create Mirror name= select-dst-port=@ select-src-port=@ output-port=@

这行命令会输出一个镜像ID

删除端口镜像

ovs-vsctl remove Bridge mirrors

在原端口镜像的基础上增加一个镜像源

# 获取端口的ID

ovs-vsctl get port _uuid

# 在原端口镜像的基础上增加镜像源

ovs-vsctl add Mirror select_src_port

ovs-vsctl add Mirror select_dst_port

在原端口镜像的基础上删除一个镜像源

# 获取端口的ID

ovs-vsctl get port _uuid

ovs-vsctl remove Mirror select_src_port

ovs-vsctl remove Mirror select_dst_port

清空端口镜像

ovs-vsctl clear Mirror

查看端口镜像

ovs-vsctl list Mirror

关闭端口的MAC地址学习

ovs-ofctl mod-port NO-FLOOD

实验

实验拓扑

实验拓扑分为一个网桥,三个虚拟网络设备,

# 添加网桥

ovs-vsctl add-br br-int

# 添加三个内部端口

ovs-vsctl add-port br-int vnet0 -- set Interface vnet0 type=internal

ovs-vsctl add-port br-int vnet1 -- set Interface vnet1 type=internal

ovs-vsctl add-port br-int vnet2 -- set Interface vnet2 type=internal

# 添加三个netns

ip netns add ns0

ip netns add ns1

ip netns add ns2

# 将内部端口分别移动到netns中

ip link set vnet0 netns ns0

ip link set vnet1 netns ns1

ip link set vnet2 netns ns2

# 启动端口并配置IP

ip netns exec ns0 ip link set lo up

ip netns exec ns0 ip link set vnet0 up

ip netns exec ns0 ip addr add 10.0.0.1/24 dev vnet0

ip netns exec ns1 ip link set lo up

ip netns exec ns1 ip link set vnet1 up

ip netns exec ns1 ip addr add 10.0.0.2/24 dev vnet1

# 注意这里只启动了网卡,但没有配置IP

ip netns exec ns2 ip link set lo up

ip netns exec ns2 ip link set vnet2 up

ovs-vsctl -- set Bridge br-int mirrors=@m \

-- --id=@vnet1 get Port vnet1 \

-- --id=@vnet2 get Port vnet2 \

-- --id=@m create Mirror name=mirror_test select-dst-port=@vnet1 select-src-port=@vnet1 output-port=@vnet2

测试

执行以下命令产生流量

ip netns exec ns0 ping 10.0.0.2

重新打开一个终端执行以下命令抓包

ip netns exec ns2 tcpdump -i vnet2

需要安装tcpdump才能使用

输出

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on vnet2, link-type EN10MB (Ethernet), capture size 262144 bytes

22:26:31.140974 IP 10.0.0.1 > 10.0.0.2: ICMP echo request, id 4599, seq 23, length 64

22:26:31.140996 IP 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 4599, seq 23, length 64

22:26:32.141066 IP 10.0.0.1 > 10.0.0.2: ICMP echo request, id 4599, seq 24, length 64

22:26:32.141085 IP 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 4599, seq 24, length 64

22:26:33.141066 IP 10.0.0.1 > 10.0.0.2: ICMP echo request, id 4599, seq 25, length 64

22:26:33.141108 IP 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 4599, seq 25, length 64

22:26:34.141044 IP 10.0.0.1 > 10.0.0.2: ICMP echo request, id 4599, seq 26, length 64

22:26:34.141062 IP 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 4599, seq 26, length 64

^C

8 packets captured

8 packets received by filter

0 packets dropped by kernel

清理实验环境

ip netns del ns0

ip netns del ns1

ip netns del ns2

ovs-vsctl del-br br-int

============= End