调度是一种向处理资源分配工作载荷的方式。在分布式环境中,调度器格外为大家需要,尤其是那些提供扩展性,资源意识以及高效能特性的调度器。
单体调度器是单个进程实体,进行调度决策并完成需要被调度的任务的部署。这些任务可以是长期运行的服务器程序,短期存在的批处理命令,MapReduce查询,等等。
为了调度任务的决策,单体调度器需要:观察集群中资源的可用性(例如,CPU,内存等),锁住资源,调度任务并更新可用资源。
对于单体调度器而言,它很难一次处理一个以上的任务,因为每个调度实体中只有一个资源管理器实体。相反,避免并发能够使得系统更易设计,更易于理解。
对于单体调度器,这里有一些样本:
本文将涵盖2个基础单体调度器。
首先,让我们来看看fleet,一个面向 systemd 单元的调度器。systemd是一个高级init子系统,负责配置和启动Linux用户空间。每个单元都是一个独立的systemd配置文件,描述了你希望运行的进程。下文中,我们也会看到Swarm,Docker容器的一个调度后端。
从本质上说,fleet即集群的systemd。
fleet利用了systemd和 etcd 的优点,其中后者是CoreOS所使用的一个分布式key-value存储,用来创建分布式init系统。在调度一个systemd单元之前,fleet会判断哪个节点目前运行的单元文件最少,然后将下一个单元文件调向该节点。
不过,fleet不是一个具有资源意识的调度器。在进行systemd单元调度时,fleet并不将诸如CPU和内存等可用的系统资源纳入考虑范围。它只使用上述简单算法来进行调度。
我们可以在单元文件中规定一些约束。例如,我们可以声明一个单元文件应该运行在每个主机上。
如下是Fleet单元文件的一个范例,用以部署 Deis储存管理器 :
[Unit]
Description=deis-store-admin
[Service]
EnvironmentFile=/etc/environment
TimeoutStartSec=20m
ExecStartPre=/bin/sh -c "IMAGE=`/run/deis/bin/get_image /deis/store-admin` /
&& docker history $IMAGE >/dev/null 2>&1 || docker pull $IMAGE"
ExecStartPre=/bin/sh -c "docker inspect deis-store-admin >/dev/null 2>&1 /
&& docker rm -f deis-store-admin >/dev/null 2>&1 || true"
ExecStart=/bin/sh -c "IMAGE=`/run/deis/bin/get_image /deis/store-admin` /
&& docker run --name deis-store-admin --rm /
--volumes-from=deis-store-daemon-data /
--volumes-from=deis-store-monitor-data /
-e HOST=$COREOS_PRIVATE_IPV4 $IMAGE"
ExecStopPost=-/usr/bin/docker rm -f deis-store-admin
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
[X-Fleet]
Global=true
约束通过 X-Fleet
部分指定。这里有些指令是提供给fleet本身的,而剩余部分则是提供给systemd。比如,在上述例子中, X-Fleet
下 Global=true
部分告诉fleet,要在集群中的每个机器上调度(如,部署)该单元。
可以参照 单元文件与调度 来获取关于定制fleet单元文件的更多选项。
通常,你可以使用 fleetctl
命令来提交一个fleet单元。如果你正在使用 Deis ,你可以使用 deisctl
命令。
用户可以通过为fleetctl的 FLEETCTL_TUNNEL
(或deisctl的 DEISCTL_TUNNEL
)设置集群中任意CoreOS的IP,来指定自己需要通讯的fleet守护进程所在的主机。
如下命令将会在集群中安装一个fleet单元:
deisctl install <unit name>
如下命令将会运行单元:
deisctl start <unit name>
Swarm是Docker容器在集群中的一个调度后端。
由于Swarm通过Docker API工作,因此我们可以通过Docker client或者其它和 Docker Engine 通讯的工具,来调度集群中的容器。
Swarm是对 libswarm 项目的扩展。Swarm有一个swarm管理器,它能够和集群中每个节点上的swarm节点通讯。Swarm的优点是支持 过滤器 和描述如何优化一个容器在集群的调度方式的策略。
让我们看一个示例命令:
docker run -d --name bar -e affinity:container==foo bar:v1
在这里,我们通过设定 affinity:container==foo
,告诉Swarm将容器 bar
部署到容器 foo
所在的节点。
用户也可以选择指定软关联,只需使用 ~
,例如 affinity:container==~foo
。如果foo容器当前不再任何节点中,Swarm将会取消关联,并根据调度策略调度容器。当前,Swarm支持的调度策略有: spead , bin packing 和 random 。
缺省情况下, Deis 使用fleet后端。不过现版本的Deis亦支持Swarm。
想要安装Swarm,只需运行:
deisctl install swarm && deisctl start swarm
切换调度后端:
deisctl config controller set schedulerModule=swarm
单体调度器的设计限制了性能和吞吐量。
由于资源管理器和调度器位于同一进程,单体调度器对于集群中的资源动态变化并不敏感。且调度是紧耦合的,这也就限制了扩展性。比如,fleet只能够调度systemd单元,Swarm只能够调度docker容器。
fleet是相对底层的调度器,并且没有资源意识。因此并不建议在超过100个节点的集群中使用fleet。幸运的是,Deis V2将能够和Kubernetes协同工作,后者是一个更加高级的调度器。Swarm也有其自身的缺点,比如,在0.2版本中,Swarm不支持节点的故障切换。因此,当一个节点变得不可用时,Swarm不会为故障节点上的容器重新调度。
在下一篇文章中,我们将会介绍高级调度器,例如Kubernetes,Apache Mesos,Omega和Sparrow。同时,我们也会讨论这些工具,相较诸如Swarm和fleet之类的基础单体调度器所做的改进。
原文链接: Schedulers, Part 1: Basic Monolithic (翻译:孙科)