overview

在本文中,我们将在三个host之间创建一个简单的二层overlay network。首先,我们来简单看一下,整个系统是怎么工作的。OVN基于分布式的control plane,其中各个组件分布在network的各个节点中。在OVN中包含了如下两种角色:

  • OVN Central --- 现在该角色仅包含一个节点,该节点用于处理和cloud management platform等其他外部资源进行集成的API。并且在该节点中包含了OVN northbound database,用于存储追踪上层的逻辑结构,例如logical switches/port,以及OVN southbound database用于确定如何将ovn-northdb中的逻辑结构映射到物理世界中
  • OVN Host -- 该角色存在于所有节点中,其中包含了virtual networking end points,例如虚拟机。OVN Host中包含一个"chassis controller",它往上和ovn-soutdb连接,因为其中包含了权威的物理网络信息,向下作为一个openflow controller和ovs连接。

The Lab

OVN实验由三个连接到同一个子网(10.127.0.0/25)的ubuntu 17.04 server组成。每台主机以及它们的IP地址如下所示:

  • ubuntu1 10.127.0.2 --- 作为OVN Central
  • ubuntu2 10.127.0.3 --- 作为OVN Host
  • ubuntu3 10.127.0.4 --- 作为OVN Host

为了实验的简单起见,我们将通过创建ovs internal interfaces,并且将它们加入一个network namespace来模拟虚拟机负载。namespace会保证我们的OVN overlay network和lab network完全隔离。

Installing Open vSwitch

和原文自行编译安装ovs不同的是,为了简单起见,我们使用了ubuntu 17.04,它的源里面已经包含了ovs 2.6.1,因此我们直接用apt-get安装即可,具体指令如下:

sudo apt-get install openvswitch-common openvswitch-switch

// OVN Central执行如下指令
sudo apt-get install ovn-common ovn-central ovn-host // OVN Host执行如下指令
sudo apt-get install ovn-common ovn-host

  

Creating the Integration Bridge

OVN会负责管理一个由ovs创建的bridge,所有希望加入OVN logical switch的设备都必须加入到该bridge中。尽管我们可以给该bridge取任意名字,但是一般我们都将它命名为"br-int"。首先我们要确认该bridge是否存在,如果有必要的话,对它进行创建。

在ubuntu2/ubuntu3执行如下命令

ovs-vsctl list-br

  

如果没有在输出中看到"br-int",那么我们必须手动创建该bridge。记住,该integration bridge必须存在在所有包含虚拟机的节点中。

ovs-vsctl add-br br-int -- set Bridge br-int fail-mode=secure
ovs-vsctl list-br

  

其中的"fail-mode=secure"是一个安全特性,它用于配置bridge,让它默认丢弃所有的流量。这非常重要,因为我们不想要integration bridge的租户能相互沟通,如果我们的flow因为一些原因被删除了或者我们在OVN controller启动前就将租户插入到了bridge中。

Connecting the Chassis Controllers to the Central Controller

接下来我们要做的是将ubuntu2/ubuntu3中的chassis controllers和ubuntu1中的central controller连接起来。

ubuntu2:

ovs-vsctl set open . external-ids:ovn-remote=tcp:10.127.0.2:6642
ovs-vsctl set open . external-ids:ovn-encap-type=geneve
ovs-vsctl set open . external-ids:ovn-encap-ip=10.127.0.3

  

ubuntu3:

ovs-vsctl set open . external-ids:ovn-remote=tcp:10.127.0.2:6642
ovs-vsctl set open . external-ids:ovn-encap-type=geneve
ovs-vsctl set open . external-ids:ovn-encap-ip=10.127.0.4

  

上述命令会触发每个节点上的OVN chassis controller和ubuntu1中的OVN Central host进行连接。并且我们指定了,我们的overlay network使用geneve协议来加密数据平面流量。

我们可以使用netstat命令来确定连接是否完成。在ubuntu3的输出应当如下所示:

root@ubuntu3:~# netstat -antp | grep 10.127.0.2
tcp 0 0 10.127.0.4:39256 10.127.0.2:6642 ESTABLISHED 3072/ovn-controller

  

Defining the Logical Network

下图展示了lab中创建的各个OVN逻辑组件

首先我们定义一个名为"ls1"的OVN logical switch以及和它相连的logical port。在ubuntu1执行如下命令:

# create the logical switch
ovn-nbctl ls-add ls1 # create logical port
ovn-nbctl lsp-add ls1 ls1-vm1
ovn-nbctl lsp-set-addresses ls1-vm1 02:ac:10:ff:00:11
ovn-nbctl lsp-set-port-security ls1-vm1 02:ac:10:ff:00:11 # create logical port
ovn-nbctl lsp-add ls1 ls1-vm2
ovn-nbctl lsp-set-addresses ls1-vm2 02:ac:10:ff:00:22
ovn-nbctl lsp-set-port-security ls1-vm2 02:ac:10:ff:00:22 ovn-nbctl show

  

在每一个命令集中我们都创建了一个命名唯一的logical port。通常这些logical port都会以UUID进行命名,从而确保唯一性,但是我们使用了对人类更加友好的命名方式。同时我们还定义了和每个logical port相关联的mac地址,而且我们还更近一步,利用port security对logical port进行了锁定(从而从该logical port只能使用我们提供的mac地址)。

Addint "Fake" Virtual Machines

接下来我们将创建用于连接到logical switch的"虚拟机"。如上文所述,我们将使用OVS internal ports和network namespace来模拟虚拟机,并且使用172.16.255.0/24来作为我们的logical switch的地址空间

ubuntu2:

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 02:ac:10:ff:00:11
ip netns exec vm1 ip addr add 172.16.255.11/24 dev vm1
ip netns exec vm1 ip link set vm1 up
ovs-vsctl set Interface vm1 external_ids:iface-id=ls1-vm1 ip netns exec vm1 ip addr show

  

ubuntu3:

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 02:ac:10:ff:00:22
ip netns exec vm2 ip addr add 172.16.255.22/24 dev vm2
ip netns exec vm2 ip link set vm2 up
ovs-vsctl set Interface vm2 external_ids:iface-id=ls1-vm2 ip netns exec vm2 ip addr show

  

如果你对namespace或者ovs不熟悉,那么上述命令可能显得有点让人疑惑。简单地说,我们创建了一个network namespace作为我们的fake VM,创建了一个internal OVS port,并将该port加入到namespace中,通过netns exec命令对其进行配置,包括IP,mac地址等,最后创建一个OVS interface,其中external_id设置为我们在OVN中定义的logical port的ID。这最后一步触发了OVS通知OVN,一个新的logical port已将上线了。OVN在接到通知后,会将指令传输给对应的节点的logical chassis controller,同时chassis controller会将network flows压入OVS。

需要注意的是,在这里我显式设置了这些interface的mac地址来和我们在OVN logical switch中的配置相匹配。这非常重要,因为如果mac地址不匹配的话,logical network将不能工作。事实上,我故意把工作流搞反了一点。其实你并不会去改变虚拟机的mac地址,而是将一个已经存在的,已知的mac存入OVN/OVS。而我这样做的目的是为了让mac/IP更加容易演示。

Verifying and Testing Connectivity

在ubuntu1中我们可以通过ovn-sbctl来确定logical network configuration。输出如下所示:

root@ubuntu1:~# ovn-sbctl show
Chassis "239f2c28-90ff-468f-a701-655585c630bf"
hostname: "ubuntu3"
Encap geneve
ip: "10.127.0.4"
options: {csum="true"}
Port_Binding "ls1-vm2"
Chassis "517d558e-158a-4cb2-8870-283e9d39685e"
hostname: "ubuntu2"
Encap geneve
ip: "10.127.0.3"
options: {csum="true"}
Port_Binding "ls1-vm1"

  

注意每个OVN Host相关联的port bindings。为了测试连接,我们在vm1这个namespace中启动一个ping命令。输出结果如下所示:

root@ubuntu2:~# ip netns exec vm1 ping 172.16.255.22
PING 172.16.255.22 (172.16.255.22) 56(84) bytes of data.
64 bytes from 172.16.255.22: icmp_seq=1 ttl=64 time=1.60 ms
64 bytes from 172.16.255.22: icmp_seq=2 ttl=64 time=0.638 ms
64 bytes from 172.16.255.22: icmp_seq=3 ttl=64 time=0.344 ms

  

Adding a 3rd "VM" and Migrating It

接着我们加入第三个"虚拟机",并且模拟虚拟机在各个节点的迁移。首先,通过ovn-nbclt在ubuntu1中定义logical port

ovn-nbctl lsp-add ls1 ls1-vm3
ovn-nbctl lsp-set-addresses ls1-vm3 02:ac:10:ff:00:33
ovn-nbctl lsp-set-port-security ls1-vm3 02:ac:10:ff:00:33 ovn-nbctl show

  

接着,在ubuntu2上为该虚拟机创建interface

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 02:ac:10:ff:00:33
ip netns exec vm3 ip addr add 172.16.255.33/24 dev vm3
ip netns exec vm3 ip link set vm3 up
ovs-vsctl set Interface vm3 external_ids:iface-id=ls1-vm3 ip netns exec vm3 ip addr show

  

测试vm3的连通性

root@ubuntu2:~# ip netns exec vm3 ping 172.16.255.22
PING 172.16.255.22 (172.16.255.22) 56(84) bytes of data.
64 bytes from 172.16.255.22: icmp_seq=1 ttl=64 time=2.04 ms
64 bytes from 172.16.255.22: icmp_seq=2 ttl=64 time=0.337 ms
64 bytes from 172.16.255.22: icmp_seq=3 ttl=64 time=0.536 ms

  

注意OVN southbound DB中的配置。我们可以看到ubuntu2由两个已经注册的port bindings

root@ubuntu1:~# ovn-sbctl show
Chassis "239f2c28-90ff-468f-a701-655585c630bf"
hostname: "ubuntu3"
Encap geneve
ip: "10.127.0.4"
options: {csum="true"}
Port_Binding "ls1-vm2"
Chassis "517d558e-158a-4cb2-8870-283e9d39685e"
hostname: "ubuntu2"
Encap geneve
ip: "10.127.0.3"
options: {csum="true"}
Port_Binding "ls1-vm3"
Port_Binding "ls1-vm1"

  

为了模拟vm3的迁移,我们先在ubuntu2中删除"vm3"这个namespace,并且将它的port从br-int上移除,最后在ubuntu3上重新进行创建。

ubuntu2:

ip netns del vm3
ovs-vsctl --if-exists --with-iface del-port br-int vm3
ovs-vsctl list-ports br-int

  

ubuntu3:

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 02:ac:10:ff:00:33
ip netns exec vm3 ip addr add 172.16.255.33/24 dev vm3
ip netns exec vm3 ip link set vm3 up
ovs-vsctl set Interface vm3 external_ids:iface-id=ls1-vm3

  

测试连接:

root@ubuntu3:~# ip netns exec vm3 ping 172.16.255.11
PING 172.16.255.11 (172.16.255.11) 56(84) bytes of data.
64 bytes from 172.16.255.11: icmp_seq=1 ttl=64 time=1.44 ms
64 bytes from 172.16.255.11: icmp_seq=2 ttl=64 time=0.407 ms
64 bytes from 172.16.255.11: icmp_seq=3 ttl=64 time=0.395 ms

  

再一次,我们在ubuntu1中观察OVN southbound DB configuration。我们可以看到port binding已经发生了改变。

root@ubuntu1:~# ovn-sbctl show
Chassis "239f2c28-90ff-468f-a701-655585c630bf"
hostname: "ubuntu3"
Encap geneve
ip: "10.127.0.4"
options: {csum="true"}
Port_Binding "ls1-vm2"
Port_Binding "ls1-vm3"
Chassis "517d558e-158a-4cb2-8870-283e9d39685e"
hostname: "ubuntu2"
Encap geneve
ip: "10.127.0.3"
options: {csum="true"}
Port_Binding "ls1-vm1"

  

Cleaning Up

在退出前,我们先对环境进行清理

ubuntu1:

# delete the logical switch and its ports
ovn-nbctl ls-del ls1

  

ubuntu2:

# delete vm1
ip netns del vm1
ovs-vsctl --if-exists --with-iface del-port br-int vm1

  

ubuntu3:

# delete vm2 and vm3
ip netns del vm2
ovs-vsctl --if-exists --with-iface del-port br-int vm2 ip netns del vm3
ovs-vsctl --if-exists --with-iface del-port br-int vm3

  

Final Words

我们可以看到,使用OVN创建一个二层的overlay network是相对比较直接的。在下一篇文章中,我将通过介绍OVN logical router来讨论OVN 三层网络

最新文章

  1. PHP中json_encode后中文乱码的解决方案
  2. 用jquery实现遮罩层
  3. 如何切换android的横屏与竖屏?
  4. Spring多数据源的动态切换
  5. 手势识别官方教程(3)识别移动手势(识别速度用VelocityTracker)
  6. Visual Studio 2013 Use HTTPS (SSL) On Web Application Projects
  7. 2017年9月3日 Spring及Mybatis中连接数据库的不同方式
  8. java集合系列——List集合之ArrayList介绍(二)
  9. Nginx安装及配置
  10. 记一个常见的ms sql server中取第N条记录的方法
  11. Python3基础 list reverse 反转列表
  12. 【资料收集】QT学习资料
  13. sqlserver统计日志数目
  14. Spring MVC post请求乱码解决
  15. 安卓自动生成代码插件-Android code Generator(转)
  16. linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程
  17. [翻译] BKZoomView
  18. 设置vim颜色方案
  19. PHP学习笔记之数组游标操作
  20. [CC-SEABUB]Sereja and Bubble Sort

热门文章

  1. python之字符串处理
  2. BootCamp支持软件6
  3. iOS关于版本更新的问题
  4. java.lang.NoSuchMethodError: org.apache.spark.util.ThreadUtils$.newDae
  5. Scala学习笔记(一)编程基础
  6. js 控制按钮点击后不可用
  7. PHP输出javascript,alert中文乱码解决办法
  8. jQuery DataTables添加自定义多个搜索条件
  9. js 代码风格(2)
  10. 【Raspberry Pi】定时运行python程序读温湿度传感器数据&发邮件