译者简介:郑敏先,就职于诺云系统(上海)有限公司。工作地点为南京的诺云研发中心。担任解决方案工程师。 本人博客为:http://blog.csdn.net/zhengmx100
本文作者:Dustin Spinhirne ,在网络行业有超过十五年的工作经验。在Rackspace做了8年的网络架构师,后又在Nicira做了2年解决方案架构师。又随着Nicira被VMware收购而进入VMware担任解决方案架构师至今。
OVS是Nicira发布的开源虚拟交换机。OVS从发布到现在一直是业界最流行的虚拟交换机。2012年VMware以12.6亿美元收购Nicira 。VMware在OVS上继续投入更多的资源,是目前OVS/OVN社区的最大贡献者。Dustin Spinhirne在Nicira和VMware担任解决方案架构师,对OVS/OVS的应用场景有着更深的理解。因此选择其博客文章进行翻译,将其引入国内供解决方案架构师,解决方案工程师,学生等人员参考。
原文链接:http://blog.spinhirne.com/2016/09/a-primer-on-ovn.html
OVN概览
OVN是由开发出OVS的那群出色的程序员们的另一个优秀的作品。这个网络虚拟化项目从2015初宣告启动, 到不久前才发布第一个正式版本OVN 2.6 。在这篇文章中,我会配置一个简单示例:在三个主机之间配置一个layer-2 overlay 网络。
首先讲一下OVN工作机制中的2种角色:
- OVN Central ——目前只能有一台主机承担这个角色。该主机将成为和外部资源(比如云管理平台)集成的API中心节点。中心节点运行着OVN 北向数据库和OVN南向数据库。OVN北向数据库,用于描述上层的逻辑网络组件,比如逻辑交换机/逻辑端口。南向数据库,其将北向数据库的逻辑网络数据格式转换为物理网络数据格式并进行存储。
- OVN Host ——所有提供虚拟机或虚拟网络的节点。OVN Host 运行着 “chassis controller” ,它上连OVN南向数据库并作为其记录的物理网络信息授权来源,下接OVS 并成为其openflow 控制器。
实验环境
本次实验中使用了3 台Ubuntu 16.04主机
OVN实验拓扑: 3 台Ubuntu 16.04主机都连接到同一个管理网络 10.127.0.0/25
主机的角色和IP地址分配如下:
- ubuntu1 10.127.0.2 – 作为OVN Central
- ubuntu2 10.127.0.3 – 作为 OVN Host
- ubuntu3 10.127.0.4 – 作为OVN Host
物理网络拓扑图如下:
为了方便测试,将会创建OVS内部接口并在网络命名空间(namespace)中使用沙盒技术来模拟虚拟机。命名空间能保证我们的OVN overlay网络与实验室物理网络完全隔离。
编译Open vSwitch 2.6
2016年9月28日社区发布了 Open vSwitch 2.6版本,可以从 这里下载。 下载包中的Ubuntu 的指导手册INSTALL.Debian.md非常不错。下面是按照这个指导手册进行实验后的总结:
首先为三台主机编译出相应的版本的OVS (注意ubuntu内核版本)
更新和安装依赖包:
1 2 |
apt-get update apt-get -y install build-essential fakeroot |
安装编译工具包:
1 2 |
apt-get -y install graphviz autoconf automake bzip2 debhelper dh-autoreconf libssl-dev libtool openssl apt-get -y install procps python-all python-twisted-conch python-zopeinterface python-six |
进行编译:
1 2 3 |
cd openvswitch-2.6.0 dpkg-checkbuilddeps `DEB_BUILD_OPTIONS='parallel=8 nocheck' fakeroot debian/rules binary` |
生成的OVS的.deb文件路径为当前路径的上一层目录。
下面会编译openvswitch-datapath内核模块
安装datapath源:
1 2 3 |
cd .. apt-get -y install module-assistant dpkg -i openvswitch-datapath-source_2.6.0-1_all.deb |
使用 module-assistant编译内核模块
1 2 |
m-a prepare m-a build openvswitch-datapath |
复制生成的deb包。你们重复这个实验时注意,版本号跟这里的输出的可能存在不同。
1 |
cp /usr/src/openvswitch-datapath-module-*.deb ./ |
把下面的这些包传到 三台Ubuntu 主机上:
- openvswitch-datapath-module-*.deb
- openvswitch-common_2.6.0-1_amd64.deb
- openvswitch-switch_2.6.0-1_amd64.deb
- ovn-common_2.6.0-1_amd64.deb
- ovn-central_2.6.0-1_amd64.deb
- ovn-host_2.6.0-1_amd64.deb
安装 Open vSwitch
在ubuntu1上安装 OVS/OVN 和依赖包:
1 2 3 4 5 |
apt-get update apt-get -y install python-six python2.7 dpkg -i openvswitch-datapath-module-*.deb dpkg -i openvswitch-common_2.6.0-1_amd64.deb openvswitch-switch_2.6.0-1_amd64.deb dpkg -i ovn-common_2.6.0-1_amd64.deb ovn-central_2.6.0-1_amd64.deb ovn-host_2.6.0-1_amd64.deb |
在ubuntu2、ubuntu3上安装 OVS/OVN 和依赖包:
1 2 3 4 5 |
apt-get update apt-get -y install python-six python2.7 dpkg -i openvswitch-datapath-module-*.deb dpkg -i openvswitch-common_2.6.0-1_amd64.deb openvswitch-switch_2.6.0-1_amd64.deb dpkg -i ovn-common_2.6.0-1_amd64.deb ovn-host_2.6.0-1_amd64.deb |
这些包安装完成后,去ubuntu1上检查下ovsdb-server进程是否监听TCP 6641,6642端口。6641端口用于监听OVN北向数据库,6642端口用于监听OVN南向数据库。下面是我执行netstat的输出结果:
1 2 3 4 5 |
root@ubuntu1:~# netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:6641 0.0.0.0:* LISTEN 1798/ovsdb-server tcp 0 0 0.0.0.0:6642 0.0.0.0:* LISTEN 1806/ovsdb-server |
如果 ovsdb-server没有使用 6641/6642 那么需要通过运行启动脚本来启动这些进程。启动脚本路径为/etc/init.d/openvswitch-switch 和 /etc/init.d/ovn-central 。
创建集成化网桥
OVS的网桥要连接到一个集成化网桥后才能够被OVN管理。通常我们给这个集成化网桥命名为“br-int”(其实可以任意命名)。首先检查环境中是否存在这个网桥,不存在的话就进行创建。
在ubuntu2、ubuntu3上:
1 |
ovs-vsctl list-br |
如果看不到“br-int” 网桥,那么需要手工创建。注意:所有运行虚拟机的节点都要存在“br-int” 网桥。
1 2 |
ovs-vsctl add-br br-int -- set Bridge br-int fail-mode=secure ovs-vsctl list-br |
“fail-mode=secure” 是一个安全特性,其让网桥丢掉所有流量。 这里用这个参数是因为我们不想在OVN控制器启用前使用网络。
将Chassis 控制器连接到中央控制器
接下来将ubuntu2/ubuntu3 上的chassis 控制器连接到ubuntu 1上的中央控制器
ubuntu2:
1 2 3 |
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:
1 2 3 |
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 |
这些命令将触发ubuntu2/ubuntu3上的OVN chassis控制器发起一个到ubuntu 1上的中央控制器的连接。我们同时指定了overlay网络封装数据平面流量的协议为 geneve 协议。
在ubuntu2/ubuntu3使用netstat校验连接是否建立:
1 2 |
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 |
创建逻辑网络
下图是本次实验的OVN逻辑网络拓扑图。
在ubuntu1 定义一台逻辑交换机和相关的逻辑端口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 创建logical switch ovn-nbctl ls-add ls1 # 创建 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 # 创建 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 |
注意,虚拟端口的名称是唯一的,不能重复。虚拟端口同时也会生成一个很长的UUID。本文使用更加人性化的端口名称来代表这些端口。我们同时定义了这些虚拟端口的mac地址。在端口安全实验(逻辑端口只允许特定的源mac地址数据包通过)将用到这些mac地址。
添加“伪虚拟机”
接下来创建连接到逻辑交换机的“伪虚拟机”。上文已经提到,我们会使用OVS内部端口和网络命名空间来模拟虚拟机。我们会给这台逻辑交换机分配172.16.255.0/24网络。
在ubuntu2上:
1 2 3 4 5 6 7 8 9 |
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上:
1 2 3 4 5 6 7 8 9 |
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 |
如果你从没接触过命名空间或者OVS,也许会对这些命令很困惑。
其实我们进行了如下几步操作:
- 给“伪虚拟机”创建了网络命名空间,
- 再给它添加一个OVS内部端口,
- 再把端口添加到命名空间,
- 在命名空间内部使用netns exec命令配置 IP地址
- 最后创建一个OVS接口,并给这个接口指定一个external_id 。(这个ID是之前创建的逻辑接口的名称或UUID)
最后一步执行完成后,OVS就会通知OVN有逻辑端口上线了。然后,OVN向下游主机的本地chassis 控制器发送指令,同时 OVN也会将网络流量传递给上游的OVS。
注意,我已明确地给这些接口设置了与OVN逻辑交换机中相同的mac地址。这非常重要。如果mac地址没有映射正确,逻辑网络就不会正常工作。请记住,我在这里没有使用常规流程。正常情况下,你不会更改虚拟机的MAC地址,而是将现有的/已知的mac地址传递入OVN / OVS。 我为了演示方便才手动设置IP/mac地址。
测试网络连通性
在 ubuntu1 上,我们使用ovn-sbctl验证逻辑网络配置 :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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主机的端口绑定是否正常。
为了测试网络连通性,我们只需从vm1的命名空间发起ping:
1 2 3 4 5 |
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 |
添加和迁移一个第三方 “虚拟机”
让我们添加一个第三方“虚拟机”,然后在主机之间迁移它。 首先,在ubuntu1上使用ovn-nbctl定义其逻辑端口:
1 2 3 4 5 |
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上给这台虚拟机创建接口:
1 2 3 4 5 6 7 8 9 |
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测试网络:
1 2 3 4 5 |
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 |
注意ubuntu1上的OVN南向数据库配置。 我们看到ubuntu2有2个注册的端口绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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”命名空间,删除其在br-int上的端口,然后在ubuntu3上重新进行配置。
在ubuntu2上:
1 2 3 |
ip netns del vm3 ovs-vsctl --if-exists --with-iface del-port br-int vm3 ovs-vsctl list-ports br-int |
在ubuntu3上:
1 2 3 4 5 6 7 |
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 |
测试网络连通性:
1 2 3 4 5 |
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南向数据库配置。 我们看到端口绑定已经改变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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" |
清理环境
为了让环境用于后面的其他实验,我们在退出前需要清理环境。
ubuntu1:
1 2 |
#删除逻辑交换机及其端口 ovn-nbctl ls-del ls1 |
ubuntu2:
1 2 3 |
# 删除 vm1 ip netns del vm1 ovs-vsctl --if-exists --with-iface del-port br-int vm1 |
ubuntu3:
1 2 3 4 5 6 |
# delete vm2 和 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 |
结语
如您所见,使用OVN创建二层overlay网络相对简单。 在下一篇文章中,我们将通过引入OVN逻辑路由器来构建一个OVN基本的三层网络。