Enabling Docker Containers for High-Performance and Many-Task Computing
Introduction
介绍了容器化部署应用的益处,并且想要把容器部署到生产环境的队列系统中(queuing system)。难点有两点:
1. Docker的默认配置是将容器作为root用户运行。要使容器进程具有用户权限,并使系统管理员记录谁在运行什么,容器进程必须作为提交用户运行。
2. 其次,在作业中运行的Docker容器的资源消耗(CPU和内存)必须受到队列系统为这个特定作业设置的资源消耗限制的限制。
关于queuing system可以参照What Is a Queuing System?
本文介绍了socker,这是一种用于在Slurm和类似的排队系统(如moa和PBS)上运行Docker容器的安全包装器。Socker是由USIT大学信息技术中心的研究计算小组测试的。Socker不能代替Docker引擎来运行和管理容器。它将Docker容器作为提交用户运行,并将运行容器的成员身份作为HPC作业的一部分在队列系统分配给该作业的cgroups中运行。已经对socker进行了基本测试,以便在Slurm集群上运行MPI作业。Socker还测试了在互连集群系统上运行容器作业的多任务计算(MTC)。Socker已被证明是安全的,而且几乎不引入任何计算开销。Socker的进一步开发正在进行中,现在可以在github上获得。
Related Work
Swarm提供了很好的可扩展性,但是它的安全性很差。此外,调度和资源管理过于基础,这使得它不足以在生产环境中的大型HPC系统中使用户。谷歌的Kubernetes是Docker Swarm的竞争对手。除了自修复之外,它还提供了对运行容器的更多控制,但是在调度和资源管理方面仍然很差。此外,它的安装和维护非常复杂。Docker Swarm和Kubernetes的一个常见问题是它们都被设计成独立的队列系统,而不是运行器(runners )或包装器(wrappers)。因此,不能将Swarm或Kubernetes插入已经安装的队列系统(如TORQUE或Slurm),而必须替换整个队列系统。HTCondor[13]最近通过Docker universe[14]为Docker提供了支持。HTCondor对于HPC系统更值得信赖,因为它是一个众所周知的、经过良好测试的HPC和HTC平台。我们已经在一个测试环境中使用HTCondor部署了Docker,并且该实现被证明是非常友好的。但它缺乏灵活性,例如在不断增长的挂载数据卷方面。此外,它对正在运行的容器的资源使用没有任何控制。Singularity[15]是一个在HPC平台上运行Linux容器的引擎。它安装在生产中的许多HPC集群上。与Docker分层容器不同,Singularity容器是轻量级的。与Docker分层容器不同。我们已经在Abel上测试了singularity容器,结果证明它们比类似的Docker容器更快、更节省资源。singularity的问题在于,它在我们所服务的科学界中仍然没有Docker那么受欢迎,Singularity支持Docker镜像到Singularity镜像的转换。Shifter[16]是一个在Slurm上运行Docker容器的平台。Shifter是一个在Slurm上运行Docker容器的平台。它由国家能源研究科学计算中心(NERSC)开发,并部署在Cray超级计算机的Slurm集群上。Shifter并没有遵循Docker标准,也没有使用Docker引擎来运行和管理容器。它有自己的镜像格式,Docker镜像和vm都转换为这种格式。Docker引擎被镜像管理器(image manager)替代,用于管理新生成的映像。在此之前,NERSC引入了MyDock[16],它是一个Docker的包装器,以用户的身份强制访问容器。MyDock没有提供一个解决方案来强制在一个正在运行的容器中包含与Slurm作业相关的cgroups。此外,shifter和myDock都通过首先作为root用户运行并挂载来强制用户访问每个容器中的/etc/passwd和/etc/group,然后让用户以自己的身份访问容器。Socker采用了一种更安全、更简单的策略,从一开始就以用户身份运行容器,避免了可能导致以root用户身份运行容器的任何威胁。与singularity类似,shifter还不成熟,并且依赖自己的图像格式和引擎,因此对于大型生产系统来说并不可靠。它将整个开发和维护责任放在了开发团队身上。开发一个使用Docker引擎的runner更现实,因为Docker是一个众所周知的维护平台,而且在全世界有数百万用户和许多IT研究支持中心。
Docker
Docker是一个新的工具,它可以在Linux容器中自动部署应用程序。它提供了操作系统级虚拟化的抽象层和自动化。Docker本身并不是一项新技术,但它是一个高级工具,最初构建在LXC [17] Linux containers API之上,并提供附加功能。Docker容器由Docker引擎执行和控制,这与vm的管理程序不同。因为它不包括一个完整的客户访问的操作系统(guest OS)
Docker容器比VM更小,启动速度更快。Docker容器装载一个单独的根文件系统,其中包含类unix操作系统的目录结构,以及运行用户应用程序所需的所有配置文件、二进制文件和库。包含引导加载程序和内核的引导文件系统不包含在容器中,容器使用主机引导文件系统[18]。当Docker挂载容器根文件系统时,它以只读方式启动,就像传统的Linux引导一样,但是它没有将文件系统更改为读写模式,而是使用union mount[19]在只读文件系统上添加一个读写文件系统。也可以将多个只读文件系统堆叠在一起。每个文件系统都可以看作是一个[20]层。
由于不是所有的文件系统都是分层的,例如Ext, Docker在主机文件系统(在Docker术语中称为备份文件系统)的顶部构建分层的文件系统。Docker支持不同层次的文件系统驱动程序,例如OverlayFS、AUFS和BTRFS。一个典型的设置是在Ext4支持文件系统的顶部使用具有Overlayfs的Docker。
The HPC infrastructure
有Abel和Colossus两种架构
Motivation
对管理员管理应用程序很有益
Socker
Socker是一个包装器,用于在HPC作业中安全地运行Docker容器。它主要用于使Slurm集群(Abel和Colossus)的用户能够运行Docker支持的作业。因为我们的计算节点运行的是CentOS 6.7,而标准内核是2.6,所以Socker被设计为能够与Docker 1.7一起工作(因为新Docker版本不再支持CentOS 6)。它还可以处理较新的Docker版本2。socker主要提供两个函数:首先,作为提交作业的用户运行每个容器进程,以便使容器受用户能力的限制。其次,通过作业的排队系统设置的限制来限制作业内部调用的任何容器的资源使用。Slurm(最近还有Moab)使用cgroups来控制作业资源消耗。Socker的设计也很简单和轻便。图1显示了Socker的结构。用户分为系统管理员和普通用户。系统管理员被赋予运行docker命令的特权,即docker组的成员。普通用户只能通过Socker运行Docker。Socker由两个可执行文件组成:
socker二进制文件和socker核心脚本(当前为bash)。socker二进制文件是用户在Slurm作业脚本中运行的入口点。Socker二进制执行以下操作:
- 收集图像名称和要执行的命令。这些参数由用户作为命令行参数提供。
- 收集用户信息,即UID和GID。
- 将UID更改为0,即以root身份运行以下命令。
- 调用socker core,将之前收集的值作为参数传递。
要使socker二进制文件可被普通用户执行,同时以root身份运行命令,需要配置如下:
- 启用所有setuid: chmod +s socker。这将使它可执行的每个人,并给予它的权限,以设置用户ID,如root。
- socker二进制文件必须是“二进制文件”,而不是脚本(以#!开头),因为出于安全原因,大多数Linux系统都忽略了上面的脚本配置。
Socker二进制文件在内部运行Socker core,它只能由root用户执行。socker核心执行主要的socker功能:
1)以用户身份运行Docker镜像,使用Docker run -u UID:GID,从容器中分离。
2)在Slurm为作业创建的cgroups中强制容器流程的成员关系。
算法1描述了Slurm部署的整个Socker功能。该功能分为二进制和bash脚本,以支持灵活性。也许对于另一个Slurm集群,系统管理员更喜欢使用他们自己的,例如Python脚本,作为socker核心来支持不同的设置
给出一个使用socker在Slurm脚本中运行并行作业的示例。
Performance Evaluation For HPC
为了在我们的主集群上启用Socker,在计算节点上安装了Abel、Docker 1.7。目前Docker不支持主机之间共享映像存储库,因此每个计算节点都有自己的本地映像存储库(分层文件系统)。为了避免将映像存储在计算节点的本地磁盘上,所有映像存储库都分配到了共享的BeeGFS文件系统上。由于Docker目前不支持将BeeGFS作为备份文件系统,所以我们将Ext4映像作为环回设备挂载到计算节点上,作为Docker映像的存储库。另一个问题是,我们不能依赖于计算节点从Docker集线器中提取图像,因为这可能非常慢,特别是对于具有很多层的图像,此外还需要所有计算节点都具有Internet访问(这对于Colossus是不可能的)。为了解决这个问题,我们安装了一个本地Docker注册表。根据用户请求,从Docker中心提取图像并推送到本地注册表。系统布局如图2所示
剩下部分是针对性能的测量,因为不深入研究相关内容,故不详细列出来了。
Conclusions
对于用户和系统管理员来说,Linux容器是一种有用的技术,它支持可移植性,并且比传统的vm开销更少。Docker是一个用于创建和管理容器的用户友好平台,全世界有数百万用户使用它。为科学计算在HPC集群上启用Docker容器是许多研究人员的需求。Socker是在Slurm上运行Docker容器的包装器。Socker被设计为简单和可移植的,因此它可以用于任何Slurm集群。Socker以用户身份安全地运行容器,并通过Slurm分配的资源数量强制限制正在运行的容器的资源使用量。socker几乎不引入任何额外的计算开销。这已经在高性能计算和小型MTC上进行了测试。我们计划使插槽排队系统独立。它还计划使用runC[32]代替docker run来运行容器,因为docker引擎本身现在是基于runC的。