Docker1.9新特性-跨物理机的多容器网络连接
近日,Docker公司正式发布Docker 1.9版本。他带来了很多新的特性,其中最重要的新特性无疑就是多宿主机互联功能.
在今年6月份的DockerCon上,互联曾经作为测试版本的特性被提出。目前,该特性正式集成在了Docker引擎的稳定版中,并将在产品中使用。其主要功能是为跨宿主机创建Docker引擎中的虚拟网络提供支持。用户可以把其所属的容器挂载到网络中,并控制网络拓扑和通信方式。此外,系统还允许用户在不修改应用的情况下直接与任何网络进行集成。
那么,我们现在就来试一试如何简单的实现多宿主机互联功能.
原理
Docker新的网络拓扑是采用的overlay network
模式的网络.
它需要一个分布式的Key-Value Storage
作为辅助的存储.当前Docker支持Consul
,Etcd
和ZooKeeper
.当创建网络之前,你首先是需要安装并运行KVS
.然后在启动Docker的时候加上一定的参数,这样Docker就会把网络拓扑信息保存在KVS
上,形成全局唯一的网络.
安装Docker1.9前的准备
由于Docker1.9多宿主机联网的功能设计为可插拔式,毫无保留兼容VXLAN
或者IPVLAN等技术。使用ovs(Open vSwitch)和VXLAN隧道进行实现。因此,需要操作系统支持VXLAN
.而在Kernel3.16
以下支持这个是有问题的,虽然看得到网络,但是使用这个网络启动容器的时候会报:subnet sandbox join failed for "10.0.0.0/24": error creating vxlan interface: file exists
,这个问题具体可以参见Issues14145.因此我们首先就是需要把操作系统的内核升级.具体的升级方法可以参考我之前的博文升级CentOS7的Linux内核.
然后还需要关闭Selinux. 直接编辑/etc/selinux/config
文件中设置SELINUX=disabled
,然后重启服务器。
还需要做的就是关闭防火墙:
|
|
安装Docker1.9
接下来就是安装最新的Docker1.9了. 在安装最新版之前,需要把旧的版本删除了.
然后在终端中输入:
|
|
等他执行完成后,最新版就安装完成了.
启动Zookeeper
这里我使用Zookeeper
来做试验,官网上的是使用Consul
做的演示,如果想使用Consul
可以看这里.
安装Zookeeper
集群就不在这里细说了,可以参考之前的博文zookeeper 集群部署.
安装完后启动zookeeper
. 这里假设 我的ZK的地址为:10.211.55.2:2181
启动Docker服务
接下来就是需要启动Docker服务了.
以前的启动方式是:service docker start
.
但是这样就不会增加KVS
的参数,因此我们需要手动的启动Docker服务:
|
|
这里主要有两个参数:
参数名 | 说明 |
---|---|
—cluster-store=PROVIDER://URL | 这个指的就是KVS的存储位置,比如zookeeper的就是:zk://xxxx,Consul的就是 consul://xxxxx |
—cluster-advertise=HOST_IP | 这个就是本机Docker服务需要对外公布的集群地址,可以直接写网卡地址 |
使用上面的参数启动后,Docker会在Zookeeper上建立一个目录.里面存放的就是网络的配置信息.
直接把所有宿主机上的Docker都像这样的方式启动.
如果你想直接使用service docker start
方式启动的话,需要修改/usr/lib/systemd/system/docker.service
这个文件.在ExecStart=/usr/bin/docker daemon
后面加上--cluster-store=zk://10.211.55.2:2181 --cluster-advertise=eth0:2376
.然后执行systemctl daemon-reload
,重新加载docker.service
即可. 以后就可以在命令行中直接输入service docker start
启动带1.9跨网的Docker服务了.注意,一定要先启动Zookeeper哦!
|
|
创建网络
Docker1.9新增加了一个命令network
,用于配置网络.在Docker1.9中,它把网络也当成了一种类似于容器的东西.可以创建,查询,删除网络.
比如在单机下 可以输入docker network create my-single-net
创建一个网络.
然后在启动容器的时候使用:docker run -itd --net=my-single-net --name web nginx
来使一个容器使用指定的网络来通信. 只要是在同一个网络下的容器,他们之间都可以通过容器的名字进行互联.而不需要像以前一样,写一堆的-Link
了.
而对于不同的网络之间也可以使用docker network connect
命令来使两个网络之间进行互联.
比如:
|
|
这样,就可以在容器中使用myapp.app
来访问其他的容器.
铺垫了这么多,现在我们就来创建overlay
类型的网络.
直接在终端中输入:docker network create --driver overlay my-net
这个命令就可以创建一个overlay
类型的网络,Docker接收到命令后会自动的在ZK上创建相应的节点.
那么这个时候,在其他机器上通过输入docker network ls
就应该能看到这个网络了:
|
|
|
|
正如上面所显示的.两台不同的宿主机上 现在都有一个ID为65a73f31fd82
的overlay
类型的网络了.
这个时候如果是调用ifconfig
命令来查看宿主机的网络配置,会发现他现在是有docker0
,docker_gwbridge
,eth0
等几个网卡的.其中docker_gwbridge
其实就是一个桥接网卡,它就负责了多个宿主机间的通信.
启动容器
既然网络已经配置好了,那么接下来要做的就是 启动容器了.这里我们已启动jplock/zookeeper
容器为例,在跨宿主机的Docker中创建一个Zookeeper
的集群.
一号宿主机(10.211.55.13):
二号宿主机(10.211.55.16):
这样就在每一个宿主机上启动了两个Zookeeper
的容器,并且都使用了相同的my-net
网络.
这个时候使用docker exec -ti zookeeper1 /bin/bash
进入到容器当中.使用ip address show
命令查看容器的IP的话,会显示为:
|
|
其中的eth0
就是容器全局唯一的一个IP地址
.
这个时候再调用cat /etc/hosts
来查看容器的hosts
配置,会发现:
|
|
Docker每启动一个容器,就会在相同网络下的其他容器的Hosts中加入hosts.因此,这个时候其实4个ZooKeeper的网络都是通的了,并且通过容器名
.网络名
是可以直接访问的.
这个时候在宿主机上使用docker network inspect my-net
命令就可以查看my-net
网络当前的状况,有什么容器在使用这个网络等等信息.
|
|
这样,Docker很简单的就实现了多宿主机的网络互通,每一个容器只需要通过全局唯一的容器名
就可以访问任意一个在相同网络中的容器了.
注意
目前还有一个问题,就是采用这种模式的情况下,其实容器的IP地址还是会改变的.因为它其实是在容器启动的时候,在ZK中去询问一个可用的IP地址,然后创建一个临时节点保存容器名和IP地址的映射. 当容器关闭后,这个IP地址就被释放了出来.下一次再申请可用的IP地址的时候,IP地址可能就变化了.这点需要我们在开发的时候注意,如果程序是依赖于IP地址的话,可能每次重启就会出现问题.尽量的使用Hosts来代替IP地址.
如果确实有固定IP的需求,这个还需要再进一步的研究.
参考文章:
http://blog.docker.com/2015/11/docker-multi-host-networking-ga/
https://github.com/docker/libnetwork/issues/