Docker实现跨主机容器实例网络通信(2)——利用OpenVSwitch构建多主机Docker网络

时间:2022-11-01 14:17:34



题记

前面我们已经针对Docker容器进行了简单介绍,相信感兴趣的朋友已经能在相关帮助下部署一个docker环境感受了容器带给我们的另一种技术进步。

当然,如果你慢慢深入容器的技术研究,你会发现,尽管容器是虚拟机的未来趋势,但是容器还有很多需要进步,特别是关于网络方面,虚拟化技术可以支持非常丰富的网络需求,但是现在容器可能在这一块还需要继续进步和完善,最大的需求就是如果我们构建容器集群,我们可能只在一个宿主机上创建多个容器,可能需要N个宿主机,每个宿主机上又包含M个容器,我们需要N*M个容器组成一个大的容器集群网络,那么如何跨宿主机进行容器的网络连接是需要我们关注的,当然,现在也有非常多的方案供我们去选择:

--------------------------------------------------------------------------------------

Blog:    http://blog.csdn.net/chinagissoft

QQ群:16403743

宗旨:专注于"GIS+"前沿技术的研究与交流,将云计算技术、大数据技术、容器技术、物联网与GIS进行深度融合,探讨"GIS+"技术和行业解决方案

转载说明:文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

--------------------------------------------------------------------------------------


1、利用容器暴露端口方式

2、LinuxBriage方式

3、例如类似weave方式实现

4、也是本博客介绍的利用OpenvSwitch来实现

关于OpenvSwitch不多介绍,我OpenStack的早期版本(K版本之前),关于网络Neutron的实现都是通过OpenvSwitch。


实验环境

Docker实现跨主机容器实例网络通信(2)——利用OpenVSwitch构建多主机Docker网络


使用VMWare Workstation12

Ubuntu14.04

Docker 1.9.0


1、构建OpenvSwitch安装包

默认安装的版本不符合需求,也可以在一个新环境执行如下步骤

#获取最新存档
wget http://openvswitch.org/releases/openvswitch-2.3.1.tar.gz
tar xzvf openvswitch-2.3.1.tar.gz
cd openvswitch-2.3.1

#安装依赖
sudo apt-get install -y build-essential fakeroot debhelper \
autoconf automake bzip2 libssl-dev \
openssl graphviz python-all procps \
python-qt4 python-zopeinterface \
python-twisted-conch libtool

# 构建(不使用并行检查)
DEB_BUILD_OPTIONS='parallel=8 nocheck' fakeroot debian/rules binary

# 得到最新deb文件并复制到某处
cd ..
ls -al *deb

执行完毕之后可以看到

openvswitch-2.3.1.tar.gz
openvswitch-common_2.3.1-1_amd64.deb
openvswitch-datapath-dkms_2.3.1-1_all.deb
openvswitch-datapath-source_2.3.1-1_all.deb
openvswitch-dbg_2.3.1-1_amd64.deb
openvswitch-ipsec_2.3.1-1_amd64.deb
openvswitch-pki_2.3.1-1_all.deb
openvswitch-switch_2.3.1-1_amd64.deb
openvswitch-test_2.3.1-1_all.deb
openvswitch-vtep_2.3.1-1_amd64.deb
python-openvswitch_2.3.1-1_all.deb

这也是我们需要的相关版本,然后安装即可(默认认为Docker环境以及安装好)

sudo apt-get install -y bridge-utils
sudo dpkg -i openvswitch-common_2.3.1-1_amd64.deb \
openvswitch-switch_2.3.1-1_amd64.deb

2、配置网络

默认两台机器的IP可以互相ping通,然后,只需要设置网络即可

例如在192.168.12.107机器上设置为

# auto:为了有效地在主机启动时启动它
# br0=br0:防止在`ifquery --list`时被找到
auto br0=br0
allow-ovs br0
iface br0 inet manual
ovs_type OVSBridge
ovs_ports gre1 gre2
ovs_extra set bridge ${IFACE} stp_enable=true
mtu 1462

# 没有auto,这是ovs的一个额外配置
# 两台主机的gre名字必须相符
allow-br0 gre1
iface gre1 inet manual
ovs_type OVSPort
ovs_bridge br0
ovs_extra set interface ${IFACE} type=gre options:remote_ip=192.168.12.117



# auto:启动时创建
# 定义docker要使用的docker0,并(在可用时)连接到到OpenVSwitch创建的br0网桥上
# 每台主机需要使用不同的IP地址(不要相互冲突!)
auto docker0=docker0
iface docker0 inet static
address 172.17.1.1
network 172.17.0.0
netmask 255.255.0.0
bridge_ports br0
mtu 1462

在其他机器上,只需在配对的远程IP修改即可,如果需要更多的宿主机,可以添加更多的gre隧道即可,例如

allow-br0 gre2(新的gre)
iface gre2 inet manual
ovs_type OVSPort
ovs_bridge br0 (都在br0网桥)
ovs_extra set interface ${IFACE} type=gre options:remote_ip=192.168.12.199(新的IP)

说明

  • 生成树协议(Spanning Tree Protocol):如果应用该配置,将在3台服务器中创建一个网络回路,这可不行。给br0网桥添加stp_enable=true将确保一些gre隧道被切断。同时确保网状网络的冗余,允许网络在其中一台主机下线时恢复。
  • MTU:这是一项关键设定!没有这项,你可能获得一些意外“惊喜”:网络看起来工作正常(比如可以ping),但无法支持大数据包(比如BW测试中的iperf、大数据量请求或简单的文件复制)。注意,GRE隧道需要封装多种协议:
    • 以太网:14字节——我们说的是网桥间的第2层;
    • IPv4:20字节——容器/主机间通讯;
    • GRE:4字节——因为,嗯,这是个GRE隧道;
    • 也就是物理网卡MTU减去38字节,结果是1462(基于常规的1500 MTU网卡)。
  • 在auto定义中使用“=:对于具有固定IP的服务器这不是必需的,但有些云服务商(这里就不说是谁了……Digital Ocean(译者:软广再次乱入))使用了一个依靠ifquery --list --allow auto的init服务(/etc/init/cloud-init-container.conf)。不加上“=”号将包含OpenVSwitch网卡,并延迟整个启动过程直到init脚本失败并超时。
  • docker0网桥:每台服务器都需要自己的IP地址(比如172.17.1.1172.17.1.2)。由于docker0网桥处在br0网桥之上,它们将(也应该!)可以相互连接。想象一下,要解决IP冲突会有多乱……这也是为什么我们要在启动时定义它,而不依赖docker服务来为我们创建这个网桥。
  • GRE隧道:你可以从gre0(而不是gre1)开始,它能完美工作。但由于某种原因,在输入ifconfig时你可以看到gre0,却看不到其他隧道。这可能是gre0作为虚拟网卡的一个副作用。从gre1开始将让所有的gre隧道对ifconfig“隐身”(好过于只能看见一个)。别着急,你还是可以使用ovs-vsctl命令显示隧道/网桥。
  • 3台以上主机:你可以遵循相同的逻辑,并且:
    • 添加额外的隧道(iface greX)来连接新主机。
    • br0网桥定义中更新ovs_ports以包含interfaces文件中定义的所有gre隧道。
    • 聪明点……不要将每台服务器跟其他主机一一链接……STP收敛(convergence)将需要更长的时间,并且无法提供任何除了多重额外链路冗余之外的有用价值。

设置完毕之后,建议重启机器,然后可以在任意机器上都可以相互ping通管理IP(192.168.12.xxx)和docker0的IP(172.17.1.xxx)


3、容器添加

现在已经有网络了,需要将各个宿主机的容器都添加到docker0里面

  • 每台主机(192.168.12.107192.168.17.117)挂接到前面创建的docker0网桥上,其各自的IP地址是172.17.1.1172.17.1.2
  • docker0网卡指定了一个/16的IP范围;
  • 给每台主机指定了一小块docker0的IP范围,以/18 fixed-cidr的形式保存在它们的docker服务配置中。分别是172.17.64.0/18172.17.128.0/18

如果你的主机多于3台,你需要细分一个每个范围,或根据组织需要对整个网络拓扑结构进行重新考虑。

Docker实现跨主机容器实例网络通信(2)——利用OpenVSwitch构建多主机Docker网络所需,需要为每一个宿主机的docker配置相关IP信息

例如docker1机器(/etc/default/docker

BRIDGE=docker0
CIDR=172.17.64.0/18

wait_ip() {
address=$(ip add show $BRIDGE | grep 'inet ' | awk '{print $2}')
[ -z "$address" ] && sleep $1 || :
}

wait_ip 5
wait_ip 15

DOCKER_OPTS="
-H unix:///var/run/docker.sock
-H tcp://0.0.0.0:2375
--fixed-cidr=$CIDR
--bridge $BRIDGE
--mtu 1462
"

其他机器的CIDR参考上述即可。

你可以根据需要修改DOCKER_OPTS配置,添加镜像、不安全的registry、DNS等等。

说明:

  • wait_ip:由于docker0网桥最后被创建,获取IP地址可能需要花点时间。使用wait_ip“功能”,你可以在返回docker init脚本前安全地等待几秒钟。该配置文件是被真正的init脚本(/etc/init/docker.conf)所引用。
  • mtu:与前面相同原因,只是一个预防措施,用于确保每个网卡被创建时会被指定正确的MTU。
  • -H tcp://……:如果你不想通过0.0.0.0将其“公开”(或绑定到服务器“真实”网卡之一),你也可以将它安全地绑定到……该主机的docker0 IP地址(比如172.17.1.2)!这样,你可以从任何一台主机访问到私有网状网络里的任何一个docker服务。


测试


1、分别在docker1和docker2运行容器实例

我在docker1运行了两个ubuntu 14.04实例,相关IP分别是172.17.64.1和172.17.64.2

我在docker2运行了一个ubuntu 14.04实例,相关IP分别是172.17.128.1

首先测试是否可以ping通

Docker实现跨主机容器实例网络通信(2)——利用OpenVSwitch构建多主机Docker网络


然后,我针对docker1的64.2容器,与docker2的128.1进行测试,分别安装了ssh服务,然后为docker2容器创建ss用户,然后通过docker1的64.2容器,进行ssh远程连接。


Docker实现跨主机容器实例网络通信(2)——利用OpenVSwitch构建多主机Docker网络


参考文献

http://dockone.io/article/228