调度机制的主要功能是选择在哪个服务器上创建并启动一个容器。它是由一个装箱算法(packing algorithm)和过滤器(或标签)组合而成。每个Docker守护进程启动的时候都带着一组标签,像以下这样:
docker -d \
--label storage=ssd \
--label zone=external \
--label tier=data \
-H tcp://0.0.0.0:2375
然后,当开启一个Docker容器时,Swarm将基于过滤器选择一组服务器,然后根据调度机制来分配每次运行的命令。过滤器会告诉Swarm哪些服务器上的容器是可用的或是不可用的,之后调度器会把命令分发到可用的服务器上。以下是几个过滤机制:
约束(Constraint) 这是利用了一个Docker守护程序开始的标签。目前,它只支持'=',(译注:官方doc里是'==',请读者遵循最新的官方doc)但在将来它可能支持'!='。节点必须符合所有的由容器提供的约束以便能进行匹配调度。比如按照下面的例子来开启有一些约束的容器:
docker run -d -P \
-e constraint:storage=ssd \
-e constraint:zone=external \
-t nginx
类同(Affinity )
类同可以以两种方式工作:容器类同或镜像类同。为了在同一台主机上启动两个容器可以运行以下命令:
docker run -d -P \
--name nginx \
-t nginx
docker run -d -P \
--name mysql \
-e affinity:container=nginx \
-t mysql
由于Swarm并没有对镜像进行管理,设置类同镜像也是可行的。这意味着一个容器仅能在已包含镜像的节点上启动。这就避免了在开启一个容器之前需要在后台等待拉取镜像的过程。举个例子:
docker run -d -P \
--name nginx \
-e affinity:image=nginx \
-t nginx
端口(Port) 端口过滤可以防止在同一主机上任意两个具有相同静态端口映射的容器启动。这样做的意义很大,你不能重复在Docker主机上端口映射。例如,两个节点以-p 80:80开启不会被允许在同一Docker主机上运行。
健康状况(Healthy) 它阻止了对不健康节点进行调度。
一旦Swarm将主机列表限制在一组符合上述条件的节点上,它就会让对容器进行调度,从以上结点中选出一个,在上面创建并启动容器。目前以下调度是器内置的:
随机分配(Random) 将容器随机分布在可用的结点上。
装箱(Binpacking) 用容器将节点填满(每个容器得到的资源固定),然后再移动到下一个节点。如果在运行时需要动态地给容器分配资源,采用这个策略可能会使过程变得更复杂。这意味着即使为每个容器的内存和CPU设置上限,也并不能保证运行期间一切正常。我个人比较喜欢让容器彼此之间竞争,看哪个容器能得到资源。
还有一些其他的调度机制正在开发中,比如平衡策略以及添加Apache Mesos的特性。