在虚拟化技术[1]的应用上, 存在移植性不方便和部署繁琐等问题, 容器技术的易迁移、轻量级和高效率等特性可以有效地改善问题[2]. 同时, 容器在持续部署和微服务等业务中利用率高, 可以提高科学计算领域的生产力[3]. Docker是容器技术的一个应用, 它成功地解决LXC (Linux container)集成度低和自动化水平低等问题[4]. 随着Docker的发展[5, 6]不少公司广泛地使用Docker技术, 例如: Redhat 、Google等[7], 成为现在最热门的开源应用容器引擎.
容器和组件一样需要管理和监控, 比如Docker命令行接口(command line interface, CLI)管理单个主机上的容器, 但是要满足在多个主机上部署管理容器则必须使用容器编排工具. 容器编排过程是指在大量机器集群上管理容器化应用程序, 一般涉及自动化应用管理的工具, 通过容器编排技术可以轻松完成部署容器、部署服务、扩展和调度. 使用容器编排工具不仅可以提高用户在开发、测试和部署时的效率, 还可以在管理容器、部署服务等业务上呈现出方便与高效等优点. 根据不同的架构环境, 越来越多的编排工具展现在大众面前, 其中有不少工具已经获得用户的认可和采用, 例如: OpenShift、Docker Swarm、Nomad、Open Nebula、Marathon、Kubernetes、Rancher和Cloudify. 其中以Kubernetes、Docker Swarm和Rancher这3个编排工具的使用率最高. Coasta等[8]研究容器编排系统中软件老化对Kubernetes的影响, Piedade等[9]为Docker的编排提供一个完整的视觉符号, 可以减少工作量、错误率和开发时间. 也可以利用最现代的技术和架构模式, 设计高效的云编译器. Heidari等[10]提出一种云编译器的架构设计, 它与Kubernetes等编排技术完全兼容, 提供更高层次的可扩展性、可靠性、安全性和可维护性. Rovnyagin等[11]提出一种系统性能的动态编排方法, 以增加数据处理系统的效能.
虽然现有的容器编排工具已经发展较为成熟, 它仍旧存在功能不够完善、部署繁琐、响应速度不够快和资料占用较多等问题. 当编排工具容量达到最大值时, 但是还有新工作节点想要继续进行工作, 那么需要删除其余某个不工作的节点, 释放一定的空间, 来达到新工作节点的空间需求. 算法上, Docker Swarm和Rancher默认使用传统式算法, 即删除最后一个插入的工作节点, 再插入新的工作节点. Kubernetes默认使用LRU (least recently used)算法来释放不工作的节点, 规则是删除最久未使用的工作节点. 传统式算法可能会导致删除的工作节点是最频繁使用的工作节点, 而真正需要释放的工作节点没有被删除. 例如: 插入工作节点1和工作节点2后已经达到了最大容量, 想要插入工作节点3时, 则需要默认删除工作节点2, 再插入工作节点3. 如果插入工作节点3后又需要使用工作节点2, 那么默认是再删除工作节点3, 插入工作节点2. 此过程繁冗, 一直在做插入工作节点和删除工作节点的重复工作, 浪费了资源, 而空闲的工作节点1才是应该被释放的. 如果一开始先删除了工作节点1, 那么集群内剩余了工作节点2和工作节点3可以交互工作, 省去了不必要的重复操作. 这种传统式做法, 不仅使得工作效率低下, 还浪费资源. 想要删除正确的工作节点, 必须制作相应的规则, 按照规则选择需要删除的工作节点. 为了改善这些问题, 提高开发人员和管理人员的工作效率, 实现更好的容器化, 本文提出将LRU算法融入Docker Swarm和Rancher中, 并且设计了LSD(least remaining space)和LRU-SD算法, LSD算法是删除剩余空间最少的工作节点, LRU-SD算法同时考虑了最近最久未使用和剩余空间两个指标, 然后将这两个算法融入Kubernetes、Docker Swarm和Rancher等3种编排工具. 本文做出的贡献有:
(1)设计LSD算法和LRU-SD算法, 优化Kubernetes、Docker Swarm和Rancher的释放节点过程.
(2)首次提出将LRU算法引用到Docker Swarm和Rancher, 改善编排工具的释放节点过程.
(3)比较LRU-SD算法、LSD算法和LRU算法, 发现三者都可以提高工作效率及资源使用率. LRU-SD算法的工作效率优于LSD算法和LRU算法.
首先在引言部分介绍容器技术、容器编排技术及工具, 提出目前编排工具存在的问题. 然后在相关工作部分, 详细介绍Docker、Kubernetes、Docker Swarm和Rancher. 在编排系统部分, 描述3种编排工具的部署过程, 列出传统式、LSD算法、LRU算法和LRU-SD算法的具体内容. 在实验分析部分, 比较不同算法在3种编排工具下的工作效率及资源使用率, 对实验结果进行分析与总结. 最后, 归纳本文与展望未来.
1 相关工作 1.1 Docker及容器编排技术Docker获得越来越多的用户喜爱, 性能高于虚拟机[12], 然而, 即便Docker容器具备启动时间短的优势, 也仍存在隔离性弱等安全威胁的困扰[13]. Docker采用C/S (client/server)模式的架构, 即客户端/服务器模式的架构. 其主要模块有Docker客户端、Docker主机和Docker镜像注册中心.
随着需要管理的节点和容器的增多, 手动管理便不能满足多个容器的管理. 所以, 需要一种集结容器、自动化和规模化于一体的集群管理平台[14], 即容器编排工具. 文献[15]通过虚拟机、容器结合YAML (YAML ain’t a markup language)和容器结合可视化等3种方式, 分别对部署的时间、服务启停的速度和扩展的速度进行测试, 结果发现容器编排可视化的方式效率最高, 甚至比传统虚拟机的方式提高一个到两个时间级别, 给开发人员带来极大的便利. 容器编排技术是组织多个容器的流程, 将部署、调度和管理等方面都成为自动化处理, 这样不只可以提升管理的效率, 还可以解决容器在管理和调度不便的问题, 并且提高安全性[16].
1.2 KubernetesKubernetes, 人们称为k8s, 数字8代替中间8个字符而形成. 它是由Google开发的开源容器编排工具[17], 用于容器云集群中自动部署与管理容器应用的编排系统[18]. Kubernetes有很多利于用户使用的优点, 首先它拥有许多的自动化操作, 表现在可以自动部署、自动弹性伸缩和自动扩展等. 并且, 还支持公有云、私有云和混合云等具备易于移植的特性[19]. Kubernetes主要由主节点和从节点所构成[20]. 节点即为主机, 可以是虚拟机或物理机.
Pod是最小的工作节点[21], 按照调度策略将pod部署到运行状况良好与最适宜的节点; 若没有合适的节点, 则将pod置于挂起状态, 直到出现合适的节点. 而controller manager会检测要控制的节点及容器的当前状态, 负责维护集群的状态. 当有容器停止运行时, 它可以进行故障检测或回滚等方式解决问题. 当容器创建完成后, Apiserver会自动调用Kubelet组件来启动容器, Kubelet还可以监视一个或多个容器组合在一起的共享资源pod, 并且负责维护容器的生命周期和节点间的通信[22].
1.3 Docker Swarm为了使Docker容器发挥更大的作用, 需要构建集群, 以便管理和强化功能. 作为编排工具的Docker Swarm即可管理集群中的镜像和容器. Docker Swarm包括Manager节点和Worker节点. Manager节点负责控制集群, 将请求从外部传到指定的Worker节点[23], Worker节点接收到任务并执行服务. Docker Swarm通过API (application programming interface)接口与外界联系, 而且轻量和操作简单, 所以有利于用户使用. 内置的策略有Spread、Random、和Binpack, Spread为默认的调度策略[24].
1.4 RancherRancher是一个企业级的、开源的容器编排工具, 它能够简单快捷的部署管理主机及容器. Rancher除了支持内置的Cattle编排环境之外, 还支持Kubernetes、Docker Swarm和Mesos. 用户可以使用它构建Kubernetes集群, 甚至直接导入已经存在的Kubernetes集群, 因此Rancher既能管理容器又能管理Kubernetes集群, 还可以对它们的健康状况进行监控. Rancher还提供可视化接口、内部包含应用商店、支持弹性伸缩、易于添加管理主机. 相较于其他的工具, Rancher不仅在添加单个主机时操作方便, 更在创建集群时节省很多的步骤. 缺点是, Rancher对Docker的安装版本要求严格, 不同版本的Rancher需要安装相对应的CentOS版本和Docker版本.
2 编排系统 2.1 编排框架本文提出一种新的想法, 在Docker Swarm和Rancher中运用LRU算法, 提高这两种工具在有限容量与数据较多时的响应速度, 并且设计LSD算法和LRU-SD算法, 并将这两种算法使用于3种容器编排工具. 编排整体架构图如图1所示. 用户通过API发送指令, 主节点中的controller manager和scheduler分别是维护集群的状态和负责资源的调度.
2.2 编排工具部署图2展示3个工具运行使用的主要步骤. 首先将所需的软件包通过FileZilla上传到虚拟机指定目录下, 并且在所有节点都安装Docker. 其次在主节点创建集群, 并将从节点加入集群. 然后在主节点和从节点拉取相应镜像, 并启动对应容器. 最后可通过浏览器访问容器编排工具的可视化界面, 在此界面可以对容器及节点做相应操作.
![]() |
图 1 编排系统架构图 |
下面分别是3种编排工具的详细部署步骤.
1) Kubernetes. 首先, 安装软件包. 在主节点和从节点上使用yum install <packages>命令安装etcd、Kubernetes、flannel软件包. 其次, 修改相应的配置文件. 然后, 构建集群. 成功部署集群后输入kubectl get nodes 命令可查看集群中节点IP及节点状态. 第四, 通过启动pod部署可视化界面. 先创建yaml文件, 进行服务名称name、镜像image和IP地址等的设置, 之后使用Docker pull命令拉取所需镜像, 并且启动yaml文件. 最后, 启动可视化界面. 通过kubectl get pod -o wide --all-namespaces命令可查看pod启动状态, 启动状态为running时, 可通过浏览器访问可视化界面.
2) Docker Swarm. 首先, 在Manager节点创建Swarm集群[25]. 其次, 在Worker节点上输入加入集群的命令, 将其加入Swarm集群. 然后, 输入Docker node ls可查看集群中节点名称及节点状态, 集群搭建成功. 最后, 部署Portainer可视化界面, 拉取Portainer镜像后启动一个容器, 启动成功后可通过浏览器访问Portainer可视化界面.
3) Rancher. 首先, 拉取Rancher镜像. 然后, 成功启动一个容器. 最后, 通过浏览器访问可视化界面, 可将浏览器内自动生成的命令复制到虚拟机上运行, 从而在Rancher工具中成功添加主机.
![]() |
图 2 容器编排工具部署序列图 |
2.3 符号及公式定义
本文涉及的符号及定义如表1.
定义1. 设插入工作节点的个数为
根据定义1可以计算链表中工作节点总个数, 如式(1):
δall=∑ϑ1τ(x)−∑Ω1τ(x) | (1) |
定义2. 设多个工作节点的总容量为
![]() |
表 1 符号定义表 |
根据定义2, 可以得出
Φre(工作点i)=Φ(工作点i)−Φcurrent(工作点i) | (2) |
定义3. 设
结合定义2的结果, 可以得出最小剩余空间的值, 如式(3):
γ=min(Φre(工作点1), ⋯, Φre(工作点n))=min(Φ−Φcurrent(工作点1), ⋯, Φ−Φcurrent(工作点n)) | (3) |
当容器满时, 传统算法选择删除最后一个进入容器的节点. LRU算法选择最近最久未使用的节点进行删除, LSD算法选择当前剩余容量最小的节点进行删除, LRU-SD算法先考虑最近最久未使用的节点. 如果存在多个满足要求的节点, 则计算这些满足要求的节点的剩余容量, 选择剩余容量最小的进行删除. 在这个过程发现, 传统算法对删除容器的选择并没有采用较优的策略, LRU算法根据节点使用的频次进行待删除节点的选择, 将使用频次低的节点删除. 理论上, 被删除的节点在后面再次使用的概率低, 因此会降低换页率. LSD算法根据节点的剩余容量进行待删除节点的选择, 优先删除剩余容量少的节点. 留下的节点因为剩余容量大, 再次需要被删除的概率变低, 因此降低换页率. LRU算法和LSD算法分别从节点的调用频次和剩余空间进行考虑. 同时, 本文结合LRU算法和LSD算法, 提出LRU-SD算法, 该算法同时考虑调用频次和剩余空间, 有效降低换页率. 经过实验验证, 它优于传统算法、LRU算法和LSD算法.
2.4.1 传统式算法在Docker Swarm和Rancher中, 发现工作节点的空间不足, 就需要释放空间以便后续的工作. 默认的做法是释放最后一次插入的工作节点.
图3显示传统式算法, 当有足够容量满足需要时, 则可以直接插入新的工作节点, 如情况1到情况2的过程. 当超出最大容量时, 想要插入新的工作节点, 则先删除最后插入的工作节点, 然后再插入新的工作节点, 如情况3-1到情况4-1的过程. 具体情况介绍如下.
![]() |
图 3 传统式、LRU、和LSD算法过程解释图 |
情况1. 链表中存在4个正常工作的节点.
情况2. 将工作节点5插入此链表中.
情况3-1. 将工作节点5删除, 其余4个工作节点正常工作.
情况4-1. 工作节点5删除后, 再插入工作节点6.
2.4.2 LRU算法当超出最大容量时, Kubernetes默认使用的是LRU算法, 释放最久未使用的工作节点, 来满足新任务的需求. LRU算法是利用双向链表和哈希表组成的数据结构, 首先利用双向链表进行存储, 其优势是通过prev指针和next指针可以得出当前元素的前驱元素和后继元素, 方便对元素增加和删除等操作. 其次是利用哈希表进行查找, 其优势是能够快速根据key值直接访问value的地址. LRU算法将两者融合后, 可以快速地实现查询、插入或删除的操作, 时间复杂度为O(1). 图3的LRU算法, 具体情况介绍如下.
情况1. 链表中存在4个正常工作的节点.
情况2. 将工作节点5插入此链表中.
情况3-2. 再次调用工作节点1, 相当于先删除工作节点1, 然后将工作节点1再插入链表中.
情况4-2. 将最久未使用的工作节点删除, 即删除工作节点2.
情况5-2. 插入工作节点6.
当使用某个工作节点之后, 便会直接被移到链表最后端, 如情况3-2所示. 此时, 链表前端便只剩下最久未使用的工作节点. 当容量不足时, 需要删除最前端的工作节点, 释放最久未使用的工作节点, 然后再插入新的工作节点, 如情况4-2到情况5-2所示.
经过对LRU算法过程的归纳, 伪代码如算法1.
算法1. LRU算法
输入: LRU(key, value, hash, list2, Max)
//数据关键字key; 数据值 value; 数据查询集 map; 数据删除插入集 list2; 最大容量Max; node 节点
输出: LRU结构体Tree
1. Procedure list2(key, value)
2. {
3. node=get(key, value);
4. //调用get函数, 查找数据是否存在, 若存在返回相应的节点地址;
5. if exist (node != null){
6. hash.delete(node) //删除node节点, 节点个数减1;
7. hash.insert(node) //插入node节点到尾部, 节点个数加1;
8. }else {
9. node = Node.create(key, value) //定义一个新的Node;
10. All.sum //利用式(1)计算当前链表中总个数num;
11. if (num>Max){
12. hash.delete //删除头部的工作节点, 节点个数减1;
13. hash.insert(node) //插入新的工作节点到尾部, 节点个数加1;
14. }
15. else
16. hash.insert(node) //直接插入新的工作节点到尾部, 节点个数加1;
17. }
18. End list2
19. Function put(key, value)
20. node = hash.get(key)
21. if (key != null){
22. Node.value = value;
23. return node;
24. }
25. else
26. return null;
27. End put
2.4.3 LSD算法LSD算法的设计思想为删除剩余空间最少的工作节点, 释放此工作节点, 来满足新任务的空间需求. 此算法使用双向链表方便数据的查询、插入和删除, 并且时间复杂度为O(1), 容易实现. LSD算法解释如图3所示, 具体情况描述如下.
情况1. 链表中存在4个正常工作的节点, 使用双链表存储这4个工作节点.
情况2. 将工作节点5插入此链表中, 此时链表未满, 插入成功. 将工作节点6插入链表中, 此时链表已满, 插入失败, 采用LSD算法进行节点删除后, 再进行插入.
情况3-3. 计算链表中5个工作节点的剩余空间, 5个工作节点的剩余空间分别是100 MB、110 MB、97 MB、86 MB、93 MB.
情况4-3. 删除5个工作节点中剩余空间最小的节点, 即工作节点4.
情况5-3. 将新的工作节点6插入链表中, 此时插入成功.
当超出最大容量时, 需要先计算各个工作节点的剩余空间, 然后选出所有工作节点中剩余空间最少的工作节点, 并且删除此工作节点释放空间, 最后再插入新的工作节点即可, 如情况3-3到情况5-3的过程.
根据对LSD算法过程的归纳总结, 伪代码如算法2.
算法2. LSD算法
输入: LSD(key, value, hash, list2, Max)
//数据关键字key; 数据值 value; 数据查询集 map; 数据删除插入集 list2; 最大容量Max; node 节点
输出: LSD结构体Tree
1. Procedure list3(key, value)
2. {
3. node=get(key, value);
4. //调用get函数, 查找数据是否存在, 若存在返回相应的节点地址;
5. if exist (node != null){
6. hash.delete(node) //删除node节点, 节点个数减1;
7. hash.insert(node) //插入node节点到尾部, 节点个数加1;
8. }else {
9. node = Node.create(key, value) //定义一个新的Node;
10. All.sum //利用式(1)计算当前链表中总个数num;
11. if(num>Max){
12. nodeF=re(hash);hash.delete(nodeF) //删除nodeF节点, 节点个数减1;
13. hash.insert(nodeF) //在删除的位置上插入新节点, +1, 节点个数加1;
14. }
15. else
16. hash.insert(node) //直接插入新的工作节点到尾部, 节点个数加1;
17. }
18. End list3
19. Function put(key, value)
20. node = hash.get(key)
21. if (key != null){
22. Node.value = value;
23. return node;
24. }
25. else
26. return null;
27. End put
28. Function re(key)
29. All.remainder //利用式(2)求出节点对应的剩余空间;
30. All.least //利用式(3)选出最少剩余空间的节点key;
31. return least
32. End re
2.4.4 LRU-SD算法LRU-SD算法的设计思想同时考虑了节点的剩余空间和最近使用情况. 当没用空闲工作节点时, 首先选择最久未使用的节点释放, 当出现多个最久未使用的节点时, 考虑这些节点当前剩余的工作空间, 释放剩余工作空间最小的节点, 如式(4)所示:
β={α,num(αi)=1αi,if(φre(αi)=min(φre(α1),φre(α2),φre(α3)⋯)) | (4) |
其中, αi表示最近最久未使用的工作节点, num(α)表示最近最久未使用的工作节点的数量. β表示要删除的节点. 此算法使用双向链表方便数据的查询、插入和删除, 并且时间复杂度为O(1), 容易实现. LRU-SD算法解释如图4所示, 具体情况描述如下.
![]() |
图 4 LRU-SD算法解释图 |
情况1. 链表中存在4个正常工作的节点, 使用双链表存储这4个工作节点.
情况2. 将工作节点5插入此链表中. 此时, 链表处于未满状态, 可以直接插入.
情况3. 此时要插入工作节点6, 求出当前最久未使用的工作节点, 若存在多个工作节点, 进入情况4; 若只存在一个当前最久未使用的工作节点, 选中该节点, 进入情况5.
情况4. 计算所有当前最久未使用的工作节点的剩余空间, 并选中所有当前最久未使用的工作节点中剩余空间最小的节点. 在图4中, 存在多个最近最久未使用的节点, 即节点1和节点2. 然后分别计算节点1和节点2的剩余空间, 节点2的剩余空间小于节点1, 则删除节点2.
情况5. 删除选中的节点.
情况6. 将新的工作节点6插入链表中.
当超出最大容量并存在多个最久未使用的工作节点时, 计算所有当前最久未使用的工作节点的剩余空间, 并选中所有当前最久未使用的工作节点中剩余空间最小的节点, 删除该节点.
当在同一时间有多个节点进入, 并在之后的时间里没有被使用时, 这多个节点会同时成为最久未使用的节点. 在上面3个算法中, 由于存储节点的数据结构的局限性, 无法找出这多个节点, 所以本文重新定义一个数据结构来存储同时进入链表的节点, 即节点集nodes, 在节点集中可以存储多个节点, 在同一个节点集中的节点就是同时进入的节点. 其他操作同上述算法一样. LRU-SD算法的流程图如图5所示.
根据对LRU-SD算法过程的归纳总结, 伪代码如算法3.
算法3. LRU-SD算法
输入: LRU-SD(key, value, hash, list4, Max)
//数据关键字key; 数据值 value; 数据查询集 map; 数据删除插入集 list4; 最大容量Max; node 节点
输出: LRU-SD结构体Tree
1. Procedure list4(key, value)
2. {
3. node=get(key, value);
4. //调用get函数, 查找数据是否存在, 若存在返回相应的节点地址;
5. if exist (node != null){
6. hash.delete(node) //删除node节点, 节点个数减1;
7. hash.insert(node) //插入node节点到尾部, 节点个数加1;
8. }else {
9. node = Node.create(key, value) //定义一个新的Node;
10. All.sum //利用式(1)计算当前链表中总个数num;
11. if (num>Max){
12. if (nodes.num>1){//当前最久未使用的节点有多个
13. nodeF=re(hash);//找当前最久未使用的节点中剩余空间最少的节点
14. node.delete(nodeF) //删除keyF节点, −1;
15. node.insert(ndoe) //在删除的位置上插入新节点, +1;}
16. else{//只有一个最久未使用节点, 直接删除该节点
17. hash.delete //删除头部的工作节点, −1;
18. hash.insert(node) //插入新的工作节点到尾部, +1;} }
19. else
20. hash.insert(node) //直接插入新的工作节点到尾部, 节点个数加1;
21. }
22. End list4
23. Function put(key, value)
24. node = hash.get(key)
25. if (key != null){
26. Node.value = value;
27. return node;
28. }
29. else
30. return null;
31. End put
32. Function re(key)
33. All.remainder //利用式(2)求出节点对应的剩余空间;
34. All.least //利用式(3)选出最少剩余空间的节点key;
35. return key;
36. End re
![]() |
图 5 LRU-SD算法流程图 |
3 实验与分析
本节使用传统式算法、LSD算法、LRU算法和LRU-SD算法运行程序后, 然后对Kubernetes、Docker Swarm和Rancher产生的影响做实验与分析. 实验包括对响应时间、CPU使用率和内存占用率的测试, 以此分析和比较传统式、LSD算法、LRU算法和LRU-SD算法的区别. 表2为相关的实验环境及软件版本.
![]() |
表 2 实验环境及软件版本说明 |
3.1 测试实验
测试实验分成3个部分, 第1部分是3个工具在传统式、LSD算法、LRU算法和LRU-SD算法启动容器的时间响应测试. 依照cAdvisor[26]有收集、处理和导出资源使用和网络统计等关于容器信息的功能[27]. 第2部分和第3部分是利用cAdvisor对Kubernetes、Docker Swarm和Rancher等3种工具进行监控, 获取CPU和内存的占用情况. 通过CPU和内存的测试, 对比这3种编排工具的资源占用情况, 针对使用传统式、LSD算法、LRU算法和LRU-SD算法对编排工具资源使用率的影响.
3.1.1 响应时间测试分别使用3个工具来连续启动10个容器, 比较这3个工具在传统式、LSD算法、LRU算法和LRU-SD算法下启动容器所花费的时间. 实验中启动容器的同时, 勾选启动前自动拉取镜像的选项. 成功启动容器后, 在3个虚拟机终端输入查看容器详细信息的命令, 可以查看对应容器的详细信息, 其中包括创建完成时间和开始运行时间. 查看Docker Swarm和Rancher启动的容器信息需要输入Docker inspect <容器ID>命令, 而查看Kubernetes启动的容器信息则要输入kubectl describe pods <容器NAME>. 由于响应时间即为开始运行时间和创建完成时间的差值, 能够轻易地比较3个工具在不同算法启动容器的速度快慢. 对应的测试结果如 图6所示.
依据测试实验, 得出各个工具在启动相同数量容器时的响应时间. 结果表明, 使用传统式算法时, Docker Swarm和Rancher的图线呈上升趋势. 使用LSD算法和LRU-SD算法时, Kubernetes的图线呈下降趋势, Docker Swarm和Rancher的图线较平稳. 使用LRU算法时, Kubernetes的图线比使用LSD算法下降幅度更大, Docker Swarm和Rancher的图线整体呈平稳状态, 并且比使用LSD算法时的整体响应时间更短. 当启动的容器数目较少时, Kubernetes的响应时间比其他两种工具的响应时间更长. 使用传统式算法时, 随着启动容器的数目越来越多, Docker Swarm和Rancher的响应速度却越来越慢. 而使用LSD算法和LRU算法时, 当启动容器的数目增多, Kubernetes的响应速度越来越快, Docker Swarm和Rancher的响应速度基本保持不变. 因此, Kubernetes更适宜于在容器或主机多的情况下使用, 而Docker Swarm和Rancher则在容器或主机较少的情况下表现更出色. 通过式(5)可以计算出3种工具分别在使用不同算法时的平均响应时间.
ˉt=∑10i=1ti10 | (5) |
![]() |
图 6 启动容器的响应时间 |
式(5)计算Kubernetes使用LRU-SD算法、LSD算法和LRU算法的
图7展示3种工具在不同算法时的CPU测试结果. 结果显示, 使用传统式算法时, 图7(b)的Docker Swarm在CPU的使用率为15%左右时会趋于平稳; 图7(c)的Rancher在CPU的使用率为图7(b)的Docker Swarm的2倍左右趋于平稳. 使用LSD算法时, 图7(a)的Kubernetes有较大的波动, 后在45%左右趋于平稳, 总体占用较高; 图7(b)的Docker Swarm在CPU使用率波动介于5%–15%之间, 总体占用较少. Rancher的CPU使用率12%–36%范围内波动. 使用LRU算法和LRU-SD算法时, Kubernetes整体在20%–30%之间浮动, 基本平稳. Docker Swarm开始在5%–15%范围内波动, 后面在7%左右趋于平稳. Rancher整体稳定在12%.
根据式(6)求出Kubernetes、Docker Swarm和Rancher这3个工具, 使用不同算法时的CPU平均使用率.
ˉn=15(4∑T=020T+20∑t=20T+1nt20) | (6) |
根据式(6)求出Kubernetes在使用LRU-SD算法、LSD算法和LRU算法的CPU平均使用率分别为23.2%、44.8%和25.2%, 使用LSD算法比使用LRU算法多1倍; Docker Swarm在使用传统式、LSD算法、LRU-SD算法和LRU算法的CPU平均使用率分别是15.1%、11.6%、9.1%和8.2%, CPU平均使用率逐渐降低, 总体差距不大; Rancher在使用传统式、LSD算法、LRU-SD算法和LRU算法的CPU平均使用率分别是39.7%、25.6%、15.3%和14.1%, CPU平均使用率逐渐降低, 传统式算法和LRU-SD算法差距最大. 根据CPU测试以及比对均值使用率可知, 无论是使用哪种算法, Kubernetes的CPU平均使用率最大, Docker Swarm的CPU平均使用率最小. 并且Kubernetes使用LRU算法比使用LSD算法的CPU使用率更低. Docker Swarm和Rancher使用LSD算法和LRU算法的CPU使用率都比传统式低, 其中使用LRU算法的CPU使用率最低.
![]() |
图 7 CPU使用率图 |
3.1.3 内存测试
图8展示3种工具在使用不同算法时的内存占用测试. 结果显示, 使用传统式算法时, 图8(b) Docker Swarm的内存占用在39%处基本稳定, 小范围内波动; 图8(c) Rancher的内存占用在45%处上下波动, 与图8(b)的Docker Swarm差距不大. 使用LSD算法时, 图8(a) Kubernetes和图8(b) Docker Swarm的内存占用存在上下浮动; 图8(c)的Rancher的内存变化平稳. 使用LRU算法时, 图8(a) Kubernetes的内存变化介于48%和51%; 图8(b)的Docker Swarm在36%左右, 小范围内波动; 图8(c) Rancher在42%左右, 小范围内波动.
此实验设定的内存为1024 MB. 根据式(5)求出Kubernetes、Docker Swarm和Rancher这3个工具在使用不同算法时的内存平均占用率. Kubernetes在使用LSD算法、LRU-SD算法和LRU算法时的内存平均占用率都在50%左右; Docker Swarm在使用传统式、LSD算法、LRU-SD算法和LRU算法时的内存平均占用率介于35%和39%, Rancher在使用传统式、LSD算法、LRU-SD算法和LRU算法均比Docker Swarm大6%左右. 根据内存测试以及比对内存均值占用率可知, 无论是使用哪种算法, Kubernetes的内存平均占用率最大, Docker Swarm的内存平均占用率最小. 并且Kubernetes使用LRU算法比使用LSD算法的内存平均占用率更低. Docker Swarm和Rancher使用LSD算法和LRU算法的内存平均占用率都比传统式低, 其中使用LRU算法的内存平均占用率最低.
![]() |
图 8 内存占用率图 |
3.2 实验分析与总结 3.2.1 内存测试
针对响应时间的测试实验做出分析, 由图9可以明显看出, Rancher的响应速度最慢, 但是经过对算法的改进, 有效缩短Rancher与其他两种工具在响应速度上的差距. 使用LSD算法、LRU-SD算法和LRU算法的响应速度都比使用传统式算法快, 其中以LRU-SD算法的速度最快. Kubernetes使用LRU-SD算法比LSD算法的
![]() |
图 9 响应时间对比图 |
3.2.2 分析CPU使用率及内存占用率
根据各个工具在使用不同算法时的CPU使用率和内存占用率, 制成表3, 由此看出3种工具中Kubernetes的CPU使用率和内存占用率都为最高, 说明Kubernetes资源占用率比其他两种工具多, 所以Kubernetes的成本比其他两种工具的成本高. 而Docker Swarm的资源占用最少, 成本最低.
![]() |
表 3 性能对比表 (%) |
表3显示, Kubernetes使用LRU算法比LSD算法的CPU平均使用率大约低1/5; Docker Swarm使用传统式算法、LSD算法、和LRU算法的CPU平均使用率, 呈现逐渐递减趋势, 递减3.5%左右; Rancher使用传统式算法、LSD算法、和LRU算法的CPU平均使用率, 呈现逐渐递减趋势, 递减13%左右. 这说明LSD算法和LRU算法都可以提升CPU的使用率, 以LRU算法的提升效果较好, 对Kubernetes的CPU使用率影响最大, 对Docker Swarm的影响最小. 在3种编排工具中, LRU-SD算法的CPU平均使用率仅仅略低于LRU, 同时LRU-SD算法需要额外的空间存储节点间, 在内存使用率上比LRU和LSD算法略高.
从内存平均占用率来看, Kubernetes使用LRU算法比LSD算法的内存平均占用率低2.4%; Docker Swarm使用传统式算法的内存平均占用率最高, 使用LRU算法的内存平均占用率最低, 使用LRU算法比LSD算法低2.2%; Rancher使用LSD算法和传统式算法的内存平均占用率相差不大, 使用LRU算法的内存平均占用率最低, 约为3%. 说明LSD算法和LRU算法都可以提升内存使用率, 其中LRU算法提升效果更好, 但是对3种工具的影响效果相差不大.
经过上述实验发现, LSD和LRU算法无论在速度上还是CPU和内存使用上均优于传统算法, 并且LRU算法作为一种经典算法, 在应用于容器时依然具有极大的优势. 但是, 本文考虑到当同一时刻有多个最近最久未使用的节点时, LRU算法仅是随机删除一个节点, 但是这些节点之间的剩余容量并不相同, 总希望删除剩余容量最小的节点, 因为这样可以延缓节点满时需要添加新的节点的情况. 因此, 本文将新提出的LSD方法与LRU方法相结合, 当出现多个最近最久未使用的节点时, 删除剩余空间最少的节点, 以此提高容器的使用效率, 并且混合后的方法与LSD方法相比, 仅需要计算最近最久未使用的节点的剩余空间即可, 不需要计算全部节点的剩余空间, 减少了计算量.
本次实验的前提是同时有多个节点加入容器, 这样会产生多个最近最久未使用的节点, 在该前提下, 探究LRU、LSD、和LRU-SD等3种方法的内存使用率、CPU使用率和换页率. 与LRU方法和LSD方法相比, LRU-SD方法需要记录同时进入容器的节点, 在本次实验中使用链表加标志的方式进行记录, 这就需要新的存储空间, 所以在内存使用率上LRU-SD方法明显高于LRU和LSD方法. 但是通过增加内存记忆同时进入容器的节点, 再从中选出剩余空间最小的节点进行删除, 可以降低换页率, 提高容器的使用效率.
综上所述, 使用LSD算法和使用LRU算法的编排工具比使用传统式算法的编排工具所占资源少, 其中使用LRU算法的编排工具降低的资源占用最大. 说明LSD算法和LRU算法都可以提高资源使用率, 而且LRU算法提升资源使用率效果最好, 尤其是对提高CPU的使用率最有效. LRU-SD算法在内存占用率上比其他算法略高, 并且可以有效降低CPU的使用率.
3.2.3 功能分析从工具的部署特性, Kubernetes是应用的部署, Docker Swarm是容器的部署, 而Rancher属于容器化组件. 在安装复杂度方面, Kubernetes安装过程复杂, Docker Swarm和Rancher的部署步骤简单. 从功能方面上看, Kubernetes、Docker Swarm和Rancher有很多相同点和不同点. 首先3个工具都有自动化部署、支持负载均衡和监测容器健康状况的功能, 这些功能都为编排工作提供便利. 此外, 这3种工具也有很多的不同点, 表4显示它们的功能归纳与对比.
![]() |
表 4 3种编排工具功能对比 |
功能对比显示, Rancher不支持灰度发布, Kubernetes和Docker Swarm支持灰度发布, 其中Kubernetes对灰度发布的支持度最高, 可以尽量避免新版本带来的风险. 然后Kubernetes和Rancher都可以回滚到特定的版本, 而Docker Swarm不支持此功能, 只能回滚到上一次的状态. 在弹性伸缩的功能中, 3个都支持手动伸缩, 但是只有Kubernetes还支持自动伸缩. 特别的是, Docker Swarm没有内置的可视化界面, 需要进行单独部署. Rancher提供应用模板, 简化复杂应用. 整体上, Kubernetes在功能性上较其他两种更有优势, 集群管理能力更强[28]. 并且在文献[29]中, 通过在Kubernetes和Docker Swarm上运行服务来对比, 也能够证明Kubernetes功能性确实更强.
3.2.4 实验总结经过对使用不同算法的编排工具的比较, 验证LSD算法、LRU-SD算法和LRU算法不仅能提高编排工具在启动容器时的响应速度, 还可以提升编排工具的资源使用率, 主要包括CPU使用率和内存占用率. 其中LRU-SD算法对提高工作效率、提升资源使用率的效果最好. 并且3种算法的时间复杂度都为O(1), 因此3种算法容易实现.
通过对伸缩、回滚功能、反应速度、CPU和内存使用率的性能比较, 发现Kubernetes在灰度发布和弹性伸缩的功能性更强, 并且在开始时响应速率较慢, 而启动大规模容器时速率明显加快, 但是它占用的CPU和内存都相对较多. Docker Swarm和Rancher比Kubernetes部署使用更简单[30], 且占用的CPU和内存较少, 其中Docker Swarm占用最少. 但是Docker Swarm和Rancher只在小规模容器时速率快、凸显优势. 3个工具中只有Rancher可以直接创建复杂的应用, 节省时间. 综上所述, Kubernetes擅长管理大规模和高可用的容器及集群, 虽然部署过程的复杂且耗时, 但是它的使用更广泛, 并且功能性更强[31]. Docker Swarm和Rancher适合管理小规模集群, 安装简单, 启动速度快, 其中Rancher还更适合在执行复杂的服务时使用. 3种工具各有优势, 用户应根据不同需要合理选择适宜的工具.
在实验的最后将LRU算法与LSD算法相结合, 借助经典算法的普适高效率以及LSD算法在特殊情况下具有的优势, 进一步完善LRU算法, 降低容器的换页率.
4 结语容器编排工具和可视化界面极大地提高服务生成效率. 容器编排工具为容器的自动化和规模化提供保障. 本文将LRU算法引用到Docker Swarm和Rancher中, 提出LSD算法和LRU-SD算法并用于3种编排工具中, 来释放不工作的节点. 然后验证这种做法在有限空间中可以提高编排工具响应速度和资源使用率, 提升工作效率.
基于容器和编排的快速发展, 安全性问题俨然成为人们关心的焦点. 未来, 可以继续对提高编排工具自身安全性的研究. 此外, 延续微服务架构的模式, 更多地将容器化应用到大型自动化的制造产业, 发展快速更新软件的过程.
[1] |
Uhlig R, Neiger G, Rodgers D, et al. Intel virtualization technology. Computer, 2005, 38(5): 48-56. DOI:10.1109/MC.2005.163 |
[2] |
彭博, 杨鹏, 马志程, 等. 基于Docker的ARM嵌入式平台性能评测与分析. 计算机应用, 2017, 37(S1): 325-330. |
[3] |
徐蕴琪, 黄荷, 金钟. 容器技术在科学计算中的应用研究. 计算机科学, 2021, 48(1): 319-325. DOI:10.11896/jsjkx.191100111 |
[4] |
应毅, 刘亚军, 俞琰. 利用Docker容器技术构建大数据实验室. 实验室研究与探索, 2018, 37(2): 264-268. DOI:10.3969/j.issn.1006-7167.2018.02.064 |
[5] |
Merkel D. Docker: Lightweight Linux containers for consistent development and deployment. Linux Journal, 2014, 2014(239): 2. |
[6] |
Kang DK, Choi GB, Kim SH, et al. Workload-aware resource management for energy efficient heterogeneous Docker containers. Proceedings of the 2016 IEEE Region 10 Conference. Singapore: IEEE, 2016. 2428–2431.
|
[7] |
武志学. 云计算虚拟化技术的发展与趋势. 计算机应用, 2017, 37(4): 915-923. |
[8] |
Costa J, Matos R, Araujo J, et al. Software aging effects on Kubernetes in container orchestration systems for digital twin cloud infrastructures of urban air mobility. Drones, 2023, 7(1): 35. DOI:10.3390/drones7010035 |
[9] |
Piedade B, Dias JP, Correia FF. Visual notations in container orchestrations: An empirical study with Docker compose. Software and Systems Modeling, 2022, 21(5): 1983-2005. DOI:10.1007/s10270-022-01027-8 |
[10] |
Heidari SM, Paznikov AA. Multipurpose cloud-based compiler based on microservice architecture and container orchestration. Symmetry, 2022, 14(9): 1818. DOI:10.3390/sym14091818 |
[11] |
Rovnyagin MM, Shipugin VA, Ovchinnikov KA, et al. Intelligent container orchestration techniques for batch and micro-batch processing and data transfer. Procedia Computer Science, 2021, 190: 684-689. DOI:10.1016/j.procs.2021.06.079 |
[12] |
邓伟健, 陈曦. 基于时变资源的容器化虚拟网络映射算法. 计算机应用, 2022, 42(2): 550-556. |
[13] |
边曼琳, 王利明. 云环境下Docker容器隔离脆弱性分析与研究. 信息网络安全, 2020, 20(7): 85-95. DOI:10.3969/j.issn.1671-1122.2020.07.010 |
[14] |
王宝生, 张维琦, 邓文平. 面向大规模容器集群的网络控制技术. 国防科技大学学报, 2019, 41(1): 142-151. DOI:10.11887/j.cn.201901020 |
[15] |
张丽敏, 高晶, 李务斌, 等. 微服务环境下容器编排可视化实践研究. 计算机工程与科学, 2019, 41(8): 1366-1373. DOI:10.3969/j.issn.1007-130X.2019.08.005 |
[16] |
李华东, 张学亮, 王晓磊, 等. Kubernetes集群中多节点合作博弈负载均衡策略. 西安电子科技大学学报, 2021, 48(6): 16-22, 122. DOI:10.19665/j.issn1001-2400.2021.06.003 |
[17] |
韩宁. 云计算虚拟化技术的发展与趋势. 电子技术与软件工程, 2018(13): 158.
|
[18] |
孔德瑾, 姚晓玲. 面向5G边缘计算的Kubernetes资源调度策略. 计算机工程, 2021, 47(2): 32-38. DOI:10.19678/j.issn.1000-3428.0058047 |
[19] |
谢晓兰, 张征征, 王建伟, 等. 基于三次指数平滑法和时间卷积网络的云资源预测模型. 通信学报, 2019, 40(8): 143-150. DOI:10.11959/j.issn.1000-436x.2019172 |
[20] |
杨凯琪, 姚培, 赵玉龙, 等. 面向异构容器云的应用迁移方法. 计算机工程, 2019, 45(8): 42-47. DOI:10.19678/j.issn.1000-3428.0051519 |
[21] |
Shamim SI, Bhuiyan FA, Rahman A. XI commandments of Kubernetes security: A systematization of knowledge related to Kubernetes security practices. Proceedings of the 2020 IEEE Secure Development. Atlanta: IEEE, 2020. 58–64.
|
[22] |
Rattihalli G, Govindaraju M, Lu H, et al. Exploring potential for non-disruptive vertical auto scaling and resource estimation in Kubernetes. Proceedings of the 12th IEEE International Conference on Cloud Computing. Milan: IEEE, 2019. 33–40.
|
[23] |
Bella MRM, Data M, Yahya W. Web server load balancing based on memory utilization using Docker Swarm. Proceedings of the 2018 International Conference on Sustainable Information Engineering and Technology. Malang: IEEE, 2018. 220–223.
|
[24] |
林昊. 基于改进混合蛙跳算法的Swarm集群调度策略研究[硕士学位论文]. 广州: 广东工业大学, 2020. 8.
|
[25] |
王昭, 邓浩江, 胡琳琳, 等. 一种多服务端HTML5 Web Worker迁移系统设计与实现. 计算机应用与软件, 2018, 35(9): 27-31, 43. DOI:10.3969/j.issn.1000-386x.2018.09.005 |
[26] |
卜尧, 吴斌, 陈玉峰, 等. BDAP——一个基于Spark的数据挖掘工具平台. 中国科学技术大学学报, 2017, 47(4): 358-368. DOI:10.3969/j.issn.0253-2778.2017.04.011 |
[27] |
Cinque M, Corte RD, Pecchia A. Microservices monitoring with event logs and black box execution tracing. IEEE Transactions on Services Computing, 2022, 15(1): 294-307. DOI:10.1109/TSC.2019.2940009 |
[28] |
许源佳, 吴恒, 杨晨, 等. 面向状态可变数据流的集群调度综述. 计算机学报, 2022, 45(5): 973-992. |
[29] |
Marathe N, Gandhi A, Shah JM. Docker Swarm and Kubernetes in cloud computing environment. Proceedings of the 3rd International Conference on Trends in Electronics and Informatics. Tirunelveli: IEEE, 2019. 179–184.
|
[30] |
游贵荣, 陈杰, 乐宁莉. 轻量级网络安全攻防PaaS平台研究与实现. 实验室研究与探索, 2020, 39(12): 129-133, 162. DOI:10.3969/j.issn.1006-7167.2020.12.026 |
[31] |
Kang B, Jeong J, Choo H. Docker Swarm and Kubernetes containers for smart home gateway. IT Professional, 2021, 23(4): 75-80. DOI:10.1109/MITP.2020.3034116 |