ovn 架构介绍

ovn是什么就不多说了,网上有很多介绍的文章。这里主要是学习下ovn的架构,并通过实践认识一下ovn。
ovn代码最初是在ovs源码下,但是从版本v2.13.0开始,ovn被移除ovs,有了独立的仓库,地址为 https://github.com/ovn-org/ovn

ovn架构图如下,是从ovn-architecture截图的

ovn 架构介绍_第1张图片

image.png


下面这几个组件运行在集群的中心节点,对于openstack来说,其运行在controller节点上。对于k8s来说,运行在master节点上。

CMS(cloud management system): OVN的最终用户,比如openstack,OVN最初就是被设计给openstack用的。

OVN/CMS plugin: CMS的一部分,对于openstack来说,就是neutron plugin,用来和OVN交互,主要目的就是将逻辑网络配置转换成OVN理解的数据,并写到nbdb中。

OVN Northbound DB: 保存CMS plugin下发的配置,数据库格式可以参考 [ovn-nb](https://man7.org/linux/man-pages/man5/ovn-nb.5.html)。它只有两个客户端:图中它上面的CMS plugin和它下面的ovn-northd。其实还有个命令行公司 ovn-nbctl 也可以直接操作它。

ovn-northd: 同时连接到OVN Northbound DB:和OVN Southbound DB。用来将OVN Northbound DB中的数据进行转换并保存到OVN Southbound DB。

OVN Southbound DB: 系统的核心, 数据库格式可以参考[ovn-sb](https://man7.org/linux/man-pages/man8/ovn-northd.8.html)。它也有两个客户端: 向上的ovn-northd和下面的运行在每个hypervisor上的ovn-controller。

ovn-nbctl和ovnsbctl:这是两个命令行工具,分别用来查看/操作Northbound DB和Southbound DB。

下面的组件运行在每个hypervisor上,对于openstack来说,其运行在compute节点上。对于k8s来说,运行在worker节点上。当然中心节点也可以是hypervisor。

ovn-controller:相当于OVN在每个hypervisor上的agent。北向它连接到OVN Southbound Database学习最新的配置转换成openflow流表,南向它连接到ovs-vswitchd下发转换后的流表,同时也连接到ovsdb-server获取它需要的配置信息。

ovs-vswitchd和ovsdb-server: 是ovs的两个后台进程,就不在多说了。

实践

下面通过源码安装ovn,并且创建一个logical switch,使用namespace模拟创建三个VM,连接到这个switch上,实现ping通的功能。
安装
可以参考官网进行安装,但是貌似少了几个步骤,废了半天劲,查看了源码才知道少了哪些步骤。

编译并安装,需要在中心节点和hypervisor上都执行。

//下载ovn源码
$ git clone https://github.com/ovn-org/ovn.git

//ovn依赖ovs的lib,所以需要先编译ovs
$ git submodule update --init
$ cd ovs
$ ./boot.sh
$ ./configure
$ make
//实验也需要ovs,顺便就安装一下ovs
$ make install
$ cd ..

//编译并安装ovn
$ ./boot.sh
$ ./configure
$ make
$ make install

ovs和ovn都安装后,启动他们。
先启动ovs的两个后台进程,只需要在hypervisor上执行。

//首先清理下之前启动ovs
$ ovs-appctl -t ovs-vswitchd exit
$ ovs-appctl -t ovsdb-server exit
$ rm /usr/local/etc/openvswitch/conf.db

//创建需要的目录
$ mkdir -p /usr/local/etc/openvswitch
$ mkdir -p /usr/local/var/run/openvswitch
$ mkdir -p /usr/local/var/log/openvswitch

//创建数据库
$ ovsdb-tool create /usr/local/etc/openvswitch/conf.db  \
     /usr/local/share/openvswitch/vswitch.ovsschema

//启动ovsdb-server
$ ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \
  --remote=db:Open_vSwitch,Open_vSwitch,manager_options \
  --private-key=db:Open_vSwitch,SSL,private_key \
  --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --pidfile --detach

$ ovs-vsctl --no-wait init

//启动ovs-vswitchd
$ export DB_SOCK=/usr/local/var/run/openvswitch/db.sock
$ ovs-vswitchd unix:$DB_SOCK --pidfile --detach --log-file=/usr/local/var/log/openvswitch/ovs-vswitchd.log

接下来启动ovn,只需要在中心节点启动。可以使用ovn自带的脚本ovn-ctl启动,脚本内部会将依赖的数据库和进程创建好。也可以参考官网步骤手动创建所有的东西。

//添加ovn-ctl路径
$ export PATH=$PATH:/usr/local/share/ovn/scripts
//启动 ovn-northd,会自动创建数据库,只需要在中心节点上执行
$ ovn-ctl start_northd
 * /usr/local/etc/ovn/ovnnb_db.db does not exist
 * Creating empty database /usr/local/etc/ovn/ovnnb_db.db
 * Starting ovsdb-nb
 * /usr/local/etc/ovn/ovnsb_db.db does not exist
 * Creating empty database /usr/local/etc/ovn/ovnsb_db.db
 * Starting ovsdb-sb
 * Starting ovn-northd

//启动 ovn-controller,只需要在hypervisor上执行
$ ovn-ctl start_controller
 * Starting ovn-controller

官网的步骤只到这里就结束了,我们看一下现在的情况

//会自动生成一个br-int网桥,这个是ovn-controller启动创建的
$ ovs-vsctl show
a891c32e-dec1-4168-8e17-1516fa55341b
    Bridge br-int
        fail_mode: secure
        Port br-int
            Interface br-int
                type: internal

//ovn-sbctl show 应该可以显示出hypervisor的信息,但是没有任何信息
$ ovn-sbctl show

//查看一些启动的ovn进程
$ ps -ef | grep ovn
//启动一个ovsdb-server进程,用来管理nbdb,并且监听socket /usr/local/var/run/ovn/ovnnb_db.sock
root     11529 11528  0 20:26 ?        00:00:00 ovsdb-server -vconsole:off -vfile:info --log-file=/usr/local/var/log/ovn/ovsdb-server-nb.log --remote=punix:/usr/local/var/run/ovn/ovnnb_db.sock --pidfile=/usr/local/var/run/ovn/ovnnb_db.pid --unixctl=/usr/local/var/run/ovn/ovnnb_db.ctl --detach --monitor --remote=db:OVN_Northbound,NB_Global,connections --private-key=db:OVN_Northbound,SSL,private_key --certificate=db:OVN_Northbound,SSL,certificate --ca-cert=db:OVN_Northbound,SSL,ca_cert --ssl-protocols=db:OVN_Northbound,SSL,ssl_protocols --ssl-ciphers=db:OVN_Northbound,SSL,ssl_ciphers /usr/local/etc/ovn/ovnnb_db.db
//启动一个ovsdb-server进程,用来管理sbdb,并且监听socket /usr/local/var/run/ovn/ovnsb_db.sock
root     11545 11544  0 20:26 ?        00:00:00 ovsdb-server -vconsole:off -vfile:info --log-file=/usr/local/var/log/ovn/ovsdb-server-sb.log --remote=punix:/usr/local/var/run/ovn/ovnsb_db.sock --pidfile=/usr/local/var/run/ovn/ovnsb_db.pid --unixctl=/usr/local/var/run/ovn/ovnsb_db.ctl --detach --monitor --remote=db:OVN_Southbound,SB_Global,connections --private-key=db:OVN_Southbound,SSL,private_key --certificate=db:OVN_Southbound,SSL,certificate --ca-cert=db:OVN_Southbound,SSL,ca_cert --ssl-protocols=db:OVN_Southbound,SSL,ssl_protocols --ssl-ciphers=db:OVN_Southbound,SSL,ssl_ciphers /usr/local/etc/ovn/ovnsb_db.db
root     11553     1  0 20:26 ?        00:00:00 ovn-northd: monitoring pid 11554 (healthy)
//启动ovn-northd进程,可看到它已经通过ovnnb_db.sock和ovnsb_db.sock连接到了两个数据库
root     11554 11553  0 20:26 ?        00:00:00 ovn-northd -vconsole:emer -vsyslog:err -vfile:info --ovnnb-db=unix:/usr/local/var/run/ovn/ovnnb_db.sock --ovnsb-db=unix:/usr/local/var/run/ovn/ovnsb_db.sock --no-chdir --log-file=/usr/local/var/log/ovn/ovn-northd.log --pidfile=/usr/local/var/run/ovn/ovn-northd.pid --detach --monitor
root     11695     1  0 20:26 ?        00:00:00 ovn-controller: monitoring pid 11696 (healthy)
//启动ovn-controller进程,它已经通过db.sock连接到ovs的db
root     11696 11695  0 20:26 ?        00:00:00 ovn-controller unix:/usr/local/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --no-chdir --log-file=/usr/local/var/log/ovn/ovn-controller.log --pidfile=/usr/local/var/run/ovn/ovn-controller.pid --detach --monitor

通过上面的观察发现两个问题,一个是ovn-sbctl show显示不出hypervisor的信息,另一个是ovn-controller应该连接到sbdb的,但是没有任何信息能显示连接成功。
经过搜索和源码分析,这两个问题其实是同一个原因,即ovn-controller没有成功连接到sbdb。解决方法如下

//在中心节点上添加如下两条命令,其中6641端口用于监听OVN北向数据库,6642端口用于监听OVN南向数据库。
//第一个在实验环境不加也可以,因为它主要是给CMS plugin用的,我们这里直接通过ovn-nbctl操作数据库即可。
$ ovn-nbctl set-connection ptcp:6641:192.168.122.20
$ ovn-sbctl set-connection ptcp:6642:192.168.122.20

//查看两个监听端口
$ netstat -nap | grep ovsdb-server
tcp        0      0 192.168.122.20:6641     0.0.0.0:*               LISTEN      14976/ovsdb-server
tcp        0      0 192.168.122.20:6642     0.0.0.0:*               LISTEN      14996/ovsdb-server

//sbdb有了监听端口号6642后,ovn-controller才可以去连接sbnb。
//ovn-controller通过ovsdb的字段获取sbdb的连接信息。
//设置 Open_vSwitch table的 external-ids 字段,在所有hypervisor上执行下面命令
$ ovs-vsctl set open . external-ids:ovn-remote=tcp:192.168.122.20:6642

//在中心节点上执行下面命令
$ ovs-vsctl set open . external-ids:system-id=master
$ ovs-vsctl set open . external-ids:ovn-encap-type=geneve
$ ovs-vsctl set open . external-ids:ovn-encap-ip=192.168.122.20

//在hypervisor节点上执行下面命令
ovs-vsctl set open . external-ids:ovn-remote=tcp:192.168.122.20:6642
ovs-vsctl set open . external-ids:system-id=node1
ovs-vsctl set open . external-ids:ovn-encap-type=geneve
//上报自己的ip,相当于向集群报告其他节点如何连接到自己
ovs-vsctl set open . external-ids:ovn-encap-ip=192.168.122.21

//可看到ovn-controller连接到了sbdb的6442端口
$ netstat -nap | grep 6642
tcp        0      0 192.168.122.20:6642     0.0.0.0:*               LISTEN      14996/ovsdb-server
tcp        0      0 192.168.122.20:6642     192.168.122.20:49516    ESTABLISHED 14996/ovsdb-server
tcp        0      0 192.168.122.20:49516    192.168.122.20:6642     ESTABLISHED 19322/ovn-controlle

再次查看,可以看到两个hypervisor都连接到了sbdb。在ovn里使用chassis表示一个hypervisor。

$ ovn-sbctl show
Chassis node1
    hostname: node1
    Encap geneve
        ip: "192.168.122.21"
        options: {csum="true"}
Chassis master
    hostname: master
    Encap geneve
        ip: "192.168.122.20"
        options: {csum="true"}

验证
在两个节点上安装ovn成功后,接下来进行验证,环境信息如下

master  192.168.122.20 既是中心节点,也是hypervisor
node1    192.168.122.21 hypervisor

在中心节点上执行如下命令,创建一个ls和三个lsp

//创建 logical switch ls1
ovn-nbctl ls-add ls1

//添加第一个 logical port ls1-vm1
ovn-nbctl lsp-add ls1 ls1-vm1
ovn-nbctl lsp-set-addresses ls1-vm1 00:00:00:00:00:01
ovn-nbctl lsp-set-port-security ls1-vm1 00:00:00:00:00:01

//添加第二个 logical port ls1-vm2
ovn-nbctl lsp-add ls1 ls1-vm2
ovn-nbctl lsp-set-addresses ls1-vm2 00:00:00:00:00:02
ovn-nbctl lsp-set-port-security ls1-vm2 00:00:00:00:00:02

//添加第三个 logical port ls1-vm3
ovn-nbctl lsp-add ls1 ls1-vm3
ovn-nbctl lsp-set-addresses ls1-vm3 00:00:00:00:00:03
ovn-nbctl lsp-set-port-security ls1-vm3 00:00:00:00:00:03

//显示nbdb中的信息
$ ovn-nbctl show
switch 6e5f7249-5501-4e34-8b63-4aa35d2ee6be (ls1)
    port ls1-vm1
        addresses: ["00:00:00:00:00:01"]
    port ls1-vm3
        addresses: ["00:00:00:00:00:03"]
    port ls1-vm2
        addresses: ["00:00:00:00:00:02"]

接下来分别创建三个namespace,模拟三个vm,分别添加一个internal类型的ovs端口作为vm的接口,并配置同网段ip

//在master上创建vm1 namespace
ip netns add vm1
ovs-vsctl add-port br-int vm1 -- set interface vm1 type=internal
ip link set vm1 netns vm1
ip netns exec vm1 ip link set vm1 address 00:00:00:00:00:01
ip netns exec vm1 ip addr add 10.10.10.1/24 dev vm1
ip netns exec vm1 ip link set vm1 up
//ovn-controller通过观察iface-id自动判断是否有需要的接口创建
ovs-vsctl set Interface vm1 external_ids:iface-id=ls1-vm1
 
//在node1上创建vm2 namespace
ip netns add vm2
ovs-vsctl add-port br-int vm2 -- set interface vm2 type=internal
ip link set vm2 netns vm2
ip netns exec vm2 ip link set vm2 address 00:00:00:00:00:02
ip netns exec vm2 ip addr add 10.10.10.2/24 dev vm2
ip netns exec vm2 ip link set vm2 up
ovs-vsctl set Interface vm2 external_ids:iface-id=ls1-vm2
 
//在master上创建vm3 namespace
ip netns add vm3
ovs-vsctl add-port br-int vm3 -- set interface vm3 type=internal
ip link set vm3 netns vm3
ip netns exec vm3 ip link set vm3 address 00:00:00:00:00:03
ip netns exec vm3 ip addr add 10.10.10.3/24 dev vm3
ip netns exec vm3 ip link set vm3 up
ovs-vsctl set Interface vm3 external_ids:iface-id=ls1-vm3

最后通过sbctl命令可看到,每个chassis下绑定了多少个接口。

$ ovn-sbctl show
Chassis node1
    hostname: node1
    Encap geneve
        ip: "192.168.122.21"
        options: {csum="true"}
    Port_Binding ls1-vm2
Chassis master
    hostname: master
    Encap geneve
        ip: "192.168.122.20"
        options: {csum="true"}
    Port_Binding ls1-vm1
    Port_Binding ls1-vm3

vm1也可以ping通vm2和vm3

$ ip netns exec vm1 ping 10.10.10.2
PING 10.10.10.2 (10.10.10.2) 56(84) bytes of data.
64 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=6.65 ms
^C
--- 10.10.10.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 6.652/6.652/6.652/0.000 ms
$ ip netns exec vm1 ping 10.10.10.3
PING 10.10.10.3 (10.10.10.3) 56(84) bytes of data.
64 bytes from 10.10.10.3: icmp_seq=1 ttl=64 time=0.939 ms
^C
--- 10.10.10.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.939/0.939/0.939/0.000 ms

参考

以下是ovn官网最新的文档,可以结合代码查看
ovn-architecture
https://www.ovn.org/support/dist-docs/ovn-architecture.7.txt

ovn-northd
https://www.ovn.org/support/dist-docs/ovn-northd.8.txt

ovn-controller
https://www.ovn.org/support/dist-docs/ovn-controller.8.txt

vtep
https://www.ovn.org/support/dist-docs/ovn-controller-vtep.8.txt

ovn-ctl
https://www.ovn.org/support/dist-docs/ovn-ctl.8.txt

ovn-trace
https://www.ovn.org/support/dist-docs/ovn-trace.8.txt

ovn-sb
https://www.ovn.org/support/dist-docs/ovn-sb.5.txt

ovn-nb
https://www.ovn.org/support/dist-docs/ovn-nb.5.txt

ovn-sbctl
https://www.ovn.org/support/dist-docs/ovn-sbctl.8.txt

ovn-nbctl
https://www.ovn.org/support/dist-docs/ovn-nbctl.8.txt

install guide
https://github.com/ovn-org/ovn/blob/master/Documentation/intro/install/general.rst

也可参考:ovn 架构介绍 - 简书 

你可能感兴趣的:(OVN,架构,ovn)