利用OpenVSwitch构建多主机Docker网络
运行Docker已经不是什么新鲜事,网上有很多入门教程来帮助你在一台主机上运行容器。这台主机可以是Linux服务器,也可以是Mac(借助类似boot2docker的项目)。
在多台主机上运行却是另外一回事……
可选方案:
- 分别在每台主机上运行Docker,在公网或内网网卡上暴露端口以便容器间相互通讯。这可能比较麻烦,而且会引发安全问题。
- 运行类似Weave的中间层方案来完全地抽象网络。这个项目前景不错,不过还太年轻,尚未与compose(之前的fig)或maestro-ng这类编排工具整合。
- 运行类似Deis或Flynn的Docker多主机一站式方案。这可能不在你的考虑范围内。
- 在主机间的网状网络中创建一个共享网桥,让Docker服务在那运行容器。这听起来有点复杂,不过……本文中我们将看到这可以非常容易地完成!
![](http://dockerone.com/uploads/article/20150306/d9919e61de13f5b2d4e4c354d4a9825b.jpg)
概述
基本上,我们将执行以下步骤:
- 在每台服务器上安装Docker;
- 在每台服务器上安装OpenVSwitch;
- 自定义网络设置用以自动在主机间创建网桥/隧道(在每台服务器的
/etc/network/interfaces
里); - 自定义每个Docker服务配置,只处理
docker0
IP范围的一小部分,防止新容器的IP地址发生重叠。
就是这样。重启服务或重启服务器后,你将获得一个具备连接冗余(link redundancy)的全网状网络,Docker服务可以在专用的IP范围(不会重叠)上运行容器,并且不需要在公网或内网网卡上暴露所有端口就能互联。很棒,对么?
技术
简单列一下我们用到的技术:
- Docker:嗯……这是篇关于Docker与网络的文章,所以……
- OpenVSwitch:非常棒的虚拟网络交换机项目,伸缩性非常好,根据本指南,你可以运行“任意”规模的网络。
我们将假定服务器运行的是Ubuntu Server 14.04.02 LTS x64,对于其它系统,你可能需要修改下面提供的各项配置。
安装
Docker
无需多言,遵循官网提供的指南就行。稍后我们将深入其配置,以便运行于服务器上的不同Docker服务可相互协作。
OpenVSwitch
糟糕的是,默认仓库里OpenVSwitch安装包不可用(或过期了),我们需要自己构建.deb
文件(一次),然后分发给不同主机。为了保持生产机的整洁,可另外找台小主机来安装开发包,并构建安装包。
OpenVSwitch GitHub上有详细的构建手册。
执行下列命令来构建安装包(新版请按要求修改):
#获取最新存档 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
现在你有了新的.deb
安装包,接下来将其推送并安装到所有主机上。
# 复制包到各主机并ssh登录 scp -r *deb user@remote_host:~/. ssh user@remote_host# 安装一些依赖(后面需要)并安装包 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
配置
网络
你可以使用OpenVSwitch提供的不同命令行工具来构建网状网络(比如ovs-vsctl
),不过Ubuntu提供了一个辅助工具让你可以通过/etc/network/interfaces
文件定义网络。
假定三台主机:1.1.1.1、2.2.2.2和3.3.3.3,可以通过上述IP相互ping通,它们是在公网或内网上并不重要。host1的/etc/network/interfaces
大概如下。
... # eth0、eth1和lo配置 ...# 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=2.2.2.2allow-br0 gre2 iface gre2 inet manual ovs_type OVSPort ovs_bridge br0 ovs_extra set interface ${IFACE} type=gre options:remote_ip=3.3.3.3# auto:启动时创建 # 定义docker要使用的docker0,并(在可用时)连接到到OpenVSwitch创建的br0网桥上 # 每台主机需要使用不同的IP地址(不要相互冲突!) auto docker0=docker0 iface docker0 inet static address 172.17.42.1 network 172.17.0.0 netmask 255.255.0.0 bridge_ports br0 mtu 1462
在其它主机上要对这个配置上做些调整:remote_ip
的IP地址要相互配对。
![](http://dockerone.com/uploads/article/20150306/2fab31519e9c9c8e8ebd756315757fe6.jpg)
几点说明:
- 生成树协议(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.42.1
、172.17.42.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)将需要更长的时间,并且无法提供任何除了多重额外链路冗余之外的有用价值。
如果现在重启服务器,你将拥有一个具备冗余的网状网络,你可以运行以下命令来测试:
- 从host1上
ping 172.17.42.2
或其他IP; - 在主机上运行
iperf
,通过ifconfig
查看使用中的链接; - 在ping第三台主机时停止“中间”那台,查看网络收敛(通过STP)时ping中断了几秒钟。
![](http://dockerone.com/uploads/article/20150306/cf9cd0130d22de184f7f27d0165c9874.jpg)
Docker
我们现在有了一个完善的网络,每个Docker服务都可以将它们的容器挂接到docker0
网桥上。让Docker自动完成这步不是很棒么?答案在于Docker有能力分配一个最小的IP地址池!
对于该示例,我们假定:
- 每台主机(
1.1.1.1
、2.2.2.2
、3.3.3.3
)挂接到前面创建的docker0
网桥上,其各自的IP地址是172.17.42.1
、172.17.42.2
、172.17.42.3
; - 给
docker0
网卡指定了一个/16的IP范围; - 给每台主机指定了一小块
docker0
的IP范围,以/18fixed-cidr
的形式保存在它们的docker服务配置中。分别是172.17.64.0/18
、172.17.128.0/18
、172.17.192.0/18
。
如果你的主机多于3台,你需要细分一个每个范围,或根据组织需要对整个网络拓扑结构进行重新考虑。
![](http://dockerone.com/uploads/article/20150306/f46cc62313ea4495e023f3d6698e9eb1.jpg)
host1的配置文件(/etc/default/docker
)是这样的:
BRIDGE=docker0 CIDR=172.17.64.0/18wait_ip() { address=$(ip add show $BRIDGE | grep 'inet ' | awk '{print $2}') [ -z "$address" ] && sleep $1 || : }wait_ip 5 wait_ip 15DOCKER_OPTS=" -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375 --fixed-cidr=$CIDR --bridge $BRIDGE --mtu 1462 "
你可以根据需要修改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.42.2
)!这样,你可以从任何一台主机访问到私有网状网络里的任何一个docker服务。
结语
重启一下(至少保证启动时所有东西都会自动上线)。
你可以试试以下命令看看一切是否正常。
# 访问host1 ssh user@host1# 运行一个新容器 docker run -ti ubuntu bash# 检查IP(在容器内运行) ip add | grep eth0# # 在其他窗口中 # # 访问另一台主机(host2或3) ssh user@host2# 运行一个新容器 docker run -ti ubuntu bash# Ping其他的容器! ping $IP
这不是一份指导如何在多主机上设置Docker的权威指南,欢迎大家提出批评(译者注:译稿也一样,请大家多多指正)。很多想法是在整体安装时产生的,本文尽可能详细地说明了为何选择这个或那个选项。
如果将分级网桥、VLAN等包括进来,事情将更复杂,不过那超出了本文的范围。;)
显然,更完整的网络是有需求的,而且看起来这个已经在开发中。
参考内容
- https://goldmann.pl/blog/2014/ ... osts/
- http://networkstatic.net/open- ... tion/
- http://networkstatic.net/confi ... itch/
- http://fbevmware.blogspot.com. ... .html
- http://openvswitch.org/support ... .html
- https://access.redhat.com/docu ... .html
- https://communities.vmware.com ... ation
- http://www.microhowto.info/tro ... .html
- http://blog.scottlowe.org/2013 ... itch/
- http://blog.scottlowe.org/2013 ... itch/
- https://github.com/openvswitch ... an.md
- http://baturin.org/tools/encapcalc/
利用OpenVSwitch构建多主机Docker网络相关推荐
- Docker实现跨主机容器实例网络通信(2)——利用OpenVSwitch构建多主机Docker网络
题记 前面我们已经针对Docker容器进行了简单介绍,相信感兴趣的朋友已经能在相关帮助下部署一个docker环境感受了容器带给我们的另一种技术进步. 当然,如果你慢慢深入容器的技术研究,你会发现,尽管 ...
- 利用BT构建简单的CDN网络
种子下载源需部署到公网服务器上,部署在内网服务器上没见成功下载过. 一. 服务器上部署tracker服务 tracker服务器建议采用OpenTracker(据说可以在生产环境下使用).OpenTra ...
- Docker 之 高级篇(应用复杂安装、DockerFile、Docker网络、Docker-compose、可视化工具)
前言 前一章介绍了docker的基础知识,适合零基础小白阅读和学习,当然非小白也可用于查阅,查漏补缺,本章开始将记录一些docker的高级部分,难度上也会提升很多,内容较多,比较枯燥,不过看下来一定会 ...
- 利用Swarmkit构建Windows/Linux混合Docker集群
在很多公司都同时存在Windows+Linux两种操作系统,在Linux上跑Docker很方便各种资料文档齐全,但是在Windows上跑Docker相对比较少,同时也受到一些限制,如Windows上d ...
- Docker原生网络、自定义网络、Docker容器通信、跨主机容器网络
Docker原生网络.自定义网络.Docker容器通信.跨主机容器网络 Docker原生网络 bridge Host none Docker自定义网络 自定义bridge overlay macvia ...
- Docker 收购 SocketPlane 多主机容器网络
Docker 官方宣布收购 SocketPlane 多主机容器网络解决方案.SocketPlane 最开始是由 4 个人创办的,希望该系统能成为 Docker 生态里重要的一部分.SocketPlan ...
- docker网络配置方法总结
docker启动时,会在宿主主机上创建一个名为docker0的虚拟网络接口.默认选择172.17.42.1/16,一个16位的子网掩码给容器提供了65534个IP地址.docker0仅仅是一个在绑定到 ...
- Docker学习四:Docker 网络
前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...
- Docker学习之四:容器虚拟化网络与docker网络
虚拟化网络的原理简述 Linux内核支持六种名称空间,只要在用户空间有相应的客户端工具,都可以对对应的名称空间进行操作. 假如物理机有四块网卡,可以创建两个名称空间,此时可灵活将网卡分配到单独的名称空 ...
最新文章
- 史上最全中文语料数据集
- 世园会开幕式上的机器人_【在国际智能制造大会暨智能机器人大会开幕式上的致辞】世界智能机器人大会...
- android 数据库 字节数组,Android上的GreenDAO:字节数组作为主键/构建包含字节数组属性Where子句的查询...
- 升级php5.4 mysql5.5_在CentOS上把PHP从5.4升级到5.5
- mysql mvc javascript_MVC中用Jquery、JS和Ajax 实现分页 存储过程是用mysql写的。
- React学习笔记一 JSX语法组件
- 强悍的 Linux —— grep 与 egrep
- MongoDB 基础操作
- 设置jupyter notebook的启动及工作目录方法汇总
- JavaWeb在线商城系统(java+jsp+servlet+MySQL+jdbc+css+js+jQuery)
- jQuery插入QuickTime视频播放器
- Android之Keystore文件签名(获取查看apk签名)
- 科林明伦杯哈理工第十届同步赛部分题解
- Microsoft visual C++6.0设置行号
- python能写app吗_Python可以开发APP吗?
- 医学影像组学之病理切片分割(免费训练数据,标注数据,免费代码,免费教程)三天走完影像组学全部流程
- 多路径配置udev_学习笔记:Linux多路径配置 multipath实现设备用户组绑定详细设置...
- oracle的sql if函数的使用方法,oracle基本sql语句和函数详解
- Google Glass 开发
- MySQL之PXC集群搭建
热门文章
- linux版vmware使用命令行启动vmware中的虚拟机
- 06_平台总线匹配规则,自己搭建总线xbus
- git如何将远程仓库代码拉下覆盖本地仓库
- 暑假假期训练总结-8
- XE8-indy10中关于Connection Closed Gracefully的源码与解读
- python json文件操作_JSON文件及Python对JSON文件的读写操作
- php前台源码,PHP房产中介小程序源码8.0.2 后端模块+前台小程序 解密开源版
- 高等数学-无穷级数思维导图
- Vulnhub靶机:EVILBOX_ ONE(很详细)
- 计算机和正餐的英语发音,晚饭的英文,早餐,午餐,晚餐英语怎么读!