Docker Networking 章节3. 构建你的第一个Docker网络

这个章节讨论了Docker网络实际的例子,它跨多个主机上多个容器和多个主机,我们也讨论下面的内容:

  • Pipework方案介绍
  • 跨主机的多个容器
  • 面向扩展网络--介绍Open vSwitch
  • 覆盖网络--Flannel
  • Docker网络方案比较

介绍Pipework网络方案

Pipework允许你在任意复杂的场景中将容器连接起来。

实际场景中,它创建一个合法的Linux网桥,在容器中增加一个新的接口,把接口附加到网桥上;容器获得一个能相互通信的网络段。

Pipework是一个shell脚本并且安装很简单:

#sudo wget -O /usr/local/bin/pipework
https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework && sudo
chmod +x /usr/local/bin/pipework

下图展示了使用Pipework方案容器之间的通信:

首先,创建两个容器:

现在,使用Pipework将它们连接起来:

#sudo pipework brpipe c1 192.168.1.1/24

这个命令在宿主机上创建了一个网桥brpripe。在容器c1中增加了eth1接口,设置IP地址是192.168.1.1并且添加接口到网桥上,如下所示:

#sudo pipework brpipe c2 192.168.1.2/24

因为已经存在网桥brpipe,所以这个命令将不会再次创建。它将增加一个eth1接口到容器C2上并且添加到网桥上,如下所示:

现在这容器是北联系起来了并且能相互ping通,就像他们在相同的子网192.168.1.0/24中。Pipework提供了给容器增加静态IP的优势。

给容器采用Weave网络方案

Weave创建了一个虚拟的网络,它能跨主机连接Docke容器就像他们全部被连接在一个交换机上。这个Weave路由器本身作为一个Docker容器运行同时它能加密路由流量以便在Internet网络中传输。服务由Weave网络中的应用程序容器提供可以访问互联网,不管这些容器在哪里运行。

使用以下代码安装Weave:

#sudo curl -L git.io/weave -o /usr/local/bin/weave
#sudo chmod a+x /usr/local/bin/weave

下面展示了使用Weave网络容器跨主机通信:

在 $HOST1上,我们运行命令:

# weave launch
# eval $(weave proxy-env)
# docker run --name c1 -ti ubuntu

在$HOST2上,我们重复相同的步骤:

# weave launch $HOST1
# eval $(weave proxy-env)
# docker run --name c2 -ti ubuntu

在$HOST1启动的容器中,执行命令可以有如下输出:

你能看到Weave网络接口,ethwe,使用ifconfig命令:

相似的,在$HOST2启动的容器中,有如下的输出:

这样我们就有了它——分别位于不同的主机上两个容器,彼此愉快地通信。

Open vSwitch

默认情况下,Docker使用Linux网桥docker0,然而,有些情况下我们需要的是Open vSwitch(OVS)而不是Linux网桥。一个单一的Linux网桥能使用1024个端口-这个限制了Docker仅仅能创建1024个容器的规模,每个占用一个网络接口。

单节点OVS

我们将安装单节点的OVS,生成两个容器并且通过OVS桥连接他们。

使用下面的命令安装OVS:

# sudo apt-get install openvswitch-switch

下面的命令安装ovs-docker工具:

# cd /usr/bin
# wget
https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-
docker
# chmod a+rwx ovs-docker

下图展示了单节点的OVS

创建一个OVS桥

接下来,我们将增加一个新的OVS桥并且配置它从而得到连接在不同网络中的容器,如下所示:

# ovs-vsctl add-br ovs-br1
# ifconfig ovs-br1 173.16.1.1 netmask 255.255.255.0 up

接下来的步骤将从OVS桥上增加一个端口给Docker的容器:

  1.生成两个Ubuntu的Docker容器:

# docker run -I -t --name container1 ubuntu /bin/bash
# docekr run -I -t --name container2 ubuntu /bin/bash

  2.把容器链接到OVS网桥上:

# ovs-docker add-port ovs-br1 eth1 container1 --ipaddress=173.16.1.2/24
# ovs-docker add-port ovs-br1 eth1 container2 --ipaddress=173.16.1.3/24

  3.通过ping命令测试通过OVS网桥相连的容器的连通性,首先,查询他们各自的IP地址:

    

    现在我们知道了container1和container2的IP地址,就可以ping它们:

   

跨主机OVS

接下来我们研究跨主机情况下使用OVS连接Docker容器。

让我们考虑展示在下面图表中设置,包含Host1和Host2两个主机,运行Ubuntu14.04系统:

在两个宿主机上安装Docker和Open vSwitch:

# wget -qO- https://get.docker.com/ | sh
# sudo apt-get install openvswitch-switch

安装ovs-docker工具

# cd /usr/bin
# wget
https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-
docker
# chmod a+rwx ovs-docker

默认情况下,Docker选择一个随机网络来运行它的容器。它创建一个网桥docker0,并且给他分配了一个地址(172.17.42.1)。所以,Host1和Host2的docker0网桥地址是一样的,因此,这是十分困难对于容器在宿主机之间通信。为了克服这个问题,我们给网络分配静态IP地址,92.168.10.0/24。

接下来,我们改变默认的Docker子网:

在Host1上执行下面的命令:

# service docker stop
# ip link set dev docker0 down
# ip addr del 172.17.42.1/16 dev docker0
# ip addr add 192.168.10.1/24 dev docker0
# ip link set dev docker0 up
# ip addr show docker0
# service docker start

增加br0 OVS网桥:

# ovs-vsctl add-br br0

给其它主机创建创建管道并且连接起来:

# add-port br0 gre0—set interface gre0 type=gre
options:remote_ip=30.30.30.8

把br0网桥连接到docker0网桥上:

# brctl addif docker0 br0

在Host2上执行下面的命令:

# service docker stop
# iptables -t nat -F POSTROUTING
# ip link set dev docker0 down
# ip addr del 172.17.42.1/16 dev docker0
# ip addr add 192.168.10.2/24 dev docker0
# ip link set dev docker0 up
# ip addr show docker0
# service docker start

增加br0 OVS网桥:

# ip link set br0 up
# ovs-vsctl add-br br0

创建到另一个主机的通道并连接起来:

# br0 bridge ovs-vsctl add-port br0 gre0—set interface gre0 type=gre
options:remote_ip=30.30.30.7

把br0网桥连接到docker0网桥上:

# brctl addif docker0 br0

这样docker0网桥就添加到另一个网桥br0上。这个时候,它就是一个OVS网桥,这意味着在容器之间全部的流量也都会由br0网桥路由。

除此之外,我们使用了一条GRE隧道将运行容器的两台主机的网络连接起来,该隧道连接到OVS的br0网桥,因此也连接到docker0网桥上。

在两个宿主机上执行了上面的命令后,应该能够从两台主机上ping docker0桥接地址。

在主机1上,使用ping命令生成以下输出:

在主机2上,使用ping命令生成以下输出:

让我们看看如何在这两个主机上创建容器:

在HOST1上,使用下面的命令:

# docker run -t -i --name container1 ubuntu:latest /bin/bash

在HOST2上,使用下面的命令:

# docker run -t -i --name container2 ubuntu:latest /bin/bash

现在我们可以从container1上 ping container2。通过这种方式,我们使用Open vSwitch在多个主机上连接Docker容器。

网络与overlay网络--Flannel

Flannel是虚拟网络层,给每个宿主机上Docker容器提供一个子网。它与CoreOS封装在一起,但也可以在其他Linux操作系统上配置。Flannel通过实际连接到Docker桥来创建覆盖层,容器连接到Docker桥,如下图所示。要安装Flannel,需要两台主机或VM,它们可以是CoreOS,或者最好是Linux OS,如图所示:

Flannel代码可以从GitHub中克隆出来,如果需要的话,还可以在不同版本的Linux操作系统上本地构建,如下所示。它预装在CoreOS中:

# git clone https://github.com/coreos/flannel.git
Cloning into 'flannel'...
remote: Counting objects: 2141, done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 2141 (delta 6), reused 0 (delta 0), pack-reused 2122
Receiving objects: 100% (2141/2141), 4.
Checking connectivity… done.


# sudo docker run -v `pwd`:/opt/flannel -i -t google/golang /bin/bash -c
"cd /opt/flannel && ./build"
Building flanneld…

可以使用Vagrant和VirtualBox轻松配置CoreOS机器,如下面的链接中提到的教程所述:

https://coreos.com/os/docs/latest/booting-on-vagrant.html

创建并登录到机器之后,我们将发现使用etcd配置自动创建的Flannel桥接器:

# ifconfig flannel0
flannel0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1472
inet 10.1.30.0 netmask 255.255.0.0 destination 10.1.30.0
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
txqueuelen 500 (UNSPEC)
RX packets 243 bytes 20692 (20.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 304 bytes 25536 (24.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Flannle环境可以通过查看subnet.env来检查

# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.1.0.0/16
FLANNEL_SUBNET=10.1.30.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=tru

Docker守护进程需要使用以下命令重新启动,以便从Flannel网桥用子网重新实例化网络:

第二个主机的Flannel环境也可以通过查看subnet.env来检查:

# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.1.0.0/16
FLANNEL_SUBNET=10.1.31.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=true

另一个子网分配给第二个主机。Docker服务也可以在此主机中通过连接到Flannel网桥而重新启动:

Docker可以在各自的主机中创建容器,并且可以使用ping命令对它们进行测试,以检查Flannel覆盖网络的连接性。
对于主机1,使用以下命令:

对于主机2,使用以下命令:

因此,在前面的示例中,我们可以看到Flannel通过在每个主机上运行flanneld代理来降低复杂性,该代理负责从预配置的地址空间分配子网租约。Flannel内部使用etcd存储网络配置和其他细节,比如主机IP和分配的子网。包的转发使用后端策略实现。

Flannel还旨在解决Kubernetes部署在GCE之外的云提供商上的问题,Flannel覆盖网格网络可以通过为每个服务器创建子网来为每个pod分配唯一的IP地址。

总结

在本章中,我们学习了Docker容器如何使用不同的网络选项(如Weave、OVS和Tlannel)在多个主机之间通信。Pipework使用了老的的Linux bridge、Weave创建虚拟网络、OVS使用GRE隧道技术,以及Flannel为每个主机提供一个单独的子网,以便将容器连接到多个主机。有些方案(如Pipework)是遗留的,在一段时间内将会废弃,而另一些则被设计用于特定操作系统的上下文中,比如带有CoreOS的Flannel。

  网络方案
Weave 虚拟化Overlay网络
Flannel 创建隔离的子网
Open vSwitch GRE管道
Pipework Linux网桥

 

 

 

 

 

 

在下一章中,我们将讨论在使用Kubernetes、Docker Swarm和Mesosphere等框架时,Docker容器是如何互联的。


更多精彩内容