Docker 1.12 版最大的性能特点之一是Swarm 模式。Docker使容器编排1.6以上的版本可以使用Swarm。在Docker 1.12(RC) 版发布之前几周,Docker发布了Swarmkit作为编排分布式系统的开源项目。对于这三个项目,我有一些困惑。在本博客中,我试图围绕这三个软件组件之间的相似性和差异性进行解释。我还创建了一个示例应用,并使用这三种方法部署该应用,这样更易于比较。
Docker Swarm 模式与Swarm根本不同,都使用Swarm命名本身就令人费解,倘若Docker能够将其重命名为其他的名字就好了。更让人不解的是,Docker1.12 版本将继续支持本地Swarm功能,这样做是为了保持向后兼容性。
在本博客中,我使用术语“Swarm”来指代传统Swarm功能,“SwarmNext”指代加入在1.12版中的新Swarm模式,“Swarmkit”指代探索中的开源编排项目。
Swarm, SwarmNext 和 Swarmkit
下表比较了Swarm和SwarmNext
Swarm | SwarmNext |
与Docker Engine分离,可作为容器运行 | 整合到Docker 引擎中 |
需要Consul, etcd等外部KV存储 | 无需外部KV存储 |
服务模型不可用 | 服务模型可用。提供可扩展性、滚动更行、服务发现、负载均衡和路由网特性。 |
通信不安全 | 控制和数据层都是安全的 |
与machine和compose集成 | 截止到1.12版本发布时尚未与machine和compose集成,将在随后发布的版本中整合。 |
下表比较了Swarmkit和SwarmNext
Swarmkit | SwarmNext |
探究开源项目 | Swarmkit在SwarmNext内部使用,并与Docker Engine集成 |
Swarmkit需要构建并独立运行 | Docker 1.12 与SwarmNext集成 |
无服务发现、负载均衡和路由网 | 服务发现、负载均衡和路由网可用 |
使用swarmctl CLI | 使用常规 Docker CLI |
示例应用
下面是一个非常简单的应用,其中有一个方便可用的投票Web服务器,可以从客户端访问。客户端的请求将在可用的Web服务器之间进行负载均衡。此应用将在一个自定义的覆盖网络中创建。我们将用Swarm, SwarmNext 和Swarmkit对此应用进行部署。
先决条件
-
我使用了docker-机器版0.8.0-rc1和Docker 引擎版11.12.0-rc3。
-
“smakam/myubuntu” 容器是在常规Ubumtu的基础上加上一些附加工具如curl等,用于说明负载均衡。
使用Swarm的部署
步骤摘要如下
-
创建KV存储。在本例中,我使用了Concul。
-
使用已经创建的KV存储创建Docker实例。在本例中,我使用Docker机创建了Dockersh实例。
-
创建一个覆盖网络。
-
创建多个实例的投票web服务器和单一实例的客户端。所有web服务器必须共享同一个网络别名,以便从客户端的请求可以得到web服务器之间的负载平衡。
▌创建KV存储
docker-machine create -d virtualbox mh-keystore
eval "$(docker-machine env mh-keystore)"
docker run -d \
-p "8500:8500" \
-h "consul" \
progrium/consul -server -bootstrap
▌创建2个指向KV 存储的Docker Swarm 实例
docker-machine create \
-d virtualbox \
--swarm --swarm-master \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
mhs-demo0
docker-machine create -d virtualbox \
--swarm \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
mhs-demo1
▌创建覆盖网络
eval $(docker-machine env --swarm mhs-demo0)
docker network create --driver overlay overlay1
▌创建服务
两个投票容器的实例使用同样的别名“投票”,以便它们可以作为单一的服务被访问。
docker run -d --name=vote1 --net=overlay1 --net-alias=vote instavote/vote
docker run -d --name=vote2 --net=overlay1 --net-alias=vote instavote/vote
docker run -ti --name client --net=overlay1 smakam/myubuntu:v4 bash
▌我们将客户端容器连接到投票Web服务器
root@abb7ec6c67fc:/# curl vote | grep "container ID"
Processed by container ID a9c05cd4ee15
root@abb7ec6c67fc:/# curl -i vote | grep "container ID"
Processed by container ID ce94f38fc958
从上面的输出中我们可以看到,向"投票”服务发出的ping命令在“投票1”和“投票2”之间进行负载均衡,它们各自拥有不同的容器 ID。
使用SwarmNext进行部署
步骤摘要如下
-
使用Docker machine 1.12 RC3 Docker 图像创建2个Docker实例。启动一个节点作为主节点,另一个为工作节点。
-
创建一个覆盖网络。
-
在上面创建的覆盖网络中创建具有2个备份的投票web服务和具有1个备份的客户端服务。
▌创建2 个Docker 实例
docker-machine create -d virtualbox node1
docker-machine create -d virtualbox node2
▌设置节点1为主节点
docker swarm init --listen-addr 192.168.99.100:2377
节点1除作为主节点以外,也将作为工作节点。
▌设置节点2为工作节点
docker swarm join 192.168.99.100:2377
▌我们来看如何运行节点
$ docker node ls
ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
b7jhf7zddv2w2evze1bz44ukx * node1 Accepted Ready Active Leader
ca4jgzcnyz70ry4h5enh701fv node2 Accepted Ready Active
▌创建覆盖网络
docker network create --driver overlay overlay1
▌创建服务
docker service create --replicas 1 --name client --network overlay1 smakam/myubuntu:v4 ping docker.com
docker service create --name vote --network overlay1 --replicas 2 -p 8080:80 instavote/vote
对于本实例而言,不需要暴露端口到主机,反正我已经使用了。使用Docker 1.12 的路由网功能,端口8080被暴露于“节点1”和“节点2”。
▌我们来看如何运行服务
$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
2rm1svgfxzzw client 1/1 smakam/myubuntu:v4 ping docker.com
af6lg0cq66bl vote 2/2 instavote/vote
▌我们将客户端容器连接到投票Web服务器
# curl vote | grep "container ID"
Processed by container ID c831f88b217f
# curl vote | grep "container ID"
Processed by container ID fe4cc375291b
从上面的输出中,我们可以看到从客户端到2个服务器容器之间进行负载均衡。
使用Swarmkit进行部署
步骤如下
-
创建Docker 机2节点集群。我能够创建Swarm集群并且不需要KV存储就能使用它。出于某种原因,没有KV存储,覆盖网络没有运行。所以对这个例子我不得不使用KV存储。
-
创建Swarmkit并导出二进制文件到Swarm节点。
-
创建具有2个节点的Swarm 集群。
-
创建覆盖网络,并在这个覆盖网络中创建服务。
▌建立Swarmkit
这里Swarmkit是建立在GO 容器之中的。
git clone https://github.com/docker/swarmkit.git
eval $(docker-machine env swarm-01)
docker run -it --name swarmkitbuilder -v `pwd`/swarmkit:/go/src/github.com/docker/swarmkit golang:1.6 bash
cd /go/src/github.com/docker/swarmkit
make binaries
▌创建带KV存储的Docker 实例
docker-machine create \
-d virtualbox \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
swarm-01
docker-machine create -d virtualbox \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
swarm-02
▌导出Swarmkit二进制文本到节点
docker-machine scp bin/swarmd swarm-01:/tmp
docker-machine scp bin/swarmctl swarm-01:/tmp
docker-machine ssh swarm-01 sudo cp /tmp/swarmd /tmp/swarmctl /usr/local/bin/
docker-machine scp bin/swarmd swarm-02:/tmp
docker-machine scp bin/swarmctl swarm-02:/tmp
docker-machine ssh swarm-02 sudo cp /tmp/swarmd /tmp/swarmctl /usr/local/bin/
▌创建Swarm丛集
Master:
docker-machine ssh swarm-01
swarmd -d /tmp/swarm-01 \
--listen-control-api /tmp/swarm-01/swarm.sock \
--listen-remote-api 192.168.99.101:4242 \
--hostname swarm-01 &
Worker:
swarmd -d /tmp/swarm-02 \
--hostname swarm-02 \
--listen-remote-api 192.168.99.102:4242 \
--join-addr 192.168.99.101:4242 &
▌创建覆盖网络和服务
swarmctl network create --driver overlay --name overlay1
swarmctl service create --name vote --network overlay1 --replicas 2 --image instavote/vote
swarmctl service create --name client --network overlay1 --image smakam/myubuntu:v4 --command ping,docker.com
▌下列命令显示这2个节点丛集
export SWARM_SOCKET=/tmp/swarm-01/swarm.sock
swarmctl node ls
ID Name Membership Status Availability Manager Status
-- ---- ---------- ------ ------------ --------------
5uh132h0acqebetsom1z1nntm swarm-01 ACCEPTED READY ACTIVE REACHABLE *
5z8z6gq36maryzrsy0cmk7f51 ACCEPTED UNKNOWN ACTIVE
▌下列命令显示从客户端到投票Web服务器的成功连接
# curl 10.0.0.3 | grep "container ID"
Processed by container ID 78a3e9b06b7f
# curl 10.0.0.4 | grep "container ID"
Processed by container ID 04e02b1731a0
在上面的输出中,因为服务器发现和负载均衡没有与Swarmkit集成,我们已经收到容器 IP地址发出的ping命令。
问题
我提出在Swarmkit覆盖网络中使用KV存储的需要的问题。这似乎是我的一个bug,又或许我丢失了一些选项。
总结
SwarmNext(Swarm 模式)是对原有Docker Swarm的巨大改善。在Docker中有服务对象将使缩放、滚动更新、服务发现、负载均衡和路由网等功能更容易实现,这也使得Swarm能够赶上Kubernetes之类的某些功能。Docker已经在1.12版中支持SwarmNext和Swarm,使得已经部署了Swarm的生产用户不会受到部分升级的影响。SwarmNext并不具有所有的功能,包括与Compose和存储插件的集成。不久这一点将被添加到SwarmNext。从长远看,我认为Swarm将会过时,而SwarmNext将会成为在Swarm中进行编排的唯一模式。Swarmkit作为一个开源项目,允许对Swarmkit进行独立开发,允许任何为分布应用开发编排系统的人将其作为一个独立模块进行使用。
本文作者Sreenivas Makam,由寄云科技翻译。欢迎关注寄云科技订阅号(neuclouddy),这里有最新云服务行业资讯,更有与PaaS、运维相关的技术干货!