1. 介绍

1.1 简介

Docker Swarm 是 Docker 官方编排(Orchestration)项目之一,负责对 Docker 集群进行管理。

Docker Swarm 是 Docker公司官方在 2014 年 12月初发布的一套管理 Docker 集群的工具。它将一群 Docker 宿主机变成一个单一的,虚拟的主Swarm 使用标准的 Docker API 接口作为其前端访问入口,换言之,各种形式的Docker 工具比如 Dokku,Compose,Krane,Deis,docker-py,Docker 本身等都可以很容易的与 Swarm 进行集成。

注意: docker swarm的功能在docker 1.12版本以后就已经集成进docker了,即swarm mode。所以新版本建议直接使用swarm mode

PS: 关于swarm mode欢迎查看我的另外一篇文章

1.2 结构

在使用 Swarm 管理docker 集群时,会有一个 swarm manager 以及若干的 swarmnode,swarm manager上运行 swarm daemon,用户只需要跟 swarm manager 通信,然后 swarm manager 再根据discovery service的信息选择一个swarm node 来运行container。值得注意的是 swarm daemon 只是一个任务调度器(scheduler)和路由器(router),它本身不运行容器,它只接受 Docker client 发送过来的请求,调度合适的 swarm node 来运行 container。这意味着,即使 swarm daemon 由于某些原因挂掉了,已经运行起来的容器也不会有任何影响。

有以下两点需要注意:

  1. 集群中的每台节点上面的 Docker 的版本都不能小于1.4
  2. 为了让 swarm manager 能够跟每台 swarm node 进行通信,集群中的每台节点的 Docker daemon 都必须监听同一个网络接口。

2. 安装使用

2.1 安装

docker pull swarm

使用命令确认安装成功

sudo docker run --rm swarm -v

2.2 开启docker node的2375端口

确保开启Docker的TCP连接端口。

PS: 需要被docker swarm管理的节点上的docker都需要开启2375端口。

#centos: 
vim /lib/systemd/system/docker.service
# 修改ExecStart所在的这一行为如下内容
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375  -H unix:///var/run/docker.sock 
# 重新启动服务
systemctl daemon-reload && service docker restart

#ubuntu: 
vim /etc/default/docker

OCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"

service docker restart 

2375为Docker默认的tcp通讯端口,稍后在使用主机连接时需要用到。

2.3 创建token

创建token可以获得一个token id用来标识docker集群。以后加入集群都会用到这个生成的token。

2.4 启动容器加入docker的swarm 集群

# 在10.45.10.31这台node上执行如下命令
docker run -d swarm join --addr=10.45.10.31:2375 token://745f039648eca0559ab694230a92abbe
# 在10.45.10.32这台node上执行如下命令
docker run -d swarm join --addr=10.45.10.32:2375 token://745f039648eca0559ab694230a92abbe

2.4 启动swarm manger

我这里使用10.45.10.31这台机器当做swarm manager

docker run -d -p 2376:2375 --name swarm_manager swarm manage token://745f039648eca0559ab694230a92abbe

在执行 Swarm manage 这条命令的时候,有几点需要注意的:

  1. 这条命令需要在充当 swarm 管理者的机器上执行
  2. Swarm 要以 daemon 的形式执行
  3. 映射的端口可以使任意的除了 2375 以外的并且是未被占用的端口,但一定不能是 2375 这个端口,因为 2375 已经被 Docker 本身给占用了。集群启动成功以后,现在我们可以在任何一台节点上使用 swarm list 命令查看集群中的节点了,本实验在 124 这台机器上执行 swarm list 命令:
docker run --rm swarm list token://745f039648eca0559ab694230a92abbe

2.5 使用swarm访问集群中的容器

# docker info查看集群中的容器,需要指定manager地址
docker -H 10.45.10.31:2376 info

3. swarm调度策略

容器调度策略可以在启动swarm manager的时候通过--strategy参数来指定

3.1 spread

使用spread策略,swarm会选择一个正在运行的container的数量最少的那个节点来运行container。这种情况会导致启动的container会尽可能的分布在不同的机器上运行,这样的好处就是如果有节点坏掉的时候不会损失太多的container。

3.2 binpack

binpack 则相反,这种情况下,swarm会尽可能的把所有的容器放在一台节点上面运行。这种策略会避免容器碎片化,因为他会把未使用的机器分配给更大的容器,带来的好处就是swarm会使用最少的节点运行最多的容器。

3.3 random(不建议使用)

随机选择节点来启动容器。

4. swarm过滤器

swarm 的调度器(scheduler)在选择节点运行容器的时候支持几种过滤器 (filter):
Constraint,Affinity,Port,Dependency,Health
可以在执行 swarm manage 命令的时候通过 --filter 选项来设置。

4.1 Constraint Filter

每个node上的docker实例启动的时候可以指定一个标签。修改/etc/default/docker文件中的DOCKER_OPTS选项:

# 指定一个标记为my-tag的docker实例
DOCKER_OPTS="-H 0.0.0.0:2375 -H unix:///var/run/docker.sock --label label_name=my-tag"

通过docker -H ip:2376 run 启动容器的时候可以指定容器运行在哪个标签的node上。

# 在my-tag这个标签的node上运行一个redis容器
docker -H 10.45.10.31:2376 run --name redis_1 -d -e constraint:label_name==my-tag redis

4.2 Affinity Filter

通过使用 Affinity Filter,可以让一个容器紧挨着另一个容器启动(简单来说就是和上一次启动的容器运行在同一个node上),也就是说让两个容器在同一个节点上面启动。

4.3 Port Filter

指定port来启动:

docker -H 192.168.1.83:2376 run -d -p 80:80 nginx

执行完这条命令,之后任何使用 80 端口的容器都是启动失败。