Open vSwitch 入门实践

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的。
  • Patch
    Patch Port和veth pair功能相同,总是成双成对的出现,在其中一端收到的数据报文会被转发到另一个Patch Port上,就像是一根网线一样。Patch Port常用于连接两个Bridge,这样两个网桥就和一个网桥一样了。
  • Tunnel
    OVS 支持 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 <port name> VLAN_mode=trunk|access|native-tagged|native-untagged
# 设置VLAN tag
ovs-vsctl set port <port name> tag=<1-4095>
# 设置VLAN trunk
ovs-vsctl set port <port name> trunk=100,200
# 移除Port的属性
ovs-vsctl remove port <port name> <property name> <property value>
# 查看Port的属性
ovs-vsctl list interface <port name>

接下来我们将使用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

测试

测试ns0ns1能否通信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

测试ns0ns2能否通信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"

测试

测试ns0ns1的能否通信 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

测试ns0ns2的能否通信 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

测试ns1ns2的能否通信 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

测试ns2ns1的能否通信 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是无法访问到ns1ns2的,ns1ns2可以互相访问。这是因为端口vnet0的数据报文发出后被OVS修改了包头,增加了VLAN 100标签,与vnet1vnet2的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:分布式无隔离网络

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

  1. 管理网卡用于日常的维护登录,业务网卡用于传输虚拟节点的数据报文,避免相互之间影响。
  2. 我们要将业务网卡绑定到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 <bridge_name> mirrors=@m \
 -- --id=@<port0> get Port <port0> \
 -- --id=@<port1> get Port <port1> \
 -- --id=@m create Mirror name=<mirror_name> select-dst-port=@<port0> select-src-port=@<port0> output-port=@<port1>
这行命令会输出一个镜像ID

删除端口镜像

ovs-vsctl remove Bridge <bridge-name> mirrors <mirror-id>

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

# 获取端口的ID
ovs-vsctl get port <port_name> _uuid

# 在原端口镜像的基础上增加镜像源
ovs-vsctl add Mirror <mirror-name> select_src_port <port-id>
ovs-vsctl add Mirror <mirror-name> select_dst_port <port-id>

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

# 获取端口的ID
ovs-vsctl get port <port_name> _uuid

ovs-vsctl remove Mirror <mirror-name> select_src_port <port-id>
ovs-vsctl remove Mirror <mirror-name> select_dst_port <port-id>

清空端口镜像

ovs-vsctl clear Mirror 

查看端口镜像

ovs-vsctl list Mirror 

关闭端口的MAC地址学习

ovs-ofctl mod-port <bridge-name> <port-name> 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

 

posted @ 2024-03-03 15:56  lsgxeva  阅读(182)  评论(0编辑  收藏  举报