蚁群优化算法的Docker集群调度策略*
2019-06-18李东光刘智平姜雨菲
李东光,刘智平,姜雨菲
(西安工业大学 计算机科学与工程学院,西安 710021)
容器技术在近年的软件部署方面为主要的新技术,Docker[1]作为一种典型的容器技术,其自带的集群编排工具Swarm在调度资源时存在负载不均,集群整体性能差的问题,无法完美实现负载均衡,在资源利用率和集群性能方面并不能很好的符合预期。
国内外对此问题有较多的研究,在资源调度方面,文献[2]基于原有的 Swarm 容器集群管理工具,另外加入权值调度模块。在接收到Client的请求时,利用权值调度模块根据各个节点的资源消耗情况计算出节点权值,按照约定,权值越高表名节点的总体资源占用率越大,鉴于此,权值调度模块会把新的容器放在权值最小的节点来实现集群负载均衡。此策略在一定程度上实现了容器集群的负载均衡,但是此策略只考虑到了整个容器的资源分配,并未对不同的资源类型做更为详细的权值计算,并不能保证所利用即为所分配。文献[3]在容器虚拟化中引入了机器学习算法,利用K-Medoid算法、分割周围类算法等实现了容器代理系统,此系统具有容器工作负载感知的能力,节约能耗的同时也保证了集群的整体性能。文献[4]基于自回归积分滑动平均模型提出了云计算负载预测模型,达到了91%的准确率。然而,计算学习调度策略在容器集群调度中能否发挥其优势需要视情况而定,机器学习算法是依托于大量的样本训练集,对于容器集群来说即是大量的时间序列和容器资源使用量,如此庞大的开销使得其优势并不是十分明显。
因此,文中综合各个调度算法的优劣,拟采用一种启发式智能算法蚁群算法[5-8](Ant Colony Optimization,ACO),其在解决这类组合优化的问题具有一定的优势,文中拟通过使用蚁群算法对部署Swarm集群调度进行改进,实现Swarm集群各节点主机任务相对均衡分布,同时提高集群的整体性能。
1 Docker和Swarm 集群
传统的虚拟机一般由两部分构成,虚拟硬件和操作系统;而Docker创建的虚拟机即容器[9]并不需要创建安装特定的操作系统和Hypervisor管理,而是直接共享主机操作系统的内核,用Host主机的硬件和操作系统来执行程序。由于容器没有中间件消耗资源,一定程度上提高了资源的利用率,两者的系统架构对比如图1所示。
图1 传统VM和Docker的比较
集群结构如图2所示,Swarm[10]使用标准的Docker API接口作为其前端访问入口,并以守护程序的形式运行,对来自Docker Client的指令信息进行配置,并最终以代理的形式将需要处理的信息发送给不同节点的Docker Daemon进行处理并返回响应。
Swarm中提供了三种不同的资源调度策略[11]Random、Spread和Binpack。Random策略采用随机分配容器的部署位置,这种调度方式有很大缺点,一般仅限于集群的测试;Spread策略按照各节点资源即内存和 CPU 内核数来决定部署的容器数量,此方式能够让容器相对均匀地分布在主机各个节点上;而Binpack策略会先将一个节点的资源用尽之后再向其他的节点部署容器,此方式调度可以充分使用每个节点资源,但会导致各节点任务负载严重不均,影响集群的整体性能表现。Swarm内置的这三种不同的调度方式,可以应用在一些对集群效率要求不高的应用中。但对于类似云平台的应用,对于集群的负载均衡,资源利用率要求较高,对集群的整体性能表现有一定的高要求,在这些情况下,Docker Swarm内置的调度策略有明显的缺陷[12]。
图2 Docker Swarm集群系统架构图
2 基于蚁群算法的调度优化设计
Docker集群是由2组节点即管理节点和工作节点组成。而管理节点也负责任务管理,包括调度决策。SwarmKit为Docker集群管理背后的真正引擎。开始调度之前,所有的工作节点将通过一组过滤器进行处理,例如Constraint Filter只允许满足指定约束的节点通过。之后使用调度算法ACO替代原始循环贪婪算法将任务组放入流水线调度,总体的结构如图3所示。
在Docker的最新版本中,提供了服务和任务的概念。服务由一个或多个任务组成。集群用户将通过向调度器提交一些任务来启动服务。调度器选择一组符合指定约束的节点,并将任务调度到这些节点。总是会同时安排一批任务,但不一定是同时完成所有任务。在每批任务中,都可以使用他们所要获取资源的信息来找到最佳方案,并使用ACO技术。
图3 ACO算法下的SwarmKit调度结构图
调度器目标是将任务放到可用资源上。他在每次调度时会使用可用资源。一个人工蚂蚁通过观察每一个资源的信息素轨迹来随机寻找资源。某个节点的每个资源的计算公式为
(1)
为了初始化每个节点的信息素轨迹,在循环贪婪算法中使用R(j),其简单地将每个任务放在循环模式的一个节点上,τ0,j=R(j)为每个节点的起始信息素。
每个概率的计算公式为
(2)
其中ηi为节点j的启发式值。
计算每个节点的概率p(t,j),选择下一个节点j
(3)
其中j∈P(k),q0为探索率。
下一步计算信息素消失。每个节点的信息素轨迹消失计算公式为
(4)
其中Δ表示信息素的变化,当一个任务被调度程序放置到一个特定的资源,Δ的值总是小于0。信息素利用式(4)计算,为了显著地减少所选节点的信息素水平,使其对下一个任务不那么重要,使得剩余的容器将被分配到整个资源中。
最佳的规划Pw采用式(5)从所有任务中选出最频繁规划。
(5)
在实现真正的调度程序之前,通过模拟输入数据并执行单元测试将其作为模拟运行,发现最佳规划的频率范围为0.35~0.70。
文中参数的选择通过大量的实验对比得来,经过测试,使得算法在收敛度,稳定性以及保障性能的基础上,α,β,ρ分别选择 0.7,0.3,0.6。
3 实验与分析
SwarmKit和Docker都是使用Go编程语言编写的。文中使用Go 1.6.2作为编译器,利用Docker支持的主要平台x86-64架构完成。通过在云提供商DigitalOcean上形成SwarmKit集群来进行实验。该集群由1个管理节点和5个在同一数据中心上运行的工作节点组成。表1为5个工作节点的资源配置情况。SwarmKit管理器将管理节点可用性设置为零,以防止将容器调度到自身。每个工作节点都连接到同一主机上的每个Docker引擎。实验一通过使用SwarmKit附带的原始循环贪婪算法实现完成,实验二通过使用ACO算法调度器的SwarmKit容器的修改版本完成。实验结果分别以 Spread和ACO表示。
表1 Docker主机各节点的资源配置
3.1 均衡性
选择部署普通的NGINX服务器作为调度任务,NGINX服务器的CPU和内存预留量分别为0.5和128 MB。在5个节点上部署了12个NGINX服务器任务,部署统一的任务可以很容易地观察结果的调度。图4和图5分别显示了由 Spread和ACO算法计算的调度计划。将最大资源节点即节点二进行资源归一化即为1。同样把每个NGINX服务器所占资源进行归一化处理。可以得到部署每个NGINX服务器所占资源为0.125,从图4和图5中可以看出每个节点部署的NGINX服务器个数,纵轴上的资源从式(1)中得出。
图4 Spread策略各节点任务分配
图4中,对于SwarmKit的Spread策略,将前10个任务平均分配给所有5个节点,对于最后2个任务,选择分别将它们放到节点2和节点4, 这导致节点2和节点4在每个节点上运行3个容器。
图5 ACO算法各节点任务分配
图5中,只有任务被放入每个512中MB节点,节点1和节点5。具有4GB规格的节点2和具有2GB规格的节点4分别用于调度4个任务。实际上,放置在所选计划中的序列Pw将任务放入节点2中,在节点4,节点2和节点3之间来回切换。节点3用于调度2个任务。
通过对比两个算法的任务调度可以看出ACO相对Spread实现了更好的均衡负载。
3.2 工作负载性能
任务分配的结果并不是主要问题。最终目标是提升集群的整体性能。因此,在部署之后,文中使用Apache Bench来测量NGINX服务器的性能。测试配置为“-c10-n1000”。
表2为ACO和Spread策略放置的每个 NGINX 容器压力测试数据。此处容器对应的两种算法中的容器可能不是同一节点的容器,只是为了统计整体性能。上一节使用ACO算法放置容器可以使任务更均匀分布,虽然,不能显示哪个容器在哪个主机节点上运行,但是通过对集群容器集群进行压力测试可以得出优劣,Spread中总负载为22 186.21,ACO中总负载为26 623.034,很明显,ACO算法调度的集群的整体压力测试性能要好于原始的调度性能。同样的环境下,基于ACO集群QPS相对Spread集群提高约20%。
表2 Docker集群下Spreed策略和ACO算法部署容器数据对比
4 结 论
目前在Docker主机中以循环方式分发容器,循环算法导致资源使用并不理想。文中提出了一种基于ACO的算法用在软件容器环境Docker中调度任务,发现Swarm的当前实现模型与ACO非常吻合,通过搭建容器集群进行任务调度分配资源,通过单元测试进行仿真,实施是可行的。
在相同配置下,文中提出的ACO算法的工作负载比Swarm算法放置的NGINX服务器快大约20%,优于原始调度算法。对于ACO算法,仍然有许多改进空间,例如对NGINX服务器特定参数的引入,将使调度程序对每个特定情况都能更好地工作。