OVS架构
用户空间主要组件有数据库服务ovsdb-server和守护进程ovs-vswitchd。kernel中是datapath内核模块。最上面的Controller表示OpenFlow控制器,控制器与OVS是通过OpenFlow协议进行连接,控制器不一定位于OVS主机上,下面分别介绍图中各组件
ovs-vswitchd
ovs-vswitchd
守护进程是OVS的核心部件,它和datapath
内核模块一起实现OVS基于流的数据交换。作为核心组件,它使用openflow协议与上层OpenFlow控制器通信,使用OVSDB协议与ovsdb-server
通信,使用netlink
和datapath
内核模块通信。ovs-vswitchd
在启动时会读取ovsdb-server
中配置信息,然后配置内核中的datapaths
和所有OVS switches,当ovsdb中的配置信息改变时(例如使用ovs-vsctl工具),ovs-vswitchd
也会自动更新其配置以保持与数据库同步
# ps -ef |grep ovs-vs
root 22176 22175 0 Jan17 ? 00:16:56 ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --no-chdir --log-file=/var/log/openvswitch/ovs-vswitchd.log --pidfile=/var/run/openvswitch/ovs-vswitchd.pid --detach --monitor
unix:/var/run/openvswitch/db.sock 与ovsdb通信
/var/log/openvswitch/ovs-vswitchd.log 日志文件存放位置
/var/run/openvswitch/ovs-vswitchd.pid pid文件
在OVS中,ovs-vswitchd
从OpenFlow控制器获取流表规则,然后把从datapath
中收到的数据包在流表中进行匹配,找到匹配的flows并把所需应用的actions返回给datapath
,同时作为处理的一部分,ovs-vswitchd
会在datapath
中设置一条datapath flows用于后续相同类型的数据包可以直接在内核中执行动作,此datapath flows相当于OpenFlow flows的缓存。对于datapath
来说,其并不知道用户空间OpenFlow的存在
ovsdb-server
ovsdb-server
是OVS轻量级的数据库服务,用于整个OVS的配置信息,包括接口/交换内容/VLAN等,OVS主进程ovs-vswitchd
根据数据库中的配置信息工作,下面是ovsdb-server
进程详细信息
root 1305 0.0 0.0 44708 2544 ? S< Aug11 0:04 ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/run/openvswitch/db.sock --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --no-chdir --log-file=/var/log/openvswitch/ovsdb-server.log --pidfile=/var/run/openvswitch/ovsdb-server.pid --detach --monitor
/etc/openvswitch/conf.db 数据库文件位置
punix:/var/run/openvswitch/db.sock 与ovs-vswitch通信socket
/var/log/openvswitch/ovsdb-server.log 日志文件
/var/run/openvswitch/ovsdb-server.pid pid文件位置
DataPath组件
内核组件信息
modinfo openvswitch
filename: /lib/modules/3.10.0-957.21.3.el7.x86_64/kernel/net/openvswitch/openvswitch.ko.xz
alias: net-pf-16-proto-16-family-ovs_packet
alias: net-pf-16-proto-16-family-ovs_flow
alias: net-pf-16-proto-16-family-ovs_vport
alias: net-pf-16-proto-16-family-ovs_datapath
license: GPL
description: Open vSwitch switching datapath
retpoline: Y
rhelversion: 7.6
srcversion: 6FE05FC439FA9CE7E264684
depends: nf_conntrack,nf_nat,libcrc32c,nf_nat_ipv6,nf_nat_ipv4,nf_defrag_ipv6
intree: Y
vermagic: 3.10.0-957.21.3.el7.x86_64 SMP mod_unload modversions
signer: CentOS Linux kernel signing key
sig_key: 1E:5F:1D:87:70:4B:F3:38:01:2F:A2:B0:FE:16:94:59:97:B3:31:27
sig_hashalgo: sha256
datapath
专注于数据交换,它不需要知道OpenFlow的存在。与OpenFlow打交道的是ovs-vswitchd
,ovs-vswitchd
存储所有Flow规则供datapath
查询或缓存.
虽然有ovs-dpctl
管理工具的存在,但我们没必要去手动管理datapath
,这是用户空间ovs-vswitchd
的工作
OVS概念
Bridge
Bridge代表一个以太网交换机(Switch),一个主机中可以创建一个或者多个Bridge。Bridge的功能是根据一定规则,把从端口收到的数据包转发到另一个或多个端口
Port
端口Port与物理交换机的端口概念类似,Port是OVS Bridge上创建的一个虚拟端口,每个Port都隶属于一个Bridge。Port有以下几种类型
- Normal
可以把操作系统中已有的网卡(物理网卡em1/eth0,或虚拟机的虚拟网卡tapxxx)挂载到ovs上,ovs会生成一个同名Port处理这块网卡进出的数据包。此时端口类型为Normal。
如下,主机中有一块物理网卡eth1
,把其挂载到OVS网桥br-ext
上,OVS会自动创建同名Port eth1
。
ovs-vsctl add-port br-ext eth1
#Bridge br-ext中出现Port "eth1"
有一点要注意的是,挂载到OVS上的网卡设备不支持分配IP地址,因此若之前eth1
配置有IP地址,挂载到OVS之后IP地址将不可访问。这里的网卡设备不只包括物理网卡,也包括主机上创建的虚拟网卡
- Internal
Internal类型是OVS内部创建的虚拟网卡接口,每创建一个Port,OVS会自动创建一个同名接口(Interface)挂载到新创建的Port上。接口的概念下面会提到。
下面创建一个网桥br0,并创建一个Internal类型的Port p0
ovs-vsctl add-br br0
ovs-vsctl add-port br0 p0 -- set Interface p0 type=internal
#查看网桥br0
ovs-vsctl show br0
Bridge "br0"
fail_mode: secure
Port "p0"
Interface "p0"
type: internal
Port "br0"
Interface "br0"
type: internal
可以看到有两个Port。当ovs创建一个新网桥时,默认会创建一个与网桥同名的Internal Port。在OVS中,只有”internal”类型的设备才支持配置IP地址信息,因此我们可以为br0
接口配置一个IP地址,当然p0
也可以配置IP地址
ip addr add 192.168.10.11/24 dev br0
ip link set br0 up
#添加默认路由
ip route add default via 192.168.10.1 dev br0
上面两种Port类型区别在于,Internal类型会自动创建接口(Interface),而Normal类型是把主机中已有的网卡接口添加到OVS中
- Patch
当主机中有多个ovs网桥时,可以使用Patch Port把两个网桥连起来。Patch Port总是成对出现,分别连接在两个网桥上,从一个Patch Port收到的数据包会被转发到另一个Patch Port,类似于Linux系统中的veth
可以使用ovs-vsctl
创建patch设备,如下创建两个网桥br0,br1
,然后使用一对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
#结果如下
#ovs-vsctl show
Bridge "br0"
Port "br0"
Interface "br0"
type: internal
Port "patch0"
Interface "patch0"
type: patch
options: {peer="patch1"}
Bridge "br1"
Port "br1"
Interface "br1"
type: internal
Port "patch1"
Interface "patch1"
type: patch
options: {peer="patch0"}
linux中支持创建Veth
设备对,我们可以首先创建一对Veth
设备对,然后把这两个Veth
分别添加到两个网桥上,其效果跟OVS中创建Patch Port一样,只是性能会有差别
#创建veth设备对veth-a,veth-b
ip link add veth-a type veth peer name veth-b
#使用Veth连接两个网桥
ovs-vsctl add-port br0 veth-a
ovs-vsctl add-port br1 veth-b
- Tunnel
OVS中支持添加隧道(Tunnel)端口,常见隧道技术有两种gre
或vxlan
。隧道技术是在现有的物理网络之上构建一层虚拟网络,上层应用只与虚拟网络相关,以此实现的虚拟网络比物理网络配置更加灵活,并能够实现跨主机的L2通信以及必要的租户隔离。不同隧道技术其大体思路均是将以太网报文使用隧道协议封装,然后使用底层IP网络转发封装后的数据包,其差异性在于选择和构造隧道的协议不同。Tunnel在OpenStack中用作实现大二层网络以及租户隔离,以应对公有云大规模,多租户的复杂网络环境。
OpenStack是多节点结构,同一子网的虚拟机可能被调度到不同计算节点上,因此需要有隧道技术来保证这些同子网不同节点上的虚拟机能够二层互通,就像他们连接在同一个交换机上,同时也要保证能与其它子网隔离。
OVS在计算和网络节点上建立隧道Port来连接各节点上的网桥br-int
,这样所有网络和计算节点上的br-int
互联形成了一个大的虚拟的跨所有节点的逻辑网桥(内部靠tunnel id或VNI隔离不同子网),这个逻辑网桥对虚拟机和qrouter是透明的,它们觉得自己连接到了一个大的br-int
上。从某个计算节点虚拟机发出的数据包会被封装进隧道通过底层网络传输到目的主机然后解封装。
#主机192.168.7.21上
ovs-vsctl add-br br-vxlan
#主机192.168.7.23上
ovs-vsctl add-br br-vxlan
#主机192.168.7.21上添加连接到7.23的Tunnel Port
ovs-vsctl add-port br-vxlan tun0 -- set Interface tun0 type=vxlan options:remote_ip=192.168.7.23
#主机192.168.7.23上添加连接到7.21的Tunnel Port
ovs-vsctl add-port br-vxlan tun0 -- set Interface tun0 type=vxlan options:remote_ip=192.168.7.21
OVS中的各种流(flows)
flows是OVS进行数据转发策略控制的核心数据结构,区别于Linux Bridge是个单纯基于MAC地址学习的二层交换机,flows的存在使OVS作为一款SDN交换机成为云平台网络虚拟机化主要组件
“hidden” flows
OVS在使用OpenFlow flow时,需要与OpenFlow控制器建立TCP连接,若此TCP连接不依赖OVS,即没有OVS依然可以建立连接,此时就是out-of-band control
模式,这种模式下不需要”hidden” flows
但是在in-band control
模式下,TCP连接的建立依赖OVS控制的网络,但此时OVS依赖OpenFLow控制器下发的flows才能正常工作,没法建立TCP连接也就无法下发flows,这就产生矛盾了,因此需要存在一些”hidden” flows,这些”hidden” flows保证了TCP连接能够正常建立。
“hidden” flows优先级高于OpenFlow flows,它们不需要手动设置。可以使用ovs-appctl
查看这些flows,下面命令输出内容包括OpenFlow flows
,"hidden" flows
ovs-appctl bridge/dump-flows br-int
duration=152114s, priority=0, n_packets=34008, n_bytes=3248720, priority=0,actions=NORMAL
table_id=254, duration=152114s, priority=0, n_packets=0, n_bytes=0, priority=0,reg0=0x3,actions=drop
table_id=254, duration=152114s, priority=0, n_packets=0, n_bytes=0, priority=0,reg0=0x1,actions=controller(reason=no_match)
table_id=254, duration=152114s, priority=0, n_packets=0, n_bytes=0, priority=0,reg0=0x2,actions=drop
datapath flows
datapath flows是datapath
内核模块维护的flows,由内核模块维护意味着我们并不需要去修改管理它。与OpenFlow flows不同的是,它不支持优先级,并且只有一个表,这些特点使它非常适合做缓存。与OpenFlow一样的是它支持通配符,也支持指令集(多个action)
datapath flows可以来自用户空间ovs-vswitchd
缓存,也可以是datapath内核模块进行MAC地址学习到的flows,这取决与OVS是作为SDN交换机,还是像Linux Bridge那样只是一个简单基于MAC地址学习的二层交换机
管理flows的命令行
ovs-ofctl dump-flows <br> | 打印指定网桥内的所有OpenFlow flows,可以存在多个流表(flow tables),按表顺序显示。不包括”hidden” flows。这是最常用的查看flows命令,当然这条命令对所有OpenFlow交换机都有效,不单单是OVS |
ovs-appctl bridge/dump-flows <br> | 打印指定网桥内所有OpenFlow flows,包括”hidden” flows,in-band control 模式下排错可以用到 |
ovs-dpctl dump-flows [dp] | 打印内核模块中datapath flows,
|
ovs-*工具的使用及区别
ovs-vsctl
ovs-vsctl
是一个管理或配置ovs-vswitchd
的高级命令行工具,高级是说其操作对用户友好,封装了对数据库的操作细节。它是管理OVS最常用的命令,除了配置flows之外,其它大部分操作比如Bridge/Port/Interface/Controller/Database/Vlan等都可以完成
#添加网桥br0
ovs-vsctl add-br br0
#列出所有网桥
ovs-vsctl list-br
#添加一个Port p1到网桥br0
ovs-vsctl add-port br0 p1
#查看网桥br0上所有Port
ovs-vsctl list-ports br0
#获取br0网桥的OpenFlow控制器地址,没有控制器则返回空
ovs-vsctl get-controller br0
#设置OpenFlow控制器,控制器地址为192.168.1.10,端口为6633
ovs-vsctl set-controller br0 tcp:192.168.1.10:6633
#移除controller
ovs-vsctl del-controller br0
#删除网桥br0
ovs-vsctl del-br br0
#设置端口p1的vlan tag为100
ovs-vsctl set Port p1 tag=100
#设置Port p0类型为internal
ovs-vsctl set Interface p0 type=internal
#添加vlan10端口,并设置vlan tag为10,Port类型为Internal
ovs-vsctl add-port br0 vlan10 tag=10 -- set Interface vlan10 type=internal
#添加隧道端口gre0,类型为gre,远端IP为1.2.3.4
ovs-vsctl add-port br0 gre0 -- set Interface gre0 type=gre options:remote_ip=1.2.3.4
ovsdb-tool
ovsdb-tool
是一个专门管理OVS数据库文件的工具,不常用,它不直接与ovsdb-server
进程通信
ovsdb-tool -h
ovsdb-tool: Open vSwitch database management utility
usage: ovsdb-tool [OPTIONS] COMMAND [ARG...]
create [DB [SCHEMA]] create DB with the given SCHEMA
compact [DB [DST]] compact DB in-place (or to DST)
convert [DB [SCHEMA [DST]]] convert DB to SCHEMA (to DST)
db-version [DB] report version of schema used by DB
db-cksum [DB] report checksum of schema used by DB
schema-version [SCHEMA] report SCHEMA's schema version
schema-cksum [SCHEMA] report SCHEMA's checksum
query [DB] TRNS execute read-only transaction on DB
transact [DB] TRNS execute read/write transaction on DB
[-m]... show-log [DB] print DB's log entries
The default DB is /etc/openvswitch/conf.db.
The default SCHEMA is /usr/share/openvswitch/vswitch.ovsschema.
Logging options:
-v, --verbose=[SPEC] set logging levels
-v, --verbose set maximum verbosity level
--log-file[=FILE] enable logging to specified FILE
(default: /var/log/openvswitch/ovsdb-tool.log)
Other options:
-m, --more increase show-log verbosity
-h, --help display this help message
-V, --version display version information
ovsdb-tool show-log
record 0: "Open_vSwitch" schema, version="7.3.0", cksum="2483452374 20182"
record 1: 2021-08-11 03:35:01.298 "ovs-vsctl: ovs-vsctl --no-wait -- init -- set Open_vSwitch . db-version=7.3.0"
record 2: 2021-08-11 03:35:01.320 "ovs-vsctl: ovs-vsctl --no-wait set Open_vSwitch . ovs-version=2.0.0 "external-ids:system-id=\"a842ca16-33d6-4439-aec8-c4e13ac0f5c7\"" "system-type=\"unknown\"" "system-version=\"unknown\"""
record 3: 2021-08-11 03:35:04.352 "ovs-vsctl: ovs-vsctl add-br br1"
record 4: 2021-08-11 03:35:04.373
record 5: 2021-08-11 03:35:04.374
record 6: 2021-08-11 03:35:06.263 "ovs-vsctl: ovs-vsctl add-br br2"
record 7: 2021-08-11 03:35:06.271
record 8: 2021-08-11 03:35:13.323 "ovs-vsctl: ovs-vsctl add-port br1 tap1 -- set Interface tap1 type=internal"
record 9: 2021-08-11 03:35:13.332
record 10: 2021-08-11 03:35:13.937 "ovs-vsctl: ovs-vsctl add-port br2 tap2 -- set Interface tap2 type=internal"
record 11: 2021-08-11 03:35:13.945
record 12: 2021-08-11 03:35:56.200 "ovs-vsctl: ovs-vsctl add-port br1 patch-ovs-1 -- set Interface patch-ovs-1 type=patch options:peer=patch-ovs-2"
record 13: 2021-08-11 03:35:56.202
record 14: 2021-08-11 03:35:56.977 "ovs-vsctl: ovs-vsctl add-port br2 patch-ovs-2 -- set Interface patch-ovs-2 type=patch options:peer=patch-ovs-1"
record 15: 2021-08-11 03:35:56.978
record 16: 2021-08-11 03:37:06.667 "ovs-vsctl: ovs-vsctl add-port br1 vx1 -- set interface vx1 type=vxlan options:remote_ip=172.16.0.100 options:key=100"
ovsdb-tool show-log -m
record 0: "Open_vSwitch" schema, version="7.3.0", cksum="2483452374 20182"
record 1: 2021-08-11 03:35:01.298 "ovs-vsctl: ovs-vsctl --no-wait -- init -- set Open_vSwitch . db-version=7.3.0"
table Open_vSwitch insert row b8ddda9c:
record 2: 2021-08-11 03:35:01.320 "ovs-vsctl: ovs-vsctl --no-wait set Open_vSwitch . ovs-version=2.0.0 "external-ids:system-id=\"a842ca16-33d6-4439-aec8-c4e13ac0f5c7\"" "system-type=\"unknown\"" "system-version=\"unknown\"""
table Open_vSwitch row b8ddda9c (b8ddda9c):
record 3: 2021-08-11 03:35:04.352 "ovs-vsctl: ovs-vsctl add-br br1"
table Port insert row "br1" (199a602c):
table Bridge insert row "br1" (aa6f3faf):
table Interface insert row "br1" (61bc80af):
table Open_vSwitch row b8ddda9c (b8ddda9c):
record 4: 2021-08-11 03:35:04.373
table Interface row "br1" (61bc80af):
record 5: 2021-08-11 03:35:04.374
table Open_vSwitch row b8ddda9c (b8ddda9c):
record 6: 2021-08-11 03:35:06.263 "ovs-vsctl: ovs-vsctl add-br br2"
table Port insert row "br2" (c7dc6595):
table Bridge insert row "br2" (b14f70db):
table Interface insert row "br2" (fdca67e7):
table Open_vSwitch row b8ddda9c (b8ddda9c):
ovsdb-client
ovsdb-client
是ovsdb-server
进程的命令行工具,主要是从正在运行的ovsdb-server
中查询信息,操作的是数据库相关
#列出主机上的所有databases,默认只有一个库Open_vSwitch
ovsdb-client list-dbs
#获取指定数据库的schema信息
ovsdb-client get-schema [DATABASE]
#列出指定数据库的所有表
ovsdb-client list-tables [DATABASE]
#dump指定数据库所有数据,默认dump所有table数据,如果指定table,只dump指定table数据
ovsdb-client dump [DATABASE] [TABLE]
#监控指定数据库中的指定表记录改变
ovsdb-client monitor DATABASE TABLE
ovs-ofctl
ovs-ofctl
是专门管理配置OpenFlow交换机的命令行工具,我们可以用它手动配置OVS中的OpenFlow flows,注意其不能操作datapath flows和”hidden” flows
#查看br-tun中OpenFlow flows
ovs-ofctl dump-flows br-tun
#查看br-tun端口信息
ovs-ofctl show br-tun
#添加新的flow:对于从端口p0进入交换机的数据包,如果它不包含任何VLAN tag,则自动为它添加VLAN tag 101
ovs-ofctl add-flow br0 "priority=3,in_port=100,dl_vlan=0xffff,actions=mod_vlan_vid:101,normal"
#对于从端口3进入的数据包,若其vlan tag为100,去掉其vlan tag,并从端口1发出
ovs-ofctl add-flow br0 in_port=3,dl_vlan=101,actions=strip_vlan,output:1
#添加新的flow: 修改从端口p1收到的数据包的源地址为9.181.137.1,show 查看p1端口ID为100
ovs-ofctl add-flow br0 "priority=1 idle_timeout=0,in_port=100,actions=mod_nw_src:9.181.137.1,normal"
#添加新的flow: 重定向所有的ICMP数据包到端口 p2
ovs-ofctl add-flow br0 idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:102
#删除编号为 100 的端口上的所有流表项
ovs-ofctl del-flows br0 "in_port=100"