利用OpenVSwitch构建多主机Docker网络

【编者的话】当你在一台主机上成功运行Docker容器后,信心满满地打算将其扩展到多台主机时,却发现前面的尝试只相当于写了个Hello World的入门程序,多主机的网络设置成了下一道门槛。在你尝试各种方案时不妨先看看本文,或许就会豁然开朗,发现原来也不复杂。嗯,是的,本文用到了OpenVSwitch。

运行Docker已经不是什么新鲜事,网上有很多入门教程来帮助你在一台主机上运行容器。这台主机可以是Linux服务器,也可以是Mac(借助类似boot2docker的项目)。

在多台主机上运行却是另外一回事……

可选方案

■分别在每台主机上运行Docker,在公网或内网网卡上暴露端口以便容器间相互通讯。这可能比较麻烦,而且会引发安全问题。

■运行类似Weave的中间层方案来完全地抽象网络。这个项目前景不错,不过还太年轻,尚未与compose(之前的fig)或maestro-ng这类编排工具整合。

■运行类似Deis或Flynn的Docker多主机一站式方案。这可能不在你的考虑范围内。

■在主机间的网状网络中创建一个共享网桥,让Docker服务在那运行容器。这听起来有点复杂,不过……本文中我们将看到这可以非常容易地完成!

概述

基本上,我们将执行以下步骤:

■在每台服务器上安装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.2

allow-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地址要相互配对。

几点说明:

1.生成树协议(Spanning Tree Protocol):如果应用该配置,将在3台服务器中创建一个网络回路,这可不行。给br0网桥添加stp_enable=true将确保一些gre隧道被切断。同时确保网状网络的冗余,允许网络在其中一台主机下线时恢复。

2. MTU:这是一项关键设定!没有这项,你可能获得一些意外“惊喜”:网络看起来工作正常(比如可以ping),但无法支持大数据包(比如BW测试中的iperf、大数据量请求或简单的文件复制)。注意,GRE隧道需要封装多种协议:

■以太网:14字节——我们说的是网桥间的第2层;

■IPv4:20字节——容器/主机间通讯;

■GRE:4字节——因为,嗯,这是个GRE隧道;

■也就是物理网卡MTU减去38字节,结果是1462(基于常规的1500 MTU网卡)。

3.在auto定义中使用“=”:对于具有固定IP的服务器这不是必需的,但有些云服务商(这里就不说是谁了……Digital Ocean(译者:软广再次乱入))使用了一个依靠ifquery --list --allow auto的init服务(/etc/init/cloud-init-container.conf)。不加上“=”号将包含OpenVSwitch网卡,并延迟整个启动过程直到init脚本失败并超时。

4. docker0网桥:每台服务器都需要自己的IP地址(比如172.17.42.1、172.17.42.2)。由于docker0网桥处在br0网桥之上,它们将(也应该!)可以相互连接。想象一下,要解决IP冲突会有多乱……这也是为什么我们要在启动时定义它,而不依赖docker服务来为我们创建这个网桥。

5. GRE隧道:你可以从gre0(而不是gre1)开始,它能完美工作。但由于某种原因,在输入ifconfig时你可以看到gre0,却看不到其他隧道。这可能是gre0作为虚拟网卡的一个副作用。从gre1开始将让所有的gre隧道对ifconfig“隐身”(好过于只能看见一个)。别着急,你还是可以使用ovs-vsctl命令显示隧道/网桥。

6. 3台以上主机:你可以遵循相同的逻辑,并且:

■添加额外的隧道(iface greX)来连接新主机。

■在br0网桥定义中更新ovs_ports以包含interfaces文件中定义的所有gre隧道。

■聪明点……不要将每台服务器跟其他主机一一链接……STP收敛(convergence)将需要更长的时间,并且无法提供任何除了多重额外链路冗余之外的有用价值。

如果现在重启服务器,你将拥有一个具备冗余的网状网络,你可以运行以下命令来测试:

■从host1上ping 172.17.42.2或其他IP;

■在主机上运行iperf,通过ifconfig查看使用中的链接;

■在ping第三台主机时停止“中间”那台,查看网络收敛(通过STP)时ping中断了几秒钟。

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范围,以/18 fixed-cidr的形式保存在它们的docker服务配置中。分别是172.17.64.0/18、172.17.128.0/18、172.17.192.0/18。

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

host1的配置文件(/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

"

你可以根据需要修改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等包括进来,事情将更复杂,不过那超出了本文的范围。;)

显然,更完整的网络是有需求的,而且看起来这个已经在开发中。

转载自:DockerOne

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 转载自 http://blog.opskumu.com/docker.html 一、Docker 简介 Docke...
    极客圈阅读 10,468评论 0 120
  • 装载自http://sdnhub.cn/index.php/openv-switch-full-guide/ 1 ...
    ximitc阅读 5,661评论 0 11
  • 概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求。而容器的网络通信...
    糙老爷们儿吃什么樱桃阅读 3,607评论 1 5
  • 五、Docker 端口映射 无论如何,这些 ip 是基于本地系统的并且容器的端口非本地主机是访问不到的。此外,除了...
    R_X阅读 1,734评论 0 7
  • 从小,就有一个武侠梦。 身穿白衣,腰跨宝剑,手牵白马,穿梭在山水间,驰骋在草原上,行万里之路,看如画风景。遇不平之...
    佛心自然阅读 302评论 0 0