操作概要(四步骤)

在详细进入每个操作步骤之前,会先把全面性的概要操作方法列出来,才不会有种见树不见林的感觉。

  1. 建立 OVS Bridge 名称 ovsbr0

  2. 直接对 OVS Bridge 设定一个 Static IP address ,并启动

  3. 产生两个 Containers 来当 Hosts

  4. 透过 ovs-docker/pipework 工具将 Containers attach 上 OVS Bridges

在这边会做了几张图,比较好了解 OVS 每道指令在 network stack 上发生什么作用。

Fig1. Original Network Stack

在 vagrant ssh 登入到 VM 之后,我们的 VM 上目前的 Network Stack 如图一所示,可以看到 IP Stack 直接连上 interface enp0s3。此时我们还没透过 OVS 建置任何一个 Bridge。

在透过 OVS 的指令来加入 Bridge之前,我们必须要先拿到 root 的权限,方便做 OVS 指令的操作

$ [host] vagrant ssh

$ [guest] sudo -i

$ [guest] ovs-vsctl add-br ovsbr0 #CreateOVS bridge

我们加入了一个名称 ovsbr0 的 bridge 可以透过 ifconfig [interface name] 来确认,并且透过 ovs-vsctl show 来看 bridge 的资讯

root@ubuntu-xenial:~# ifconfig ovsbr0

ovsbr0   Link encap:Ethernet  HWaddr be:86:d5💿f9:4b

BROADCAST MULTICAST  MTU:1500  Metric:1

RX packets:0 errors:0 dropped:0 overruns:0 frame:0

TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:1

RX bytes:0 (0.0 B)  TX bytes:0 (0.0B)

root@ubuntu-xenial:~# ovs-vsctl show

0a19b4a7-0279-452f-9916-b73655d5b122

Bridge"ovsbr0"

Port "ovsbr0"

Interface "ovsbr0"

type: internal

ovs_version: "2.5.2"

此时我们的 network stack 变成如图二所示,串接在 IP Stack上,但是尚未将它启动。

Fig2. Network Stack with OVS Bridge

再来设定 OVS bridge (ovsbr0) 的 IP address ,并将这个 interface 启动(注意我们刚刚只有创建一个 ovsbr0 并没有指派给他IP 也没有将它启动)。

透过 ip 指令指派 IP 和启动 ovsbr0

$ ip addr add dev ovsbr0 10.0.2.100/24 #Configure IP address

$ ip link set dev ovsbr0 up            #ovsbr0 interface up

接着要启动两个 containers 来模拟 hosts,这里有两个工具可以利用,一个是由开发者@jpetazzo 所开发的 pipework 另外一个是 OVS 官方对 docker 网路操作所释出的工具 ovs-docker 两套各有好处,这边两边都会记录,选一套操作即可。

ovs-docker [option1]

首先我们先启动两个 containers 这里用 busybox 的 image 当范例因为只是要验证网路的互通性,busybox 的 image 可以事先用 docker pull busybox 拉下来,或是直接跑 containers 它(docker) 找不到 local image 会自动去 DockerHub pull

$ docker pull busybox

$ docker run --name=container1--cap-add=NET_ADMIN --net='none' -itd busybox /bin/sh

$ docker run --name=container2--cap-add=NET_ADMIN --net='none' -itd busybox /bin/sh

几个 options 稍微介绍一下,如果不了解可以去看 docker 官方指南

• --name=container1: 指定docker 名称

• --cap-add=NET_ADMIN: 给予 network 最高权限

• --net=’none’: 停掉所有 default 的 networking (我们不用docke0的bridge)

• -itd busybox /bin/sh: 启动 busybox 的 shell 并放入背景 (detach)

透过 ovs-docker 将 container attach 上 OVS bridge, container1 容器内给一个 interface eth0 指派 IP 10.0.2.30/24 ,又或者你可以不要给指派 IP 进去容器内后再用 DHCP (busybox: udhcpc, ubuntu: dhclient)去要 IP (因为我们是用 virtualbox 所以 enp0s3 外面会有一个 gateway 在发 IP)

$ ovs-docker add-port ovsbr0 eth0 container1--ipaddress=10.0.2.30/24

$ ovs-docker add-port ovsbr0 eth0 container2--ipaddress=10.0.2.40/24

Pipework [option2]

pipwork 更加简洁,指令只要两行就可以把网路串好且 docker 开好,原则上跟上面类似 $() 内会启动 container 并且吐出 container ID 喂给 pipework

$ pipework ovsbr0 -i eth0 $(docker run--cap-add=NET_ADMIN --net='none' -itd busybox /bin/sh) 10.0.2.10/24

$ pipework ovsbr0 -i eth0 $(docker run --cap-add=NET_ADMIN--net='none' -itd busybox /bin/sh) 10.0.2.20/24

Fig3. Network Stack with OVS Bridge and Containers

当然,要开几个 Containers 就一直 copy 指令改 IP 下去,反正docker 号称 Lightweight 但还是要注意 VM 一开始所配的 RAM 跟 CPU (可以从 Vagrantfile 里做修改)

大功告成,不管用的是 Option1 还是 Option2 我们的 Network Stack 都是变成图三这个样子,我们先来看一下 OVS 在 bridge 及 port 的资讯

root@ubuntu-xenial:~# ovs-vsctl show

80dfbd0a-f6b7-47d0-89a4-ca7906a86a92

Bridge"ovsbr0"

Port "43ad433deb9684_l"

Interface "43ad433deb9684_l"

Port "ovsbr0"

Interface "ovsbr0"

type: internal

Port "veth0pl6094"

Interface "veth0pl6094"

ovs_version: "2.5.2"

我分别用了 pipework 及 ovs-docker 连上了 OVS bridge 在 list ports 可以发现他们命名的方式不同分别是 veth0pl6094 及 43ad433deb9684_l

root@ubuntu-xenial:~# ovs-vsctl list-portsovsbr0

43ad433deb9684_l

veth0pl6094

验证一下其结果透过 docker attach 指令进入任一个 container 试着 ping 另外一个 container 通了就代表 bridge 两个 containers 成功!

$ docker attach

$ ping 10.0.2.20  #ping container2

$ ping 10.0.2.100 #ping ovs

记得要离开 container 的时候先按下 Ctrl+P 然后再按 Ctrl+Q 离开(detach)容器,这样容器才不会停止。或者用 tmux 开两个 sessions 每个 session 分别放不同的 container 透过 tmux detach 的方式暂时离开切换 session

接下来你可以将 SDN Controller 接上 OVS 开始控制网路流量 (可以将 SDN Controller 放到第三个容器内跟 OVS bridge 做 OpenFlow Protocol 的连线),但是你可能会发现到 Container 内网路没办法对外连线,不过如果实验不需要外部网路,大概这样就可以开始一个 SDN 的网路环境,对外网路连线会留到下一篇做介绍。

- END -

文章来源于腾讯云开发者社区,点击查看原文