阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

利用OpenVSwitch构建多主机Docker网络

261次阅读
没有评论

共计 6155 个字符,预计需要花费 16 分钟才能阅读完成。

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

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

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

可选方案:

  • 分别在每台主机上运行 Docker,在公网或内网网卡上暴露端口以便容器间相互通讯。这可能比较麻烦,而且会引发安全问题。
  • 运行类似 Weave 的中间层方案来完全地抽象网络。这个项目前景不错,不过还太年轻,尚未与 compose(之前的 fig)或 maestro-ng 这类编排工具整合。
  • 运行类似 Deis 或 Flynn 的 Docker 多主机一站式方案。这可能不在你的考虑范围内。
  • 在主机间的网状网络中创建一个共享网桥,让 Docker 服务在那运行容器。这听起来有点复杂,不过……本文中我们将看到这可以非常容易地完成!

利用 OpenVSwitch 构建多主机 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 -*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 地址要相互配对。

multi-host-docker2.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.1172.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 中断了几秒钟。

利用 OpenVSwitch 构建多主机 Docker 网络

 

Docker

我们现在有了一个完善的网络,每个 Docker 服务都可以将它们的容器挂接到 docker0 网桥上。让 Docker 自动完成这步不是很棒么?答案在于 Docker 有能力分配一个最小的 IP 地址池!

对于该示例,我们假定:

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

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

multi-host-docker4.jpg

host1 的配置文件(/etc/default/docker)是这样的:

BRIDGE=docker0
CIDR=172.17.64.0/18

wait_ip() {
address=$(ip add show $BRIDGE | grep 'inet' | awk '{print $2}')[ -"$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 等包括进来,事情将更复杂,不过那超出了本文的范围。;)

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

如果你读完本文了,恭喜!

CentOS7 安装 Openvswitch 2.3.0 LTS  http://www.linuxidc.com/Linux/2014-12/110272.htm

OpenvSwitch 中端口的抽象层次结构  http://www.linuxidc.com/Linux/2014-09/106760.htm

OpenvSwitch 2.1.2 安装完成后 启动 与 停止 shell 脚本  http://www.linuxidc.com/Linux/2014-09/106284.htm

在 Docker 中使用 MySQL http://www.linuxidc.com/Linux/2014-01/95354.htm

在 Ubuntu Trusty 14.04 (LTS) (64-bit)安装 Docker http://www.linuxidc.com/Linux/2014-10/108184.htm 

Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm 

Ubuntu 14.04 安装 Docker  http://www.linuxidc.com/linux/2014-08/105656.htm 

阿里云 CentOS 6.5 模板上安装 Docker http://www.linuxidc.com/Linux/2014-11/109107.htm 

Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里 

本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-03/115566.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计6155字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中