容器-3-Cgroups的计划经济

Cgroups-限制可用资源

如果应用优化得不够好,直接把CPU或内存吃光也完全不是新鲜事。但我们肯定不能容忍容器无限制地挤占宿主机的资源,甚至把宿主机搞down掉。
所以我们可以通过Linux的Cgroups(Control Groups,控制组)对某个容器可以使用的各种硬件资源设置配额。

cgroup

根据wiki,Cgroups的功能包括:

  • 资源限制(Resource Limitation):进程组使用的内存的上限,也包括文件系统与物理内存交换用的页缓存(Page Cache)
  • 优先级分配(Prioritization):控制分配的CPU时间片数量及硬盘IO吞吐,实际上就相当于控制了进程运行的优先级
  • 资源统计(Accounting):统计资源使用量,如CPU使用时长、内存用量等,主要用于计费
  • 进程控制(Control):执行挂起、恢复进程组的操作

Cgroups的设置一般分为三个主要步骤:

  1. 创建cgroup
  2. 设置cgroup配额(将cpu/内存等各种子系统添加到该cgroup中)
  3. 将进程添加为cgroup的任务

Docker容器在启动时候会动态创建Cgroup,并在容器终止的时候删除。

容器的Cgroups相比虚拟机的优势主要在两方面:

  • 资源利用率
  • 性能损耗
    首先从资源利用率方面来说,一部分虚拟化技术只能静态分配资源,一台物理机上也装不了几个虚拟机。如果虚拟机闲置,分配给虚拟机的硬件资源也无法分配给其他虚拟机。也有一部分虚拟化技术可以实现一定程度上的“动态分配”。但这种“动态分配”有各种各样的缺陷,比如回收速度慢(Balloon技术),影响性能(内存压缩),或即慢又影响性能(透明页共享)。
    虚拟化技术也有很大的性能损耗。例如为了虚拟CPU,Hypervisor需要为每个虚拟的CPU创建一个数据结构,以模拟CPU的寄存器;为了虚拟内存,需要通过一个shadow page table,在物理内存和虚拟机内存之间增加一层虚拟的物理内存。而且操作系统本身的资源损耗是无论如何无法避免的。

相比之下,Cgroups虽然也会带来一些性能损耗。但通过一些测试可以发现,相比虚拟机接近50%的损耗,容器的性能损耗微乎其微(CPU密集场景下是5%)。此外Docker还节省了操作系统运行的资源损耗。此外,容器在启动时间上也有巨大的优势。

当然Cgroups也有自己的问题。比如高压力下容器与容器之间,以及容器和操作系统之间抢占资源的问题。有兴趣的话可以参考这篇,或者自己做个实验试一下。

Docker原理总结

从以上的介绍你可以看到,其实Docker engine并没有使用什么特别深奥的原理。甚至你可以通过shell脚本自己来实现一个docker engine(事实上github上就有这么一个开源项目,使用100行bash实现了精简版的docker)。所以事实上真正Docker的架构类似下图:
容器-虚拟机vs容器(真)

常见问题

建议在物理机上还是虚拟机上运行Docker?

当我要开始搭容器测试环境的时候,最纠结的其实是到底该搭在虚拟机上还是物理机上。万一搞错了还要铲掉重来。
按照我的经验,先到官方文档里找最佳实践,但翻了半天也没找到。
在了解了原理后,自然会得出结论:物理机上部署Docker的性能约等于直接在物理机上部署应用。所以物理机上部署肯定有性能和延迟优势。
不过Docker的博客上也提到了虚拟机化的几个好处:

  • 方便上云
  • 可以利用成熟且已有的虚拟化经验,例如:灾备,监控和自动化
  • 节省虚拟机License

国内也有人测试过具体的性能差异,IO和CPU方面物理机快25%-30%。
运行Docker:物理机vs虚拟机,五方面详细对比理

在我们的场景下,性能远不及其他几个优点重要。于是最终还是选择了虚拟机上部署。
容器-虚拟机上部署docker

容器的操作系统是否能和宿主机不一样?

可以分成三种情况讨论:

  • 容器的操作系统版本比宿主机高或低
  • 操作系统是不同发行版本的(例如宿主机是CentOS,容器是Ubuntu)
  • 操作系统完全不同(例如宿主机是Windows,容器是CentOS)

其实1和2都差不多。不同版本和发行版本的Linux内核的差别不那么大。容器只与主机共享一个内核。
操作系统=内核+文件系统/库
镜像=文件系统/库
这也是为什么不能在Linux宿主机上运行Windows容器。内核根本就不一样。

但为什么我们可以在Windows 10上运行容器?这多亏了Hyper-V。(回想起来Hyper-V最初发布的时候还是在微软内部看到消息并试用的。。。)
Hyper-V的技术细节就不多提了。与Docker相关的可以参见这张架构图:
容器-虚拟机上部署docker
与之原理类似,MacOS上运行Docker是通过虚拟化技术xhyve或者virtualbox来实现。

更多可以参见这篇:
Understanding Docker “Container Host” vs. “Container OS” for Linux and Windows Containers

Docker全系列

Namespace:楚门的世界
Docker存储引擎
Cgroups的计划经济
Docker的意义

本文永久链接 [ https://galaxyyao.github.io/2019/05/25/容器-3-Cgroups的计划经济/ ]